Repository: argotorg/solidity Branch: develop Commit: 64bba94186a2 Files: 11533 Total size: 18.0 MB Directory structure: gitextract_thz9iz3f/ ├── .circleci/ │ ├── README.md │ ├── cln-asan.supp │ ├── compare_bytecode_reports.sh │ ├── config.yml │ ├── osx_install_dependencies.sh │ ├── parallel_bytecode_report.sh │ ├── parallel_cli_tests.py │ ├── soltest.ps1 │ ├── soltest.sh │ └── soltest_all.sh ├── .clang-format ├── .codespellrc ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── config.yml │ │ ├── documentation_issue.md │ │ └── feature_request.md │ └── workflows/ │ ├── buildpack-deps.yml │ ├── stale.yml │ └── welcome-external-pr.yml ├── .gitignore ├── .gitmodules ├── .readthedocs.yml ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CODING_STYLE.md ├── CONTRIBUTING.md ├── Changelog.md ├── LICENSE.txt ├── README.md ├── ReleaseChecklist.md ├── ReviewChecklist.md ├── SECURITY.md ├── cmake/ │ ├── EthBuildInfo.cmake │ ├── EthCcache.cmake │ ├── EthCheckCXXCompilerFlag.cmake │ ├── EthCompilerSettings.cmake │ ├── EthDependencies.cmake │ ├── EthOptions.cmake │ ├── EthPolicy.cmake │ ├── EthToolchains.cmake │ ├── EthUtils.cmake │ ├── FindCLN.cmake │ ├── FindGMP.cmake │ ├── FindZ3.cmake │ ├── fmtlib.cmake │ ├── nlohmann-json.cmake │ ├── range-v3.cmake │ ├── scripts/ │ │ └── buildinfo.cmake │ ├── submodules.cmake │ ├── templates/ │ │ ├── BuildInfo.h.in │ │ └── license.h.in │ └── toolchains/ │ ├── default.cmake │ ├── libfuzzer.cmake │ └── ossfuzz.cmake ├── docs/ │ ├── 050-breaking-changes.rst │ ├── 060-breaking-changes.rst │ ├── 070-breaking-changes.rst │ ├── 080-breaking-changes.rst │ ├── Makefile │ ├── README.md │ ├── _static/ │ │ ├── css/ │ │ │ ├── custom-dark.css │ │ │ ├── custom.css │ │ │ ├── fonts.css │ │ │ ├── pygments.css │ │ │ └── toggle.css │ │ └── js/ │ │ ├── constants.js │ │ ├── initialize.js │ │ └── toggle.js │ ├── _templates/ │ │ ├── footer.html │ │ ├── layout.html │ │ └── versions.html │ ├── abi-spec.rst │ ├── analysing-compilation-output.rst │ ├── assembly.rst │ ├── brand-guide.rst │ ├── bugs.json │ ├── bugs.rst │ ├── bugs_by_version.json │ ├── cheatsheet.rst │ ├── common-patterns.rst │ ├── conf.py │ ├── contracts/ │ │ ├── abstract-contracts.rst │ │ ├── constant-state-variables.rst │ │ ├── creating-contracts.rst │ │ ├── custom-storage-layout.rst │ │ ├── errors.rst │ │ ├── events.rst │ │ ├── function-modifiers.rst │ │ ├── functions.rst │ │ ├── inheritance.rst │ │ ├── interfaces.rst │ │ ├── libraries.rst │ │ ├── transient-storage.rst │ │ ├── using-for.rst │ │ └── visibility-and-getters.rst │ ├── contracts.rst │ ├── contributing.rst │ ├── control-structures.rst │ ├── credits-and-attribution.rst │ ├── docs.sh │ ├── examples/ │ │ ├── blind-auction.rst │ │ ├── micropayment.rst │ │ ├── modular.rst │ │ ├── safe-remote.rst │ │ └── voting.rst │ ├── ext/ │ │ ├── html_extra_template_renderer.py │ │ └── remix_code_links.py │ ├── grammar/ │ │ ├── SolidityLexer.g4 │ │ └── SolidityParser.g4 │ ├── grammar.rst │ ├── index.rst │ ├── installing-solidity.rst │ ├── internals/ │ │ ├── layout_in_calldata.rst │ │ ├── layout_in_memory.rst │ │ ├── layout_in_storage.rst │ │ ├── optimizer.rst │ │ ├── source_mappings.rst │ │ └── variable_cleanup.rst │ ├── introduction-to-smart-contracts.rst │ ├── ir-breaking-changes.rst │ ├── language-influences.rst │ ├── layout-of-source-files.rst │ ├── make.bat │ ├── metadata.rst │ ├── natspec-format.rst │ ├── path-resolution.rst │ ├── requirements.txt │ ├── resources.rst │ ├── robots.txt.template │ ├── security-considerations.rst │ ├── smtchecker.rst │ ├── solidity-by-example.rst │ ├── structure-of-a-contract.rst │ ├── style-guide.rst │ ├── types/ │ │ ├── conversion.rst │ │ ├── mapping-types.rst │ │ ├── operator-precedence-table.rst │ │ ├── operators.rst │ │ ├── reference-types.rst │ │ └── value-types.rst │ ├── types.rst │ ├── units-and-global-variables.rst │ ├── using-the-compiler.rst │ └── yul.rst ├── funding.json ├── libevmasm/ │ ├── AbstractAssemblyStack.h │ ├── Assembly.cpp │ ├── Assembly.h │ ├── AssemblyItem.cpp │ ├── AssemblyItem.h │ ├── BlockDeduplicator.cpp │ ├── BlockDeduplicator.h │ ├── CMakeLists.txt │ ├── CommonSubexpressionEliminator.cpp │ ├── CommonSubexpressionEliminator.h │ ├── ConstantOptimiser.cpp │ ├── ConstantOptimiser.h │ ├── ControlFlowGraph.cpp │ ├── ControlFlowGraph.h │ ├── Disassemble.cpp │ ├── Disassemble.h │ ├── EVMAssemblyStack.cpp │ ├── EVMAssemblyStack.h │ ├── Ethdebug.cpp │ ├── Ethdebug.h │ ├── EthdebugSchema.cpp │ ├── EthdebugSchema.h │ ├── Exceptions.h │ ├── ExpressionClasses.cpp │ ├── ExpressionClasses.h │ ├── GasMeter.cpp │ ├── GasMeter.h │ ├── Inliner.cpp │ ├── Inliner.h │ ├── Instruction.cpp │ ├── Instruction.h │ ├── JumpdestRemover.cpp │ ├── JumpdestRemover.h │ ├── KnownState.cpp │ ├── KnownState.h │ ├── LinkerObject.cpp │ ├── LinkerObject.h │ ├── PathGasMeter.cpp │ ├── PathGasMeter.h │ ├── PeepholeOptimiser.cpp │ ├── PeepholeOptimiser.h │ ├── RuleList.h │ ├── SemanticInformation.cpp │ ├── SemanticInformation.h │ ├── SimplificationRule.h │ ├── SimplificationRules.cpp │ ├── SimplificationRules.h │ └── SubAssemblyID.h ├── liblangutil/ │ ├── CMakeLists.txt │ ├── CharStream.cpp │ ├── CharStream.h │ ├── CharStreamProvider.h │ ├── Common.h │ ├── DebugData.h │ ├── DebugInfoSelection.cpp │ ├── DebugInfoSelection.h │ ├── EVMVersion.cpp │ ├── EVMVersion.h │ ├── ErrorReporter.cpp │ ├── ErrorReporter.h │ ├── Exceptions.cpp │ ├── Exceptions.h │ ├── ParserBase.cpp │ ├── ParserBase.h │ ├── Scanner.cpp │ ├── Scanner.h │ ├── SemVerHandler.cpp │ ├── SemVerHandler.h │ ├── SourceLocation.cpp │ ├── SourceLocation.h │ ├── SourceReferenceExtractor.cpp │ ├── SourceReferenceExtractor.h │ ├── SourceReferenceFormatter.cpp │ ├── SourceReferenceFormatter.h │ ├── Token.cpp │ ├── Token.h │ └── UniqueErrorReporter.h ├── libsmtutil/ │ ├── BMCSolverInterface.h │ ├── CHCSmtLib2Interface.cpp │ ├── CHCSmtLib2Interface.h │ ├── CHCSolverInterface.h │ ├── CMakeLists.txt │ ├── Exceptions.h │ ├── Helpers.h │ ├── SMTLib2Context.cpp │ ├── SMTLib2Context.h │ ├── SMTLib2Interface.cpp │ ├── SMTLib2Interface.h │ ├── SMTLib2Parser.cpp │ ├── SMTLib2Parser.h │ ├── SMTPortfolio.cpp │ ├── SMTPortfolio.h │ ├── SolverInterface.h │ ├── Sorts.cpp │ └── Sorts.h ├── libsolc/ │ ├── CMakeLists.txt │ ├── libsolc.cpp │ └── libsolc.h ├── libsolidity/ │ ├── CMakeLists.txt │ ├── analysis/ │ │ ├── ConstantEvaluator.cpp │ │ ├── ConstantEvaluator.h │ │ ├── ContractLevelChecker.cpp │ │ ├── ContractLevelChecker.h │ │ ├── ControlFlowAnalyzer.cpp │ │ ├── ControlFlowAnalyzer.h │ │ ├── ControlFlowBuilder.cpp │ │ ├── ControlFlowBuilder.h │ │ ├── ControlFlowGraph.cpp │ │ ├── ControlFlowGraph.h │ │ ├── ControlFlowRevertPruner.cpp │ │ ├── ControlFlowRevertPruner.h │ │ ├── DeclarationContainer.cpp │ │ ├── DeclarationContainer.h │ │ ├── DeclarationTypeChecker.cpp │ │ ├── DeclarationTypeChecker.h │ │ ├── DocStringAnalyser.cpp │ │ ├── DocStringAnalyser.h │ │ ├── DocStringTagParser.cpp │ │ ├── DocStringTagParser.h │ │ ├── FunctionCallGraph.cpp │ │ ├── FunctionCallGraph.h │ │ ├── GlobalContext.cpp │ │ ├── GlobalContext.h │ │ ├── ImmutableValidator.cpp │ │ ├── ImmutableValidator.h │ │ ├── NameAndTypeResolver.cpp │ │ ├── NameAndTypeResolver.h │ │ ├── OverrideChecker.cpp │ │ ├── OverrideChecker.h │ │ ├── PostTypeChecker.cpp │ │ ├── PostTypeChecker.h │ │ ├── PostTypeContractLevelChecker.cpp │ │ ├── PostTypeContractLevelChecker.h │ │ ├── ReferencesResolver.cpp │ │ ├── ReferencesResolver.h │ │ ├── Scoper.cpp │ │ ├── Scoper.h │ │ ├── StaticAnalyzer.cpp │ │ ├── StaticAnalyzer.h │ │ ├── SyntaxChecker.cpp │ │ ├── SyntaxChecker.h │ │ ├── TypeChecker.cpp │ │ ├── TypeChecker.h │ │ ├── ViewPureChecker.cpp │ │ └── ViewPureChecker.h │ ├── ast/ │ │ ├── AST.cpp │ │ ├── AST.h │ │ ├── ASTAnnotations.cpp │ │ ├── ASTAnnotations.h │ │ ├── ASTEnums.h │ │ ├── ASTForward.h │ │ ├── ASTJsonExporter.cpp │ │ ├── ASTJsonExporter.h │ │ ├── ASTJsonImporter.cpp │ │ ├── ASTJsonImporter.h │ │ ├── ASTUtils.cpp │ │ ├── ASTUtils.h │ │ ├── ASTVisitor.h │ │ ├── AST_accept.h │ │ ├── CallGraph.cpp │ │ ├── CallGraph.h │ │ ├── ExperimentalFeatures.h │ │ ├── TypeProvider.cpp │ │ ├── TypeProvider.h │ │ ├── Types.cpp │ │ ├── Types.h │ │ └── UserDefinableOperators.h │ ├── codegen/ │ │ ├── ABIFunctions.cpp │ │ ├── ABIFunctions.h │ │ ├── ArrayUtils.cpp │ │ ├── ArrayUtils.h │ │ ├── Compiler.cpp │ │ ├── Compiler.h │ │ ├── CompilerContext.cpp │ │ ├── CompilerContext.h │ │ ├── CompilerUtils.cpp │ │ ├── CompilerUtils.h │ │ ├── ContractCompiler.cpp │ │ ├── ContractCompiler.h │ │ ├── ExpressionCompiler.cpp │ │ ├── ExpressionCompiler.h │ │ ├── LValue.cpp │ │ ├── LValue.h │ │ ├── MultiUseYulFunctionCollector.cpp │ │ ├── MultiUseYulFunctionCollector.h │ │ ├── ReturnInfo.cpp │ │ ├── ReturnInfo.h │ │ ├── YulUtilFunctions.cpp │ │ ├── YulUtilFunctions.h │ │ └── ir/ │ │ ├── Common.cpp │ │ ├── Common.h │ │ ├── IRGenerationContext.cpp │ │ ├── IRGenerationContext.h │ │ ├── IRGenerator.cpp │ │ ├── IRGenerator.h │ │ ├── IRGeneratorForStatements.cpp │ │ ├── IRGeneratorForStatements.h │ │ ├── IRLValue.h │ │ ├── IRVariable.cpp │ │ ├── IRVariable.h │ │ └── README.md │ ├── experimental/ │ │ ├── analysis/ │ │ │ ├── Analysis.cpp │ │ │ ├── Analysis.h │ │ │ ├── DebugWarner.cpp │ │ │ ├── DebugWarner.h │ │ │ ├── FunctionDependencyAnalysis.cpp │ │ │ ├── FunctionDependencyAnalysis.h │ │ │ ├── SyntaxRestrictor.cpp │ │ │ ├── SyntaxRestrictor.h │ │ │ ├── TypeClassRegistration.cpp │ │ │ ├── TypeClassRegistration.h │ │ │ ├── TypeInference.cpp │ │ │ ├── TypeInference.h │ │ │ ├── TypeRegistration.cpp │ │ │ └── TypeRegistration.h │ │ ├── ast/ │ │ │ ├── FunctionCallGraph.h │ │ │ ├── Type.cpp │ │ │ ├── Type.h │ │ │ ├── TypeSystem.cpp │ │ │ ├── TypeSystem.h │ │ │ ├── TypeSystemHelper.cpp │ │ │ └── TypeSystemHelper.h │ │ └── codegen/ │ │ ├── Common.cpp │ │ ├── Common.h │ │ ├── IRGenerationContext.h │ │ ├── IRGenerator.cpp │ │ ├── IRGenerator.h │ │ ├── IRGeneratorForStatements.cpp │ │ └── IRGeneratorForStatements.h │ ├── formal/ │ │ ├── ArraySlicePredicate.cpp │ │ ├── ArraySlicePredicate.h │ │ ├── BMC.cpp │ │ ├── BMC.h │ │ ├── CHC.cpp │ │ ├── CHC.h │ │ ├── Cvc5SMTLib2Interface.cpp │ │ ├── Cvc5SMTLib2Interface.h │ │ ├── EldaricaCHCSmtLib2Interface.cpp │ │ ├── EldaricaCHCSmtLib2Interface.h │ │ ├── EncodingContext.cpp │ │ ├── EncodingContext.h │ │ ├── ExpressionFormatter.cpp │ │ ├── ExpressionFormatter.h │ │ ├── ModelChecker.cpp │ │ ├── ModelChecker.h │ │ ├── ModelCheckerSettings.cpp │ │ ├── ModelCheckerSettings.h │ │ ├── Predicate.cpp │ │ ├── Predicate.h │ │ ├── PredicateInstance.cpp │ │ ├── PredicateInstance.h │ │ ├── PredicateSort.cpp │ │ ├── PredicateSort.h │ │ ├── SMTEncoder.cpp │ │ ├── SMTEncoder.h │ │ ├── SSAVariable.cpp │ │ ├── SSAVariable.h │ │ ├── SymbolicState.cpp │ │ ├── SymbolicState.h │ │ ├── SymbolicTypes.cpp │ │ ├── SymbolicTypes.h │ │ ├── SymbolicVariables.cpp │ │ ├── SymbolicVariables.h │ │ ├── Z3CHCSmtLib2Interface.cpp │ │ ├── Z3CHCSmtLib2Interface.h │ │ ├── Z3SMTLib2Interface.cpp │ │ └── Z3SMTLib2Interface.h │ ├── interface/ │ │ ├── ABI.cpp │ │ ├── ABI.h │ │ ├── CompilerStack.cpp │ │ ├── CompilerStack.h │ │ ├── DebugSettings.h │ │ ├── FileReader.cpp │ │ ├── FileReader.h │ │ ├── GasEstimator.cpp │ │ ├── GasEstimator.h │ │ ├── ImportRemapper.cpp │ │ ├── ImportRemapper.h │ │ ├── Natspec.cpp │ │ ├── Natspec.h │ │ ├── OptimiserSettings.h │ │ ├── ReadFile.h │ │ ├── SMTSolverCommand.cpp │ │ ├── SMTSolverCommand.h │ │ ├── StandardCompiler.cpp │ │ ├── StandardCompiler.h │ │ ├── StorageLayout.cpp │ │ ├── StorageLayout.h │ │ ├── UniversalCallback.h │ │ ├── Version.cpp │ │ └── Version.h │ ├── lsp/ │ │ ├── DocumentHoverHandler.cpp │ │ ├── DocumentHoverHandler.h │ │ ├── FileRepository.cpp │ │ ├── FileRepository.h │ │ ├── GotoDefinition.cpp │ │ ├── GotoDefinition.h │ │ ├── HandlerBase.cpp │ │ ├── HandlerBase.h │ │ ├── LanguageServer.cpp │ │ ├── LanguageServer.h │ │ ├── RenameSymbol.cpp │ │ ├── RenameSymbol.h │ │ ├── SemanticTokensBuilder.cpp │ │ ├── SemanticTokensBuilder.h │ │ ├── Transport.cpp │ │ ├── Transport.h │ │ ├── Utils.cpp │ │ └── Utils.h │ └── parsing/ │ ├── DocStringParser.cpp │ ├── DocStringParser.h │ ├── Parser.cpp │ ├── Parser.h │ └── Token.h ├── libsolutil/ │ ├── Algorithms.h │ ├── AnsiColorized.h │ ├── Assertions.h │ ├── CMakeLists.txt │ ├── Common.h │ ├── CommonData.cpp │ ├── CommonData.h │ ├── CommonIO.cpp │ ├── CommonIO.h │ ├── DisjointSet.cpp │ ├── DisjointSet.h │ ├── DominatorFinder.h │ ├── ErrorCodes.h │ ├── Exceptions.cpp │ ├── Exceptions.h │ ├── FixedHash.h │ ├── FunctionSelector.h │ ├── IpfsHash.cpp │ ├── IpfsHash.h │ ├── JSON.cpp │ ├── JSON.h │ ├── Keccak256.cpp │ ├── Keccak256.h │ ├── LEB128.h │ ├── LazyInit.h │ ├── Numeric.cpp │ ├── Numeric.h │ ├── Profiler.cpp │ ├── Profiler.h │ ├── Result.h │ ├── SetOnce.h │ ├── StackTooDeepString.h │ ├── StringUtils.cpp │ ├── StringUtils.h │ ├── SwarmHash.cpp │ ├── SwarmHash.h │ ├── TemporaryDirectory.cpp │ ├── TemporaryDirectory.h │ ├── UTF8.cpp │ ├── UTF8.h │ ├── Views.h │ ├── Visitor.h │ ├── Whiskers.cpp │ ├── Whiskers.h │ ├── picosha2.h │ └── vector_ref.h ├── libstdlib/ │ ├── CMakeLists.txt │ ├── src/ │ │ └── stub.sol │ ├── stdlib.h.in │ └── stdlib.src.h.in ├── libyul/ │ ├── AST.cpp │ ├── AST.h │ ├── ASTForward.h │ ├── ASTLabelRegistry.cpp │ ├── ASTLabelRegistry.h │ ├── AsmAnalysis.cpp │ ├── AsmAnalysis.h │ ├── AsmAnalysisInfo.h │ ├── AsmJsonConverter.cpp │ ├── AsmJsonConverter.h │ ├── AsmJsonImporter.cpp │ ├── AsmJsonImporter.h │ ├── AsmParser.cpp │ ├── AsmParser.h │ ├── AsmPrinter.cpp │ ├── AsmPrinter.h │ ├── Builtins.h │ ├── CMakeLists.txt │ ├── CompilabilityChecker.cpp │ ├── CompilabilityChecker.h │ ├── ControlFlowSideEffects.h │ ├── ControlFlowSideEffectsCollector.cpp │ ├── ControlFlowSideEffectsCollector.h │ ├── Dialect.cpp │ ├── Dialect.h │ ├── Exceptions.h │ ├── FunctionReferenceResolver.cpp │ ├── FunctionReferenceResolver.h │ ├── Object.cpp │ ├── Object.h │ ├── ObjectOptimizer.cpp │ ├── ObjectOptimizer.h │ ├── ObjectParser.cpp │ ├── ObjectParser.h │ ├── Scope.cpp │ ├── Scope.h │ ├── ScopeFiller.cpp │ ├── ScopeFiller.h │ ├── SideEffects.h │ ├── Utilities.cpp │ ├── Utilities.h │ ├── YulName.h │ ├── YulStack.cpp │ ├── YulStack.h │ ├── YulString.h │ ├── backends/ │ │ └── evm/ │ │ ├── AbstractAssembly.h │ │ ├── AsmCodeGen.cpp │ │ ├── AsmCodeGen.h │ │ ├── ConstantOptimiser.cpp │ │ ├── ConstantOptimiser.h │ │ ├── ControlFlowGraph.h │ │ ├── ControlFlowGraphBuilder.cpp │ │ ├── ControlFlowGraphBuilder.h │ │ ├── EVMBuiltins.cpp │ │ ├── EVMBuiltins.h │ │ ├── EVMCodeTransform.cpp │ │ ├── EVMCodeTransform.h │ │ ├── EVMDialect.cpp │ │ ├── EVMDialect.h │ │ ├── EVMMetrics.cpp │ │ ├── EVMMetrics.h │ │ ├── EVMObjectCompiler.cpp │ │ ├── EVMObjectCompiler.h │ │ ├── EthAssemblyAdapter.cpp │ │ ├── EthAssemblyAdapter.h │ │ ├── NoOutputAssembly.cpp │ │ ├── NoOutputAssembly.h │ │ ├── OptimizedEVMCodeTransform.cpp │ │ ├── OptimizedEVMCodeTransform.h │ │ ├── StackHelpers.h │ │ ├── StackLayoutGenerator.cpp │ │ ├── StackLayoutGenerator.h │ │ ├── VariableReferenceCounter.cpp │ │ ├── VariableReferenceCounter.h │ │ └── ssa/ │ │ ├── BridgeFinder.h │ │ ├── CodeTransform.cpp │ │ ├── CodeTransform.h │ │ ├── ControlFlow.cpp │ │ ├── ControlFlow.h │ │ ├── JunkAdmittingBlocksFinder.cpp │ │ ├── JunkAdmittingBlocksFinder.h │ │ ├── LivenessAnalysis.cpp │ │ ├── LivenessAnalysis.h │ │ ├── PhiInverse.cpp │ │ ├── PhiInverse.h │ │ ├── SSACFG.cpp │ │ ├── SSACFG.h │ │ ├── SSACFGBuilder.cpp │ │ ├── SSACFGBuilder.h │ │ ├── SSACFGLoopNestingForest.cpp │ │ ├── SSACFGLoopNestingForest.h │ │ ├── Stack.cpp │ │ ├── Stack.h │ │ ├── StackLayout.h │ │ ├── StackLayoutGenerator.cpp │ │ ├── StackLayoutGenerator.h │ │ ├── StackShuffler.cpp │ │ ├── StackShuffler.h │ │ ├── StackUtils.cpp │ │ ├── StackUtils.h │ │ ├── io/ │ │ │ ├── DotExporterBase.cpp │ │ │ ├── DotExporterBase.h │ │ │ ├── JSONExporter.cpp │ │ │ └── JSONExporter.h │ │ └── traversal/ │ │ ├── ForwardTopologicalSort.cpp │ │ └── ForwardTopologicalSort.h │ └── optimiser/ │ ├── ASTCopier.cpp │ ├── ASTCopier.h │ ├── ASTWalker.cpp │ ├── ASTWalker.h │ ├── BlockFlattener.cpp │ ├── BlockFlattener.h │ ├── BlockHasher.cpp │ ├── BlockHasher.h │ ├── CallGraphGenerator.cpp │ ├── CallGraphGenerator.h │ ├── CircularReferencesPruner.cpp │ ├── CircularReferencesPruner.h │ ├── CommonSubexpressionEliminator.cpp │ ├── CommonSubexpressionEliminator.h │ ├── ConditionalSimplifier.cpp │ ├── ConditionalSimplifier.h │ ├── ConditionalUnsimplifier.cpp │ ├── ConditionalUnsimplifier.h │ ├── ControlFlowSimplifier.cpp │ ├── ControlFlowSimplifier.h │ ├── DataFlowAnalyzer.cpp │ ├── DataFlowAnalyzer.h │ ├── DeadCodeEliminator.cpp │ ├── DeadCodeEliminator.h │ ├── Disambiguator.cpp │ ├── Disambiguator.h │ ├── EqualStoreEliminator.cpp │ ├── EqualStoreEliminator.h │ ├── EquivalentFunctionCombiner.cpp │ ├── EquivalentFunctionCombiner.h │ ├── EquivalentFunctionDetector.cpp │ ├── EquivalentFunctionDetector.h │ ├── ExpressionInliner.cpp │ ├── ExpressionInliner.h │ ├── ExpressionJoiner.cpp │ ├── ExpressionJoiner.h │ ├── ExpressionSimplifier.cpp │ ├── ExpressionSimplifier.h │ ├── ExpressionSplitter.cpp │ ├── ExpressionSplitter.h │ ├── ForLoopConditionIntoBody.cpp │ ├── ForLoopConditionIntoBody.h │ ├── ForLoopConditionOutOfBody.cpp │ ├── ForLoopConditionOutOfBody.h │ ├── ForLoopInitRewriter.cpp │ ├── ForLoopInitRewriter.h │ ├── FullInliner.cpp │ ├── FullInliner.h │ ├── FunctionCallFinder.cpp │ ├── FunctionCallFinder.h │ ├── FunctionGrouper.cpp │ ├── FunctionGrouper.h │ ├── FunctionHoister.cpp │ ├── FunctionHoister.h │ ├── FunctionSpecializer.cpp │ ├── FunctionSpecializer.h │ ├── InlinableExpressionFunctionFinder.cpp │ ├── InlinableExpressionFunctionFinder.h │ ├── KnowledgeBase.cpp │ ├── KnowledgeBase.h │ ├── LabelIDDispenser.cpp │ ├── LabelIDDispenser.h │ ├── LoadResolver.cpp │ ├── LoadResolver.h │ ├── LoopInvariantCodeMotion.cpp │ ├── LoopInvariantCodeMotion.h │ ├── Metrics.cpp │ ├── Metrics.h │ ├── NameCollector.cpp │ ├── NameCollector.h │ ├── NameDispenser.cpp │ ├── NameDispenser.h │ ├── NameDisplacer.cpp │ ├── NameDisplacer.h │ ├── NameSimplifier.cpp │ ├── NameSimplifier.h │ ├── OptimiserStep.h │ ├── OptimizerUtilities.cpp │ ├── OptimizerUtilities.h │ ├── README.md │ ├── Rematerialiser.cpp │ ├── Rematerialiser.h │ ├── SSAReverser.cpp │ ├── SSAReverser.h │ ├── SSATransform.cpp │ ├── SSATransform.h │ ├── SSAValueTracker.cpp │ ├── SSAValueTracker.h │ ├── Semantics.cpp │ ├── Semantics.h │ ├── SimplificationRules.cpp │ ├── SimplificationRules.h │ ├── StackCompressor.cpp │ ├── StackCompressor.h │ ├── StackLimitEvader.cpp │ ├── StackLimitEvader.h │ ├── StackToMemoryMover.cpp │ ├── StackToMemoryMover.h │ ├── StructuralSimplifier.cpp │ ├── StructuralSimplifier.h │ ├── Substitution.cpp │ ├── Substitution.h │ ├── Suite.cpp │ ├── Suite.h │ ├── SyntacticalEquality.cpp │ ├── SyntacticalEquality.h │ ├── UnusedAssignEliminator.cpp │ ├── UnusedAssignEliminator.h │ ├── UnusedFunctionParameterPruner.cpp │ ├── UnusedFunctionParameterPruner.h │ ├── UnusedFunctionsCommon.cpp │ ├── UnusedFunctionsCommon.h │ ├── UnusedPruner.cpp │ ├── UnusedPruner.h │ ├── UnusedStoreBase.cpp │ ├── UnusedStoreBase.h │ ├── UnusedStoreEliminator.cpp │ ├── UnusedStoreEliminator.h │ ├── VarDeclInitializer.cpp │ ├── VarDeclInitializer.h │ ├── VarNameCleaner.cpp │ └── VarNameCleaner.h ├── scripts/ │ ├── ASTImportTest.sh │ ├── AntlrBatchTestRig.java │ ├── Dockerfile │ ├── Dockerfile_alpine │ ├── build.sh │ ├── build_emscripten.sh │ ├── bytecodecompare/ │ │ ├── prepare_report.js │ │ └── prepare_report.py │ ├── check_style.sh │ ├── check_symlinks.sh │ ├── chk_shellscripts/ │ │ └── chk_shellscripts.sh │ ├── ci/ │ │ ├── base64DecToArr.js │ │ ├── build.sh │ │ ├── build_emscripten.sh │ │ ├── build_ossfuzz.sh │ │ ├── build_win.sh │ │ ├── docker_upgrade.sh │ │ ├── install_and_check_minimum_requirements.sh │ │ ├── mini-lz4.js │ │ ├── notification/ │ │ │ ├── matrix_notification.sh │ │ │ └── templates/ │ │ │ ├── build_fail.json │ │ │ ├── build_release.json │ │ │ └── build_success.json │ │ ├── pack_soljson.sh │ │ └── post_style_errors_on_github.sh │ ├── codespell_ignored_lines.txt │ ├── codespell_whitelist.txt │ ├── common/ │ │ ├── cmdline_helpers.py │ │ ├── git_helpers.py │ │ └── rest_api_helpers.py │ ├── common.sh │ ├── common_cmdline.sh │ ├── create_source_tarball.sh │ ├── docker/ │ │ └── buildpack-deps/ │ │ ├── Dockerfile.emscripten │ │ ├── Dockerfile.ubuntu.clang.ossfuzz │ │ ├── Dockerfile.ubuntu2404 │ │ ├── Dockerfile.ubuntu2404.arm │ │ ├── Dockerfile.ubuntu2404.clang │ │ ├── README.md │ │ └── emscripten.jam │ ├── docker_deploy_manual.sh │ ├── docs_version_pragma_check.sh │ ├── download_ossfuzz_corpus.sh │ ├── error_codes.py │ ├── externalTests/ │ │ ├── benchmark_diff.py │ │ ├── common.sh │ │ ├── download_benchmarks.py │ │ ├── merge_benchmarks.sh │ │ ├── parse_eth_gas_report.py │ │ ├── runners/ │ │ │ ├── base.py │ │ │ └── foundry.py │ │ ├── summarize_benchmarks.sh │ │ ├── test_helpers.py │ │ └── update_external_repos.sh │ ├── extract_test_cases.py │ ├── gas_diff_stats.py │ ├── get_nightly_version.sh │ ├── get_version.sh │ ├── install_deps.ps1 │ ├── install_evmone.ps1 │ ├── isolate_tests.py │ ├── isoltest.sh │ ├── list_contributors.sh │ ├── prerelease_suffix.sh │ ├── pylint_all.py │ ├── pylintrc │ ├── regressions.py │ ├── run_proofs.sh │ ├── solc-bin/ │ │ ├── bytecode_reports_for_modified_binaries.sh │ │ └── compare_bytecode_reports.sh │ ├── soltest.sh │ ├── splitSources.py │ ├── test_antlr_grammar.sh │ ├── test_emscripten.sh │ ├── tests.sh │ ├── uniqueErrors.sh │ ├── update_bugs_by_version.py │ ├── wasm-rebuild/ │ │ ├── README │ │ ├── docker-scripts/ │ │ │ ├── genbytecode.sh │ │ │ ├── isolate_tests.py │ │ │ ├── patch.sh │ │ │ ├── rebuild_current.sh │ │ │ └── rebuild_tags.sh │ │ └── rebuild.sh │ └── yul_coverage.sh ├── snap/ │ └── snapcraft.yaml ├── solc/ │ ├── CMakeLists.txt │ ├── CommandLineInterface.cpp │ ├── CommandLineInterface.h │ ├── CommandLineParser.cpp │ ├── CommandLineParser.h │ ├── Exceptions.h │ └── main.cpp ├── test/ │ ├── .solhint.json │ ├── .solhintignore │ ├── CMakeLists.txt │ ├── Common.cpp │ ├── Common.h │ ├── CommonSyntaxTest.cpp │ ├── CommonSyntaxTest.h │ ├── EVMHost.cpp │ ├── EVMHost.h │ ├── ExecutionFramework.cpp │ ├── ExecutionFramework.h │ ├── FilesystemUtils.cpp │ ├── FilesystemUtils.h │ ├── InteractiveTests.h │ ├── Metadata.cpp │ ├── Metadata.h │ ├── TestCase.cpp │ ├── TestCase.h │ ├── TestCaseReader.cpp │ ├── TestCaseReader.h │ ├── benchmarks/ │ │ ├── OptimizorClub.sol │ │ ├── chains.sol │ │ ├── external-setup.sh │ │ ├── external.sh │ │ ├── local.sh │ │ └── verifier.sol │ ├── buglistTests.js │ ├── buglist_test_vectors.md │ ├── cmdlineTests/ │ │ ├── abi_via_ir/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── abiencoderv2_no_warning/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── asm_json/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── asm_json_import_sourcelist_with_null_elements/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── asm_json_no_pretty_print/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── asm_json_subassembly_id_representation/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── asm_json_yul_export_evm_asm_import/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── ast_compact_json_no_pretty_json/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ast_compact_json_storage_layout_specifier/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ast_compact_json_with_base_path/ │ │ │ ├── args │ │ │ ├── c.sol │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ast_ir/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ast_json_import_wrong_evmVersion/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── combined_json_abi/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── combined_json_generated_sources/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── combined_json_no_pretty_print/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── combined_json_stop_after_parsing/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── combined_json_with_base_path/ │ │ │ ├── args │ │ │ ├── c.sol │ │ │ ├── input.sol │ │ │ └── output │ │ ├── combined_json_with_devdoc/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── combined_json_with_userdoc/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── constant_optimizer_yul/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── debug_info_in_yul_and_evm_asm_print_all/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── debug_info_in_yul_and_evm_asm_print_all_and_none/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── debug_info_in_yul_and_evm_asm_print_location_only/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── debug_info_in_yul_and_evm_asm_print_none/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── debug_info_in_yul_and_evm_asm_print_snippet_only/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── debug_info_in_yul_snippet_escaping/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── dup_opt_peephole/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── eof_unavailable_before_osaka/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── error_codes/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── ethdebug_debuginfo_without_experimental_flag/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── ethdebug_eof_container_osaka/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ethdebug_on_abstract/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ethdebug_on_interface/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── events_in_abi/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evm_version_byzantium/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── evm_version_constantinople/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── evmasm_difficulty_post_paris/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evmasm_difficulty_pre_paris/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evmasm_prevrandao_post_paris/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evmasm_prevrandao_pre_paris/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evmasm_transient_storage_inline_assembly/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evmasm_transient_storage_inline_assembly_via_ir/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evmasm_transient_storage_state_variable/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── evmasm_transient_storage_state_variable_via_ir/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── exp_base_literal/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── experimental_feature_without_experimental_flag/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── experimental_flag_with_standard_json/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.json │ │ ├── function_debug_info/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── function_debug_info_via_yul/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── hashes/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── import_asm_json_all_valid_flags/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_difficulty_prevrandao/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_eof_unavailable_before_osaka/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_hex_subassembly_indices/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_invalid_data_not_hex/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_invalid_data_not_object/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_invalid_jumptype_instruction/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_invalid_value/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_missing_subobject_indices/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_no_optimize/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_no_value/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_non_unique_sources/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_optimize/ │ │ │ ├── args │ │ │ ├── exit │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_out_of_range_data_index/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_random_order_data_index/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_unrecognized_field/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_untagged_jumpdest/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── import_asm_json_verbatim/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_yul_more_subobjects/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── import_asm_json_yul_subobjects/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── inheritance_repeated_definition_error/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── inline_assembly_function_name_clash/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_compiler_inheritance_nosubobjects/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_compiler_subobjects/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_optimized_transient_storage_value_type/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_optimized_with_optimize/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_subobject_order/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_unoptimized_with_optimize/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_unoptimized_with_optimize_via_ir/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_with_assembly_no_memoryguard_creation/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── ir_with_assembly_no_memoryguard_runtime/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── keccak_optimization_deploy_code/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── keccak_optimization_low_runs/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── linker_mode_invalid_option_no_optimize_yul/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── exit │ │ ├── linker_mode_invalid_option_optimize/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── exit │ │ ├── linker_mode_invalid_option_optimize_runs/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── exit │ │ ├── linker_mode_invalid_option_optimize_yul/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── exit │ │ ├── linker_mode_invalid_option_yul_optimizations/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── exit │ │ ├── linker_mode_output_selection_invalid/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── exit │ │ ├── linking_qualified_library_name/ │ │ │ ├── args │ │ │ ├── contract1.sol │ │ │ ├── math.sol │ │ │ └── output │ │ ├── linking_solidity/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── linking_solidity_unresolved_references/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── linking_standard_solidity/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── linking_standard_solidity_quote_in_file_name/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── linking_standard_solidity_unresolved_references/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── linking_standard_yul/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── linking_standard_yul_quote_in_file_name/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── linking_standard_yul_unresolved_references/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── linking_strict_assembly/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_strict_assembly_duplicate_library_name/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── linking_strict_assembly_qualified_library_qualified_reference/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_strict_assembly_qualified_library_unqualified_reference/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_strict_assembly_same_library_name_different_files/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_strict_assembly_same_library_name_different_files_in_link_references/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_strict_assembly_unqualified_library_qualified_reference/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_strict_assembly_unqualified_library_unqualified_reference/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_strict_assembly_unresolved_references/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── linking_unqualified_library_name/ │ │ │ ├── args │ │ │ ├── contract1.sol │ │ │ ├── contract2.sol │ │ │ ├── error.sol │ │ │ ├── math.sol │ │ │ └── output │ │ ├── mcopy_bytes_array_abi_decode/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── mcopy_bytes_array_returned_from_function/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── mcopy_string_literal_returned_from_function/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── memoryguard_shadowing_by_inline_assembly_identifiers/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── message_format/ │ │ │ ├── err │ │ │ └── input.sol │ │ ├── message_format_utf8/ │ │ │ ├── err │ │ │ └── input.sol │ │ ├── metadata/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── metadata_experimental/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── metadata_via_ssa_cfg/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── model_checker_bmc_loop_iterations/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_bmc_loop_iterations_invalid_arg/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_bmc_loop_iterations_no_argument/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_contracts_all/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_contracts_all_explicit/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_contracts_contract_missing/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_contracts_empty_contract/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_contracts_empty_source/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_contracts_inexistent_contract/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_contracts_inexistent_source/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_contracts_one_contract_missing/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_contracts_only_one/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_contracts_source_missing/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_divModSlacks_default_all/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_divModSlacks_default_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_divModSlacks_default_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_divModSlacks_false_all/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_divModSlacks_false_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_divModSlacks_false_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_engine_all/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_engine_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_engine_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_engine_none/ │ │ │ ├── args │ │ │ └── input.sol │ │ ├── model_checker_ext_calls_empty_arg/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_ext_calls_trusted_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_ext_calls_untrusted_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_ext_calls_wrong_arg/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_invariants_all/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_invariants_contract/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_invariants_contract_eld/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_invariants_contract_reentrancy/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_invariants_reentrancy/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_invariants_wrong/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_print_query_all/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_print_query_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_print_query_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_proved_safe_default_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_proved_safe_default_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_proved_safe_default_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_proved_safe_true_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_proved_safe_true_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_proved_safe_true_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unproved_default_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unproved_default_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unproved_default_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unproved_true_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unproved_true_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unproved_true_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unsupported_default_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unsupported_default_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unsupported_default_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unsupported_true_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unsupported_true_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_show_unsupported_true_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_solvers_cvc5/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_solvers_cvc5_eld/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_solvers_eld/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_solvers_smtlib2/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_solvers_wrong/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_solvers_wrong2/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_solvers_z3/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_solvers_z3_implicit/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_solvers_z3_smtlib2/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_all_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_all_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_all_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_assert_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_assert_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_balance_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_balance_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_constant_condition_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_constant_condition_chc/ │ │ │ ├── args │ │ │ └── input.sol │ │ ├── model_checker_targets_default_all_engines/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_default_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_default_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_div_by_zero_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_div_by_zero_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_error/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── model_checker_targets_out_of_bounds_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_out_of_bounds_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_overflow_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_overflow_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_pop_empty_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_pop_empty_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_underflow_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_underflow_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_underflow_overflow_assert_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_underflow_overflow_assert_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_underflow_overflow_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_targets_underflow_overflow_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_timeout_all/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_timeout_bmc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── model_checker_timeout_chc/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── input.sol │ │ ├── name_simplifier/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── no_cbor_metadata/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── no_cbor_metadata_with_metadata_hash/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── no_contract_combined_json/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── no_import_callback/ │ │ │ ├── args │ │ │ ├── contract_1.sol │ │ │ ├── contract_2.sol │ │ │ ├── err │ │ │ └── exit │ │ ├── object_compiler/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── optimize_full_storage_write/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_BlockDeDuplicator/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_array_sload/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_enabled_invalid_yul_optimizer_enabled_and_disabled/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── optimizer_inliner_add/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_inliner_call_from_constructor/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_inliner_dynamic_reference/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_inliner_dynamic_reference_constructor/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_inliner_inc/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_inliner_multireturn/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── optimizer_user_yul/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── pretty_json_indent_only/ │ │ │ ├── args │ │ │ ├── input.json │ │ │ ├── no-pretty-print │ │ │ ├── output │ │ │ └── output.json │ │ ├── pretty_json_standard/ │ │ │ ├── args │ │ │ ├── input.json │ │ │ ├── no-pretty-print │ │ │ └── output.json │ │ ├── pretty_json_standard_indent/ │ │ │ ├── args │ │ │ ├── input.json │ │ │ ├── no-pretty-print │ │ │ ├── output │ │ │ └── output.json │ │ ├── require_overload/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── require_with_error_ir/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── require_with_string_ir/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── revert_strings/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── stack_too_deep_from_code_transform/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── standard_cli_import_ast_storage_layout_specifier_missing_expression/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── standard_cli_output_selection_invalid/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.json │ │ ├── standard_debug_info_in_evm_asm_via_ir_location/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_debug_info_in_yul_and_evm_asm_print_all/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_debug_info_in_yul_and_evm_asm_print_location_only/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_debug_info_in_yul_and_evm_asm_print_none/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_debug_info_in_yul_and_evm_asm_print_snippet_only/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_debug_info_in_yul_location/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_default_success/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_empty_file_name/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_eof_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_eof_unavailable_before_osaka/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_evm_version_byzantium/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_evm_version_constantinople/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_file_not_found/ │ │ │ ├── args │ │ │ ├── err │ │ │ └── exit │ │ ├── standard_function_debug_info/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_generatedSources/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_immutable_references/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_eof_unavailable_before_osaka/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_immutable_references/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_invalid_input_array/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_invalid_key_inside_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_invalid_key_other_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_invalid_no_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_invalid_opcode/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_invalid_two_sources/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_link_references/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_multiple_keys_inside_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_no_optimize/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_no_output_selection/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_asm_json_optimize/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_ast/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_ast_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_ast_select_bytecode/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_with_comments/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_with_comments_simple/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_import_with_invalid_utf8/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_invalid_option_no_optimize_yul/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.json │ │ ├── standard_invalid_option_optimize/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.json │ │ ├── standard_invalid_option_optimize_runs/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.json │ │ ├── standard_invalid_option_optimize_yul/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.json │ │ ├── standard_invalid_option_yul_optimizations/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.json │ │ ├── standard_irOptimized_ast_requested/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_irOptimized_requested/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_ir_ast_requested/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_ir_requested/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_ir_unoptimized_with_optimize/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_ir_unoptimized_with_optimize_via_ir/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_json_no_pretty_print/ │ │ │ ├── input.json │ │ │ ├── no-pretty-print │ │ │ └── output.json │ │ ├── standard_metadata/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_metadata_experimental/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_method_identifiers_requested/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_method_identifiers_requested_empty/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_missing_key_useLiteralContent/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_bmc_loop_iterations/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_bmc_loop_iterations_invalid_arg/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_all/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_all_explicit/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_empty_array/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_empty_contract/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_empty_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_inexistent_contract/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_multi_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_only_one/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_wrong_key_sources/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_wrong_key_sources_2/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_wrong_key_sources_3/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_contracts_wrong_key_sources_4/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_divModSlacks_default_all/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_divModSlacks_default_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_divModSlacks_default_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_divModSlacks_false_all/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_divModSlacks_false_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_divModSlacks_false_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_divModSlacks_wrong/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_engine_all/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_engine_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_engine_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_engine_none/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_ext_calls_empty_arg/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_ext_calls_trusted_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_ext_calls_untrusted_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_ext_calls_wrong_arg_1/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_ext_calls_wrong_arg_2/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_invariants_contract/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_invariants_contract_reentrancy/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_invariants_reentrancy/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_invariants_wrong_key/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_invariants_wrong_type/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_invariants_wrong_type_2/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_print_query_all/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_print_query_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_print_query_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_print_query_invalid_arg/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_default_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_default_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_default_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_false_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_false_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_false_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_true_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_true_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_true_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_proved_safe_wrong/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_default_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_false_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_false_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_false_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_true_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_true_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_true_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unproved_wrong/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_default_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_default_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_default_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_false_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_false_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_false_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_true_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_true_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_true_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_show_unsupported_wrong/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_solvers_none/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_solvers_smtlib2/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_solvers_z3/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_solvers_z3_smtlib2/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_assert_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_assert_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_balance_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_balance_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_constantCondition_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_constantCondition_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_default_all_engines/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_default_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_default_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_div_by_zero_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_div_by_zero_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_empty_array/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_out_of_bounds_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_out_of_bounds_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_overflow_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_overflow_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_pop_empty_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_pop_empty_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_underflow_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_underflow_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_underflow_overflow_assert_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_underflow_overflow_assert_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_underflow_overflow_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_underflow_overflow_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_wrong_target_types/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_wrong_target_types_2/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_targets_wrong_targets/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_timeout_all/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_timeout_bmc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_timeout_chc/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_timeout_wrong_key/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_model_checker_timeout_wrong_value/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_no_append_cbor/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_no_append_cbor_with_metadata_hash/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_no_import_callback/ │ │ │ ├── B.sol │ │ │ ├── args │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_non_utf8_filename/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_non_utf8_filename2/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_only_ast_requested/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_generatedSources/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_invalid_detail_type/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_invalid_details/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_no_yul/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yul/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_no_object/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_empty_sequence_metadata/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_empty_sequence_whitespaces_metadata/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_invalid_abbreviation/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_invalid_nested_delimiter/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_mutliple_delimiters/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_nested_brackets/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_nesting_too_deep/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_no_yul/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_no_yul_empty_string/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_no_yul_whitespaces/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_type/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_unbalanced_closing_bracket/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_unbalanced_opening_bracket/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_with_cleanup_sequence/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_with_empty_cleanup_sequence/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_with_empty_optimisation_sequence/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_with_empty_sequence_no_yul/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_optimiserSteps_with_whitespace_newline_sequence_no_yul/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_optimizer_yulDetails_without_yul/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_debuginfo_ethdebug_compatible/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_debuginfo_ethdebug_incompatible/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_debuginfo_ethdebug_with_interfaces_and_abstracts/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_all_blank/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_all_sources_blank_contract_named_blank/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_all_sources_single_contract_multiple_matches/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_all_sources_single_contract_single_match/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_all_sources_star_contract_named_star/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_all_star/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_duplicate_matching_source_and_contract_selectors/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_empty/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_ethdebug_bytecode_and_deployedbytecode_ir/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_bytecode_and_deployedbytecode_iroptimized/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_ir/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_ethdebug_bytecode_and_deployedbytecode_optimizer_iroptimized/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_ethdebug_bytecode_ir/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_bytecode_iroptimized/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_deployedbytecode_ir/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_deployedbytecode_iroptimized/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_ir/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_iroptimized/ │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_output_selection_ethdebug_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_ethdebug_no_viair/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_ethdebug_optimize_ir/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_ethdebug_optimize_iroptimized/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_ir_ast_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_multiple_matching_source_and_contract_selectors/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_multiple_matching_source_and_contract_selectors_full_pipeline/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_no_output_selected/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_single_all/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_single_source_single_contract_multiple_matches/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_single_source_single_contract_single_match/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_unrecognized_output/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_unrecognized_source_and_contract_selectors/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_wrong_type/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_wrong_type_contract/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_wrong_type_output/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_wrong_type_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_output_selection_yul_cfg_json_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_outputs_on_analysis_error_fatal/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_outputs_on_analysis_error_fatal_after_current_step/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_outputs_on_analysis_error_non_fatal/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_outputs_on_compilation_error/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_outputs_on_parsing_error/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_parsing_import_absolute_paths/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_raw_utf16_filename/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_secondary_source_location/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_stack_too_deep_from_code_transform/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_stop_after_parsing_ast_requested/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_stop_after_parsing_bytecode_requested/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_stop_after_parsing_non_binary_output_requested/ │ │ │ ├── args │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_undeployable_contract_all_outputs/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_urls_existing_and_missing/ │ │ │ ├── contract.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_urls_missing/ │ │ │ ├── contract.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_via_ssa_cfg_ethdebug/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_via_ssa_cfg_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_via_ssa_cfg_via_ir_false/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_viair_requested/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_key_auxiliary_input/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_key_metadata/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_key_optimizer/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_key_root/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_key_settings/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_key_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_auxiliary_input/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_auxiliary_input_smtlib2responses/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_auxiliary_input_smtlib2responses_member/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_metadata/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_optimizer/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_remappings/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_remappings_entry/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_root/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_settings/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_source/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_sources/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_wrong_type_useLiteralContent/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_cfg_json_export/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_code_generation_error/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_debug_info_ethdebug_compatible_output/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_debug_info_ethdebug_compatible_output_eof/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_debug_info_ethdebug_incompatible_output/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_debug_info_ethdebug_verbatim_unimplemented/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_debug_info_print_all/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_debug_info_print_location_only/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_debug_info_print_none/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_debug_info_print_snippet_only/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_embedded_object_name/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_eof_unavailable_before_osaka/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_ethdebug_assign_immutable/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_ethdebug_bytecode_ir/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_ethdebug_bytecode_iroptimized/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_ethdebug_deployed_bytecode/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_ethdebug_deployed_bytecode_and_bytecode/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_ethdebug_eof/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_ethdebug_ir/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_ethdebug_iroptimize/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ ├── output.json │ │ │ └── strip-ethdebug │ │ ├── standard_yul_ethdebug_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_ethdebug_optimize_ir/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_ethdebug_optimize_iroptimized/ │ │ │ ├── args │ │ │ ├── in.yul │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_evm_version_byzantium/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_evm_version_constantinople/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_immutable_references/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_invalid_object_name/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_ir_ast_no_experimental/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_multiple_files/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_multiple_files_selected/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_object/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_object_invalid_sub/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_object_name/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_optimiserSteps/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_optimized/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_output_warning/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_single_file_via_urls/ │ │ │ ├── args │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_stack_opt/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── standard_yul_stack_opt_disabled/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── stdin/ │ │ │ ├── args │ │ │ └── stdin │ │ ├── stop_after_parsing_abi/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── stop_after_parsing_ast/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── storage_layout_already_defined_in_ancestor/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── storage_layout_bytes/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_dyn_array/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_many/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_mapping/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_smoke/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_smoke_two_contracts/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_specifier_repeated_definition_error/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── storage_layout_specifier_smoke/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── storage_layout_specifier_smoke_ir_codegen/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── storage_layout_specifier_storage_layout_output/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── storage_layout_string/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_struct/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_struct_packed/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_transient_value_types/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_user_defined/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── storage_layout_user_defined_no_pretty_print/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── storage_layout_value_types/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_layout_value_types_packed/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── storage_transient_storage_collision_ir_output/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── strict_asm_asm_json_arbitrary_source_index/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── stdin │ │ ├── strict_asm_asm_json_subobjects_with_debug/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── strict_asm_asm_json_with_debug_info_annotations/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── strict_asm_asm_json_without_debug_info_annotations/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── strict_asm_asm_json_yul_verbatim/ │ │ │ ├── args │ │ │ ├── output │ │ │ └── stdin │ │ ├── strict_asm_ast_compact_json/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_code_generation_error/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_debug_info_print_all/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_debug_info_print_location_only/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_debug_info_print_none/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_debug_info_print_snippet_only/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_eof_container_osaka/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_eof_dataloadn_osaka/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_eof_unavailable_before_osaka/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_evm_version_byzantium/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_evm_version_constantinople/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_invalid_option_output_dir/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_jump/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_msize_with_optimizer/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_msize_without_optimizer/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_only_cr/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_optimizer_invalid_yul_optimizer_enabled_and_disabled/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_optimizer_steps/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_options_in_non_asm_mode/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── strict_asm_output_selection_asm_only/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_output_selection_bin_only/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_output_selection_invalid/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_output_selection_ir_optimized_only/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_warning/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_warning_and_error_optimize/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.yul │ │ ├── strict_asm_warning_optimize/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_warning_optimize_unreachable/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.yul │ │ │ └── output │ │ ├── strict_asm_yul_cfg_json_export/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── structured_documentation_source_location/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── too_long_line/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── too_long_line_both_sides_short/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── too_long_line_edge_in/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── too_long_line_edge_out/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── too_long_line_left_short/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── too_long_line_multiline/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── too_long_line_right_short/ │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── transient_storage_layout/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── transient_storage_layout_smoke_empty/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── transient_storage_layout_smoke_two_contracts/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── transient_storage_layout_value_types/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── transient_storage_layout_value_types_interleaved_with_storage/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── transient_storage_layout_value_types_packed/ │ │ │ ├── in.sol │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── undeployable_contract_empty_outputs/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── via_ssa_cfg_ethdebug/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── via_ssa_cfg_without_experimental/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── viair_abicoder_v1/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── viair_msize_without_optimizer/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── viair_subobject_optimization/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── viair_subobjects/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_cfg_json_export/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_function_name_clashes/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── yul_function_name_clashes_different_params/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── yul_optimize_runs/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── yul_optimizer_disabled_sequence_empty/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_erc7201_literal_comptime_evaluation/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_erc7201_param_calldata/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_erc7201_param_memory/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_erc7201_param_storage/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_steps/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_steps_disabled/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── yul_optimizer_steps_invalid_abbreviation/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── yul_optimizer_steps_invalid_substitution_in_expression_simplifier/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_steps_nested_brackets/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_steps_nesting_too_deep/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── yul_optimizer_steps_short_sequence/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_steps_unbalanced_closing_bracket/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── yul_optimizer_steps_unbalanced_opening_bracket/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── exit │ │ │ └── input.sol │ │ ├── yul_optimizer_steps_with_empty_cleanup_sequence/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_steps_with_empty_optimization_sequence/ │ │ │ ├── args │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_optimizer_steps_without_optimize_empty_sequence/ │ │ │ ├── args │ │ │ ├── err │ │ │ ├── input.sol │ │ │ └── output │ │ ├── yul_string_format_ascii/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── yul_string_format_ascii_bytes32/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── yul_string_format_ascii_bytes32_from_number/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── yul_string_format_ascii_long/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── yul_string_format_hex/ │ │ │ ├── input.json │ │ │ └── output.json │ │ ├── yul_verbatim/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── yul_verbatim_msize/ │ │ │ ├── args │ │ │ ├── input.yul │ │ │ └── output │ │ ├── ~assembler_modes/ │ │ │ └── test.sh │ │ ├── ~ast_export_with_stop_after_parsing/ │ │ │ └── test.sh │ │ ├── ~ast_import_export/ │ │ │ └── test.sh │ │ ├── ~bytecode_equivalence_independent_of_import_discovery_order/ │ │ │ ├── inputs.sol │ │ │ └── test.py │ │ ├── ~bytecode_equivalence_with_unused_contracts/ │ │ │ ├── inputs.sol │ │ │ └── test.py │ │ ├── ~cli_and_standard_json_equivalence/ │ │ │ └── test.sh │ │ ├── ~compilation_tests/ │ │ │ └── test.sh │ │ ├── ~deduplicator-verbatim-bug/ │ │ │ ├── test.sh │ │ │ └── verbatim_inside_identical_blocks.yul │ │ ├── ~documentation_examples/ │ │ │ └── test.sh │ │ ├── ~evmasm_import_export/ │ │ │ └── test.sh │ │ ├── ~library_checksum/ │ │ │ └── test.sh │ │ ├── ~library_long_names/ │ │ │ └── test.sh │ │ ├── ~linking/ │ │ │ └── test.sh │ │ ├── ~name_dependent_cse_bug/ │ │ │ ├── cse_bug.yul │ │ │ └── test.sh │ │ ├── ~overwriting_files/ │ │ │ └── test.sh │ │ ├── ~soljson_via_fuzzer/ │ │ │ └── test.sh │ │ ├── ~standard_input/ │ │ │ └── test.sh │ │ ├── ~unknown_options/ │ │ │ └── test.sh │ │ ├── ~update_bugs_by_version/ │ │ │ └── test.sh │ │ └── ~via_ir_equivalence/ │ │ └── test.sh │ ├── cmdlineTests.sh │ ├── compilationTests/ │ │ ├── MultiSigWallet/ │ │ │ ├── Factory.sol │ │ │ ├── LICENSE │ │ │ ├── MultiSigWallet.sol │ │ │ ├── MultiSigWalletFactory.sol │ │ │ ├── MultiSigWalletWithDailyLimit.sol │ │ │ ├── MultiSigWalletWithDailyLimitFactory.sol │ │ │ ├── README.md │ │ │ └── TestToken.sol │ │ ├── README.md │ │ ├── corion/ │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── announcementTypes.sol │ │ │ ├── ico.sol │ │ │ ├── module.sol │ │ │ ├── moduleHandler.sol │ │ │ ├── multiOwner.sol │ │ │ ├── owned.sol │ │ │ ├── premium.sol │ │ │ ├── provider.sol │ │ │ ├── publisher.sol │ │ │ ├── safeMath.sol │ │ │ ├── schelling.sol │ │ │ ├── token.sol │ │ │ └── tokenDB.sol │ │ ├── gnosis/ │ │ │ ├── Events/ │ │ │ │ ├── CategoricalEvent.sol │ │ │ │ ├── Event.sol │ │ │ │ ├── EventFactory.sol │ │ │ │ └── ScalarEvent.sol │ │ │ ├── LICENSE │ │ │ ├── MarketMakers/ │ │ │ │ ├── LMSRMarketMaker.sol │ │ │ │ └── MarketMaker.sol │ │ │ ├── Markets/ │ │ │ │ ├── Campaign.sol │ │ │ │ ├── CampaignFactory.sol │ │ │ │ ├── Market.sol │ │ │ │ ├── MarketFactory.sol │ │ │ │ ├── StandardMarket.sol │ │ │ │ └── StandardMarketFactory.sol │ │ │ ├── Migrations.sol │ │ │ ├── Oracles/ │ │ │ │ ├── CentralizedOracle.sol │ │ │ │ ├── CentralizedOracleFactory.sol │ │ │ │ ├── DifficultyOracle.sol │ │ │ │ ├── DifficultyOracleFactory.sol │ │ │ │ ├── FutarchyOracle.sol │ │ │ │ ├── FutarchyOracleFactory.sol │ │ │ │ ├── MajorityOracle.sol │ │ │ │ ├── MajorityOracleFactory.sol │ │ │ │ ├── Oracle.sol │ │ │ │ ├── SignedMessageOracle.sol │ │ │ │ ├── SignedMessageOracleFactory.sol │ │ │ │ ├── UltimateOracle.sol │ │ │ │ └── UltimateOracleFactory.sol │ │ │ ├── README.md │ │ │ ├── Tokens/ │ │ │ │ ├── EtherToken.sol │ │ │ │ ├── OutcomeToken.sol │ │ │ │ ├── StandardToken.sol │ │ │ │ └── Token.sol │ │ │ └── Utils/ │ │ │ └── Math.sol │ │ └── milestonetracker/ │ │ ├── LICENSE │ │ ├── MilestoneTracker.sol │ │ ├── README.md │ │ └── RLP.sol │ ├── contracts/ │ │ ├── AuctionRegistrar.cpp │ │ ├── ContractInterface.h │ │ └── Wallet.cpp │ ├── docsCodeStyle.sh │ ├── ethdebugSchemaTests/ │ │ ├── conftest.py │ │ ├── input_file.json │ │ ├── input_file_eof.json │ │ └── test_ethdebug_schema_conformity.py │ ├── evmc/ │ │ ├── CMakeLists.txt │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bytes.hpp │ │ ├── evmc.h │ │ ├── evmc.hpp │ │ ├── filter_iterator.hpp │ │ ├── helpers.h │ │ ├── hex.hpp │ │ ├── loader.c │ │ ├── loader.h │ │ ├── mocked_host.hpp │ │ └── utils.h │ ├── externalTests/ │ │ ├── README.md │ │ ├── bleeps.sh │ │ ├── brink.sh │ │ ├── chainlink.sh │ │ ├── colony.sh │ │ ├── elementfi.sh │ │ ├── ens.sh │ │ ├── euler.sh │ │ ├── gnosis.sh │ │ ├── gp2.sh │ │ ├── pool-together.sh │ │ ├── prb-math.py │ │ ├── solc-js/ │ │ │ ├── DAO/ │ │ │ │ ├── DAO.sol │ │ │ │ ├── ManagedAccount.sol │ │ │ │ ├── Token.sol │ │ │ │ └── TokenCreation.sol │ │ │ ├── asm-json.js │ │ │ ├── determinism.js │ │ │ └── solc-js.sh │ │ ├── trident.sh │ │ ├── uniswap.sh │ │ ├── yield-liquidator.sh │ │ └── zeppelin.sh │ ├── external_tests.py │ ├── formal/ │ │ ├── README.md │ │ ├── and_distributed_over_shl.py │ │ ├── byte_big.py │ │ ├── byte_equivalence.py │ │ ├── checked_int_add.py │ │ ├── checked_int_div.py │ │ ├── checked_int_mul_12.py │ │ ├── checked_int_sub.py │ │ ├── checked_uint_add.py │ │ ├── checked_uint_mul_12.py │ │ ├── checked_uint_sub.py │ │ ├── combine_byte_shl.py │ │ ├── combine_byte_shr_1.py │ │ ├── combine_byte_shr_2.py │ │ ├── combine_div_shl_one_32.py │ │ ├── combine_mul_shl_one_64.py │ │ ├── combine_shl_shr_by_constant_64.py │ │ ├── combine_shr_shl_by_constant_64.py │ │ ├── eq_sub.py │ │ ├── exp_neg_one.py │ │ ├── exp_to_shl.py │ │ ├── mod_add_to_addmod.py │ │ ├── mod_mul_to_mulmod.py │ │ ├── move_and_across_shl_128.py │ │ ├── move_and_across_shr_128.py │ │ ├── move_and_inside_or.py │ │ ├── opcodes.py │ │ ├── redundant_store_unrelated.py │ │ ├── repeated_and.py │ │ ├── repeated_or.py │ │ ├── replace_mul_by_shift.py │ │ ├── rule.py │ │ ├── shl_workaround_8.py │ │ ├── signed_integer_cleanup_function.py │ │ ├── signextend.py │ │ ├── signextend_and.py │ │ ├── signextend_equivalence.py │ │ ├── signextend_shl.py │ │ ├── signextend_shr.py │ │ ├── smod.py │ │ ├── sub_not_zero_x_to_not_x_256.py │ │ ├── sub_sub.py │ │ ├── unsigned_integer_cleanup_function.py │ │ └── util.py │ ├── libevmasm/ │ │ ├── Assembler.cpp │ │ ├── EVMAssemblyTest.cpp │ │ ├── EVMAssemblyTest.h │ │ ├── Optimiser.cpp │ │ ├── PlainAssemblyParser.cpp │ │ ├── PlainAssemblyParser.h │ │ └── evmAssemblyTests/ │ │ └── isoltestTesting/ │ │ ├── code_generation_error.asmjson │ │ ├── comments.asm │ │ ├── empty.asm │ │ ├── invalid_json.asmjson │ │ ├── jumps.asm │ │ ├── nontrivial_subassembly_ids.asm │ │ ├── operations.asm │ │ ├── push.asm │ │ ├── pushsize.asm │ │ ├── pushsubsize.asm │ │ ├── settings_eof_version.asmjson │ │ ├── settings_evm_version.asmjson │ │ ├── settings_optimizer_constant_optimizer.asmjson │ │ ├── settings_optimizer_cse.asmjson │ │ ├── settings_optimizer_deduplicate.asmjson │ │ ├── settings_optimizer_expected_executions_per_deployment.asmjson │ │ ├── settings_optimizer_inliner.asmjson │ │ ├── settings_optimizer_jumpdest_remover.asmjson │ │ ├── settings_optimizer_peephole.asmjson │ │ ├── settings_optimizer_preset.asmjson │ │ ├── settings_outputs.asmjson │ │ ├── smoke.asmjson │ │ ├── smoke_plain.asm │ │ ├── subassemblies.asm │ │ ├── subassemblies_empty.asm │ │ └── subassemblies_nested.asm │ ├── liblangutil/ │ │ ├── CharStream.cpp │ │ ├── Scanner.cpp │ │ └── SourceLocation.cpp │ ├── libsolidity/ │ │ ├── ABIDecoderTests.cpp │ │ ├── ABIEncoderTests.cpp │ │ ├── ABIJson/ │ │ │ ├── basic_test.sol │ │ │ ├── constructor_abi.sol │ │ │ ├── empty_contract.sol │ │ │ ├── empty_name_input_parameter_with_named_one.sol │ │ │ ├── empty_name_return_parameters.sol │ │ │ ├── errors.sol │ │ │ ├── errors_referenced.sol │ │ │ ├── event_emitted_from_foreign_contract.sol │ │ │ ├── event_emitted_in_base_contract.sol │ │ │ ├── event_file_level.sol │ │ │ ├── event_from_aggregated_contract_not_emitted.sol │ │ │ ├── event_inheritance.sol │ │ │ ├── event_structs.sol │ │ │ ├── events.sol │ │ │ ├── events_anonymous.sol │ │ │ ├── events_indirect.sol │ │ │ ├── events_repetitions.sol │ │ │ ├── function_type.sol │ │ │ ├── function_type_extended.sol │ │ │ ├── global_struct.sol │ │ │ ├── include_fallback_function.sol │ │ │ ├── inherited.sol │ │ │ ├── internal_constructor.sol │ │ │ ├── library_function.sol │ │ │ ├── mapping.sol │ │ │ ├── multiple_methods.sol │ │ │ ├── multiple_methods_order.sol │ │ │ ├── multiple_params.sol │ │ │ ├── payable_constructor_abi.sol │ │ │ ├── payable_fallback_function.sol │ │ │ ├── payable_function.sol │ │ │ ├── pure_function.sol │ │ │ ├── receive_ether_and_fallback_function.sol │ │ │ ├── receive_ether_function.sol │ │ │ ├── return_param_in_abi.sol │ │ │ ├── return_structs.sol │ │ │ ├── return_structs_with_contracts.sol │ │ │ ├── same_event_defined_twice.sol │ │ │ ├── structs_and_arrays.sol │ │ │ ├── structs_in_libraries.sol │ │ │ ├── user_defined_value_type.sol │ │ │ └── view_function.sol │ │ ├── ABIJsonTest.cpp │ │ ├── ABIJsonTest.h │ │ ├── ABITestsCommon.h │ │ ├── ASTJSON/ │ │ │ ├── abstract_contract.json │ │ │ ├── abstract_contract.sol │ │ │ ├── abstract_contract_parseOnly.json │ │ │ ├── address_payable.json │ │ │ ├── address_payable.sol │ │ │ ├── address_payable_parseOnly.json │ │ │ ├── array_type_name.json │ │ │ ├── array_type_name.sol │ │ │ ├── array_type_name_parseOnly.json │ │ │ ├── assembly/ │ │ │ │ ├── call.json │ │ │ │ ├── call.sol │ │ │ │ ├── call_legacy.json │ │ │ │ ├── call_parseOnly.json │ │ │ │ ├── empty_block.json │ │ │ │ ├── empty_block.sol │ │ │ │ ├── empty_block_legacy.json │ │ │ │ ├── empty_block_parseOnly.json │ │ │ │ ├── empty_let_variable_declaration.json │ │ │ │ ├── empty_let_variable_declaration.sol │ │ │ │ ├── empty_let_variable_declaration_parseOnly.json │ │ │ │ ├── function.json │ │ │ │ ├── function.sol │ │ │ │ ├── function_legacy.json │ │ │ │ ├── function_parseOnly.json │ │ │ │ ├── leave.json │ │ │ │ ├── leave.sol │ │ │ │ ├── leave_legacy.json │ │ │ │ ├── leave_parseOnly.json │ │ │ │ ├── loop.json │ │ │ │ ├── loop.sol │ │ │ │ ├── loop_legacy.json │ │ │ │ ├── loop_parseOnly.json │ │ │ │ ├── nested_functions.json │ │ │ │ ├── nested_functions.sol │ │ │ │ ├── nested_functions_legacy.json │ │ │ │ ├── nested_functions_parseOnly.json │ │ │ │ ├── slot_offset.json │ │ │ │ ├── slot_offset.sol │ │ │ │ ├── slot_offset_legacy.json │ │ │ │ ├── slot_offset_parseOnly.json │ │ │ │ ├── stringlit.json │ │ │ │ ├── stringlit.sol │ │ │ │ ├── stringlit_legacy.json │ │ │ │ ├── stringlit_parseOnly.json │ │ │ │ ├── switch.json │ │ │ │ ├── switch.sol │ │ │ │ ├── switch_default.json │ │ │ │ ├── switch_default.sol │ │ │ │ ├── switch_default_legacy.json │ │ │ │ ├── switch_default_parseOnly.json │ │ │ │ ├── switch_legacy.json │ │ │ │ ├── switch_parseOnly.json │ │ │ │ ├── var_access.json │ │ │ │ ├── var_access.sol │ │ │ │ ├── var_access_legacy.json │ │ │ │ └── var_access_parseOnly.json │ │ │ ├── ast_internal_function_different_ids_export.json │ │ │ ├── ast_internal_function_different_ids_export.sol │ │ │ ├── ast_internal_function_id_export.json │ │ │ ├── ast_internal_function_id_export.sol │ │ │ ├── base_constructor_call.json │ │ │ ├── base_constructor_call.sol │ │ │ ├── base_constructor_call_parseOnly.json │ │ │ ├── constructor.json │ │ │ ├── constructor.sol │ │ │ ├── constructor_parseOnly.json │ │ │ ├── contract_dep_order.json │ │ │ ├── contract_dep_order.sol │ │ │ ├── contract_dep_order_parseOnly.json │ │ │ ├── documentation.json │ │ │ ├── documentation.sol │ │ │ ├── documentation_local_variable.json │ │ │ ├── documentation_local_variable.sol │ │ │ ├── documentation_local_variable_parseOnly.json │ │ │ ├── documentation_on_statements.json │ │ │ ├── documentation_on_statements.sol │ │ │ ├── documentation_on_statements_parseOnly.json │ │ │ ├── documentation_parseOnly.json │ │ │ ├── documentation_triple.json │ │ │ ├── documentation_triple.sol │ │ │ ├── documentation_triple_parseOnly.json │ │ │ ├── emit_event_from_module_via_member_access.json │ │ │ ├── emit_event_from_module_via_member_access.sol │ │ │ ├── enum_natspec.json │ │ │ ├── enum_natspec.sol │ │ │ ├── enum_natspec_parseOnly.json │ │ │ ├── enum_value.json │ │ │ ├── enum_value.sol │ │ │ ├── enum_value_declaration.json │ │ │ ├── enum_value_declaration.sol │ │ │ ├── enum_value_declaration_parseOnly.json │ │ │ ├── enum_value_natspec.json │ │ │ ├── enum_value_natspec.sol │ │ │ ├── enum_value_natspec_parseOnly.json │ │ │ ├── enum_value_parseOnly.json │ │ │ ├── error_from_module_via_member_access.json │ │ │ ├── error_from_module_via_member_access.sol │ │ │ ├── event_aggregated_contract.json │ │ │ ├── event_aggregated_contract.sol │ │ │ ├── event_definition.json │ │ │ ├── event_definition.sol │ │ │ ├── event_definition_parseOnly.json │ │ │ ├── event_emited_in_base_contract.json │ │ │ ├── event_emited_in_base_contract.sol │ │ │ ├── event_emitted_from_foreign_contract.json │ │ │ ├── event_emitted_from_foreign_contract.sol │ │ │ ├── event_emitted_from_foreign_contract_parseOnly.json │ │ │ ├── event_inheritance.json │ │ │ ├── event_inheritance.sol │ │ │ ├── event_with_variables_of_internal_types.sol │ │ │ ├── event_with_variables_of_internal_types_parseOnly.json │ │ │ ├── fail_after_parsing.sol │ │ │ ├── fail_after_parsing_parseOnly.json │ │ │ ├── fallback.json │ │ │ ├── fallback.sol │ │ │ ├── fallback_and_receive_ether.json │ │ │ ├── fallback_and_receive_ether.sol │ │ │ ├── fallback_and_receive_ether_parseOnly.json │ │ │ ├── fallback_parseOnly.json │ │ │ ├── fallback_payable.json │ │ │ ├── fallback_payable.sol │ │ │ ├── fallback_payable_parseOnly.json │ │ │ ├── function_type.json │ │ │ ├── function_type.sol │ │ │ ├── function_type_parseOnly.json │ │ │ ├── global_enum.json │ │ │ ├── global_enum.sol │ │ │ ├── global_enum_parseOnly.json │ │ │ ├── global_struct.json │ │ │ ├── global_struct.sol │ │ │ ├── global_struct_parseOnly.json │ │ │ ├── indirect_event.json │ │ │ ├── indirect_event.sol │ │ │ ├── indirect_event_parseOnly.json │ │ │ ├── inheritance_specifier.json │ │ │ ├── inheritance_specifier.sol │ │ │ ├── inheritance_specifier_parseOnly.json │ │ │ ├── license.json │ │ │ ├── license.sol │ │ │ ├── license_parseOnly.json │ │ │ ├── long_type_name_binary_operation.json │ │ │ ├── long_type_name_binary_operation.sol │ │ │ ├── long_type_name_binary_operation_parseOnly.json │ │ │ ├── long_type_name_identifier.json │ │ │ ├── long_type_name_identifier.sol │ │ │ ├── long_type_name_identifier_parseOnly.json │ │ │ ├── mappings.json │ │ │ ├── mappings.sol │ │ │ ├── mappings_parseOnly.json │ │ │ ├── modifier_definition.json │ │ │ ├── modifier_definition.sol │ │ │ ├── modifier_definition_parseOnly.json │ │ │ ├── modifier_invocation.json │ │ │ ├── modifier_invocation.sol │ │ │ ├── modifier_invocation_parseOnly.json │ │ │ ├── mutability.json │ │ │ ├── mutability.sol │ │ │ ├── mutability_parseOnly.json │ │ │ ├── non_utf8.json │ │ │ ├── non_utf8.sol │ │ │ ├── non_utf8_parseOnly.json │ │ │ ├── not_existing_import.sol │ │ │ ├── not_existing_import_parseOnly.json │ │ │ ├── override.json │ │ │ ├── override.sol │ │ │ ├── override_parseOnly.json │ │ │ ├── placeholder_statement.json │ │ │ ├── placeholder_statement.sol │ │ │ ├── placeholder_statement_parseOnly.json │ │ │ ├── pragma_experimental_solidity.sol │ │ │ ├── pragma_experimental_solidity_parseOnly.json │ │ │ ├── receive_ether.json │ │ │ ├── receive_ether.sol │ │ │ ├── receive_ether_parseOnly.json │ │ │ ├── short_type_name.json │ │ │ ├── short_type_name.sol │ │ │ ├── short_type_name_parseOnly.json │ │ │ ├── short_type_name_ref.json │ │ │ ├── short_type_name_ref.sol │ │ │ ├── short_type_name_ref_parseOnly.json │ │ │ ├── smoke.json │ │ │ ├── smoke.sol │ │ │ ├── smoke_parseOnly.json │ │ │ ├── source_location.json │ │ │ ├── source_location.sol │ │ │ ├── source_location_parseOnly.json │ │ │ ├── storage_layout_specifier.json │ │ │ ├── storage_layout_specifier.sol │ │ │ ├── string.json │ │ │ ├── string.sol │ │ │ ├── string_parseOnly.json │ │ │ ├── struct_natspec.json │ │ │ ├── struct_natspec.sol │ │ │ ├── struct_natspec_parseOnly.json │ │ │ ├── two_base_functions.json │ │ │ ├── two_base_functions.sol │ │ │ ├── two_base_functions_parseOnly.json │ │ │ ├── unicode.json │ │ │ ├── unicode.sol │ │ │ ├── unicode_parseOnly.json │ │ │ ├── used_errors.json │ │ │ ├── used_errors.sol │ │ │ ├── used_errors_parseOnly.json │ │ │ ├── userDefinedValueType.json │ │ │ ├── userDefinedValueType.sol │ │ │ ├── userDefinedValueType_parseOnly.json │ │ │ ├── user_defined_operator.json │ │ │ ├── user_defined_operator.sol │ │ │ ├── using_for_directive.json │ │ │ ├── using_for_directive.sol │ │ │ ├── using_for_directive_parseOnly.json │ │ │ ├── yul_hex_literal.json │ │ │ ├── yul_hex_literal.sol │ │ │ └── yul_hex_literal_parseOnly.json │ │ ├── ASTJSONTest.cpp │ │ ├── ASTJSONTest.h │ │ ├── ASTPropertyTest.cpp │ │ ├── ASTPropertyTest.h │ │ ├── AnalysisFramework.cpp │ │ ├── AnalysisFramework.h │ │ ├── Assembly.cpp │ │ ├── ErrorCheck.cpp │ │ ├── ErrorCheck.h │ │ ├── FunctionDependencyGraphTest.cpp │ │ ├── FunctionDependencyGraphTest.h │ │ ├── GasCosts.cpp │ │ ├── GasMeter.cpp │ │ ├── GasTest.cpp │ │ ├── GasTest.h │ │ ├── Imports.cpp │ │ ├── InlineAssembly.cpp │ │ ├── LibSolc.cpp │ │ ├── MemoryGuardTest.cpp │ │ ├── MemoryGuardTest.h │ │ ├── Metadata.cpp │ │ ├── NatspecJSONTest.cpp │ │ ├── NatspecJSONTest.h │ │ ├── OptimizedIRCachingTest.cpp │ │ ├── OptimizedIRCachingTest.h │ │ ├── SMTCheckerTest.cpp │ │ ├── SMTCheckerTest.h │ │ ├── SemVerMatcher.cpp │ │ ├── SemanticTest.cpp │ │ ├── SemanticTest.h │ │ ├── SolidityCompiler.cpp │ │ ├── SolidityEndToEndTest.cpp │ │ ├── SolidityExecutionFramework.cpp │ │ ├── SolidityExecutionFramework.h │ │ ├── SolidityExpressionCompiler.cpp │ │ ├── SolidityNameAndTypeResolution.cpp │ │ ├── SolidityOptimizer.cpp │ │ ├── SolidityParser.cpp │ │ ├── SolidityTypes.cpp │ │ ├── StandardCompiler.cpp │ │ ├── SyntaxTest.cpp │ │ ├── SyntaxTest.h │ │ ├── ViewPureChecker.cpp │ │ ├── analysis/ │ │ │ └── FunctionCallGraph.cpp │ │ ├── astPropertyTests/ │ │ │ ├── blank_test_case.sol │ │ │ ├── forLoop/ │ │ │ │ ├── isSimpleCounterLoop_negative_cases.sol │ │ │ │ └── isSimpleCounterLoop_positive_cases.sol │ │ │ ├── multiple_nested_properties_per_node.sol │ │ │ ├── multiple_properties_per_node.sol │ │ │ ├── nested_properties.sol │ │ │ ├── property_expectation_with_colon.sol │ │ │ ├── simple_properties.sol │ │ │ └── transient_data_location.sol │ │ ├── functionDependencyGraphTests/ │ │ │ ├── callgraph.sol │ │ │ └── callgraph_no_leaves.sol │ │ ├── gasTests/ │ │ │ ├── abiv2.sol │ │ │ ├── abiv2_optimised.sol │ │ │ ├── data_storage.sol │ │ │ ├── dispatch_large.sol │ │ │ ├── dispatch_large_optimised.sol │ │ │ ├── dispatch_medium.sol │ │ │ ├── dispatch_medium_optimised.sol │ │ │ ├── dispatch_small.sol │ │ │ ├── dispatch_small_optimised.sol │ │ │ ├── exp.sol │ │ │ ├── exp_optimized.sol │ │ │ └── storage_costs.sol │ │ ├── interface/ │ │ │ └── FileReader.cpp │ │ ├── lsp/ │ │ │ ├── analyze-full-project/ │ │ │ │ ├── C.sol │ │ │ │ ├── D.sol │ │ │ │ └── E.sol │ │ │ ├── didChange_template.sol │ │ │ ├── didOpen_with_import.sol │ │ │ ├── goto/ │ │ │ │ ├── goto_definition.sol │ │ │ │ ├── goto_definition_imports.sol │ │ │ │ ├── lib.sol │ │ │ │ ├── publish_diagnostics_1.sol │ │ │ │ └── publish_diagnostics_2.sol │ │ │ ├── hover/ │ │ │ │ └── hover.sol │ │ │ ├── include-paths/ │ │ │ │ ├── default_include.sol │ │ │ │ ├── file_at_include_path.sol │ │ │ │ ├── file_not_found_in_searchpath.sol │ │ │ │ └── using-custom-includes.sol │ │ │ ├── include-paths-nested/ │ │ │ │ ├── A/ │ │ │ │ │ ├── B/ │ │ │ │ │ │ ├── C/ │ │ │ │ │ │ │ └── foo.sol │ │ │ │ │ │ └── foo.sol │ │ │ │ │ └── foo.sol │ │ │ │ └── foo.sol │ │ │ ├── include-paths-nested-2/ │ │ │ │ ├── A/ │ │ │ │ │ ├── B/ │ │ │ │ │ │ ├── C/ │ │ │ │ │ │ │ └── foo.sol │ │ │ │ │ │ └── foo.sol │ │ │ │ │ └── foo.sol │ │ │ │ └── foo.sol │ │ │ ├── other-include-dir/ │ │ │ │ └── otherlib/ │ │ │ │ ├── otherlib.sol │ │ │ │ └── second.sol │ │ │ ├── publish_diagnostics_3.sol │ │ │ ├── rename/ │ │ │ │ ├── contract.sol │ │ │ │ ├── function.sol │ │ │ │ ├── functionCall.sol │ │ │ │ ├── import_directive.sol │ │ │ │ └── variable.sol │ │ │ └── semanticTokens/ │ │ │ ├── enums.sol │ │ │ ├── functions.sol │ │ │ ├── modifiers.sol │ │ │ └── structs.sol │ │ ├── memoryGuardTests/ │ │ │ ├── comment/ │ │ │ │ ├── constructor_safe_deploy_unsafe.sol │ │ │ │ ├── constructor_unsafe_deploy_safe.sol │ │ │ │ ├── free_function.sol │ │ │ │ ├── multi_annotation.sol │ │ │ │ ├── multiple_contracts.sol │ │ │ │ ├── safe_and_unmarked_empty.sol │ │ │ │ └── safe_and_unmarked_unsafe.sol │ │ │ ├── dialectString/ │ │ │ │ ├── constructor_safe_deploy_unsafe.sol │ │ │ │ ├── constructor_unsafe_deploy_safe.sol │ │ │ │ ├── free_function.sol │ │ │ │ ├── multiple_contracts.sol │ │ │ │ ├── safe_and_unmarked_empty.sol │ │ │ │ ├── safe_and_unmarked_unsafe.sol │ │ │ │ └── stub.sol │ │ │ ├── marked_empty.sol │ │ │ ├── marked_with_memory_access.sol │ │ │ ├── shadowing_memoryguard_with_inline_assembly_identifiers.sol │ │ │ ├── stub.sol │ │ │ ├── unmarked_but_no_memory_access.sol │ │ │ ├── unmarked_empty.sol │ │ │ ├── unmarked_with_memory_access_mcopy.sol │ │ │ ├── unmarked_with_memory_access_mcopy_zero_size.sol │ │ │ ├── unmarked_with_memory_access_mstore.sol │ │ │ └── unmarked_with_memory_assignment.sol │ │ ├── natspecJSON/ │ │ │ ├── custom.sol │ │ │ ├── custom_inheritance.sol │ │ │ ├── dev_and_user_basic_test.sol │ │ │ ├── dev_and_user_no_doc.sol │ │ │ ├── dev_author_at_function.sol │ │ │ ├── dev_constructor.sol │ │ │ ├── dev_constructor_and_function.sol │ │ │ ├── dev_constructor_return.sol │ │ │ ├── dev_contract_doc.sol │ │ │ ├── dev_contract_no_doc.sol │ │ │ ├── dev_default_inherit.sol │ │ │ ├── dev_default_inherit_variable.sol │ │ │ ├── dev_desc_after_nl.sol │ │ │ ├── dev_different_return_name.sol │ │ │ ├── dev_different_return_name_multiple.sol │ │ │ ├── dev_different_return_name_multiple_partly_unnamed.sol │ │ │ ├── dev_different_return_name_multiple_unnamed.sol │ │ │ ├── dev_documenting_no_param_description.sol │ │ │ ├── dev_documenting_no_param_name.sol │ │ │ ├── dev_documenting_no_param_name_end.sol │ │ │ ├── dev_documenting_no_return_param_name.sol │ │ │ ├── dev_documenting_nonexistent_param.sol │ │ │ ├── dev_explicit_inherit.sol │ │ │ ├── dev_explicit_inherit2.sol │ │ │ ├── dev_explicit_inherit_complex.sol │ │ │ ├── dev_explicit_inherit_partial.sol │ │ │ ├── dev_explicit_inherit_partial2.sol │ │ │ ├── dev_explicit_inherit_variable.sol │ │ │ ├── dev_inherit_parameter_mismatch.sol │ │ │ ├── dev_multiline_comment.sol │ │ │ ├── dev_multiline_param_description.sol │ │ │ ├── dev_multiline_return.sol │ │ │ ├── dev_multiple_functions.sol │ │ │ ├── dev_multiple_params.sol │ │ │ ├── dev_multiple_params_mixed_whitespace.sol │ │ │ ├── dev_return.sol │ │ │ ├── dev_return_desc_after_nl.sol │ │ │ ├── dev_return_desc_multiple.sol │ │ │ ├── dev_return_desc_multiple_unnamed.sol │ │ │ ├── dev_return_desc_multiple_unnamed_mixed.sol │ │ │ ├── dev_return_desc_multiple_unnamed_mixed_2.sol │ │ │ ├── dev_return_name_no_description.sol │ │ │ ├── dev_return_no_params.sol │ │ │ ├── dev_struct_getter_override.sol │ │ │ ├── dev_struct_getter_override_different_return_parameter_names.sol │ │ │ ├── dev_struct_getter_override_no_return_name.sol │ │ │ ├── dev_title_at_function_error.sol │ │ │ ├── docstring_double_empty.sol │ │ │ ├── docstring_named_return_parameter.sol │ │ │ ├── docstring_parameter.sol │ │ │ ├── docstring_private_state_variable.sol │ │ │ ├── docstring_state_variable.sol │ │ │ ├── docstring_struct.sol │ │ │ ├── docstring_variable.sol │ │ │ ├── emit_event_from_foreign_contract.sol │ │ │ ├── emit_event_from_foreign_contract_no_inheritance.sol │ │ │ ├── emit_event_from_foreign_contract_with_same_signature.sol │ │ │ ├── emit_event_from_module_via_member_access.sol │ │ │ ├── emit_file_level_event.sol │ │ │ ├── emit_file_level_event_inheritance.sol │ │ │ ├── emit_file_level_event_with_same_signature_as_foreign_event.sol │ │ │ ├── emit_same_signature_event_different_libraries.sol │ │ │ ├── emit_same_signature_event_different_libraries_missing_natspec.sol │ │ │ ├── emit_same_signature_event_library_contract.sol │ │ │ ├── emit_same_signature_event_library_contract_missing_natspec.sol │ │ │ ├── emit_same_signature_event_library_inherited.sol │ │ │ ├── emit_same_signature_event_library_inherited_missing_natspec.sol │ │ │ ├── empty_comment.sol │ │ │ ├── enum.sol │ │ │ ├── enum_value.sol │ │ │ ├── error.sol │ │ │ ├── error_from_module_via_member_access.sol │ │ │ ├── error_multiple.sol │ │ │ ├── event.sol │ │ │ ├── event_inheritance.sol │ │ │ ├── event_inheritance_interface.sol │ │ │ ├── invalid/ │ │ │ │ ├── docstring_author_function.sol │ │ │ │ ├── docstring_author_title_state_variable.sol │ │ │ │ ├── docstring_empty_description.sol │ │ │ │ ├── docstring_empty_tag.sol │ │ │ │ ├── docstring_inherit_modifier_no_return.sol │ │ │ │ ├── docstring_inherit_modifier_no_return2.sol │ │ │ │ ├── docstring_inheritdoc.sol │ │ │ │ ├── docstring_inheritdoc2.sol │ │ │ │ ├── docstring_inheritdoc3.sol │ │ │ │ ├── docstring_inheritdoc_emptys.sol │ │ │ │ ├── docstring_inheritdoc_twice.sol │ │ │ │ ├── docstring_inheritdoc_wrong_type.sol │ │ │ │ ├── docstring_named_return_param_mismatch.sol │ │ │ │ ├── docstring_non_public_state_variable_with_return.sol │ │ │ │ ├── docstring_parameter.sol │ │ │ │ ├── docstring_return_size_mismatch.sol │ │ │ │ ├── docstring_state_variable_too_many_return_tags.sol │ │ │ │ ├── docstring_too_many_return_tags.sol │ │ │ │ ├── inherit_doc_events.sol │ │ │ │ └── invalid_tag.sol │ │ │ ├── multiline_notice_without_tag.sol │ │ │ ├── notice_without_tag.sol │ │ │ ├── private_state_variable.sol │ │ │ ├── public_state_variable.sol │ │ │ ├── public_state_variable_struct.sol │ │ │ ├── public_state_variable_struct_repeated.sol │ │ │ ├── return_param_amount_differs.sol │ │ │ ├── return_param_amount_differs2.sol │ │ │ ├── slash3_slash3.sol │ │ │ ├── slash3_slash4.sol │ │ │ ├── slash4.sol │ │ │ ├── star3.sol │ │ │ ├── storage_layout_specifier_no_doc.sol │ │ │ ├── struct_no_docs.sol │ │ │ ├── unused_file_level_event.sol │ │ │ ├── user_basic_test.sol │ │ │ ├── user_constructor.sol │ │ │ ├── user_constructor_and_function.sol │ │ │ ├── user_default_inherit.sol │ │ │ ├── user_default_inherit_variable.sol │ │ │ ├── user_empty_contract.sol │ │ │ ├── user_empty_natspec_test.sol │ │ │ ├── user_explicit_inherit.sol │ │ │ ├── user_explicit_inherit2.sol │ │ │ ├── user_explicit_inherit_partial.sol │ │ │ ├── user_explicit_inherit_partial2.sol │ │ │ ├── user_explicit_inherit_variable.sol │ │ │ ├── user_inherit_parameter_mismatch.sol │ │ │ ├── user_multiline_comment.sol │ │ │ ├── user_multiline_empty_lines.sol │ │ │ ├── user_multiple_functions.sol │ │ │ └── user_newline_break.sol │ │ ├── optimizedIRCaching/ │ │ │ ├── bytecode_dependency_creation.sol │ │ │ ├── bytecode_dependency_creation_and_runtime.sol │ │ │ ├── bytecode_dependency_creation_and_runtime_shared.sol │ │ │ ├── bytecode_dependency_runtime.sol │ │ │ ├── bytecode_dependency_shared_by_multiple_contracts.sol │ │ │ ├── multiple_contracts.sol │ │ │ ├── no_contracts.sol │ │ │ └── single_contract.sol │ │ ├── semanticTests/ │ │ │ ├── abiEncodeDecode/ │ │ │ │ ├── abi_decode_calldata.sol │ │ │ │ ├── abi_decode_simple.sol │ │ │ │ ├── abi_decode_simple_storage.sol │ │ │ │ ├── abi_encode_call.sol │ │ │ │ ├── abi_encode_call_declaration.sol │ │ │ │ ├── abi_encode_call_is_consistent.sol │ │ │ │ ├── abi_encode_call_memory.sol │ │ │ │ ├── abi_encode_call_special_args.sol │ │ │ │ ├── abi_encode_call_uint_bytes.sol │ │ │ │ ├── abi_encode_empty_string_v1.sol │ │ │ │ ├── abi_encode_with_selector.sol │ │ │ │ ├── abi_encode_with_selectorv2.sol │ │ │ │ ├── abi_encode_with_signature.sol │ │ │ │ ├── abi_encode_with_signaturev2.sol │ │ │ │ ├── contract_array.sol │ │ │ │ ├── contract_array_v2.sol │ │ │ │ ├── offset_overflow_in_array_decoding.sol │ │ │ │ ├── offset_overflow_in_array_decoding_2.sol │ │ │ │ └── offset_overflow_in_array_decoding_3.sol │ │ │ ├── abiEncoderV1/ │ │ │ │ ├── abi_decode_dynamic_array.sol │ │ │ │ ├── abi_decode_fixed_arrays.sol │ │ │ │ ├── abi_decode_static_array.sol │ │ │ │ ├── abi_decode_static_array_v2.sol │ │ │ │ ├── abi_decode_trivial.sol │ │ │ │ ├── abi_decode_v2.sol │ │ │ │ ├── abi_decode_v2_calldata.sol │ │ │ │ ├── abi_decode_v2_storage.sol │ │ │ │ ├── abi_encode.sol │ │ │ │ ├── abi_encode_call.sol │ │ │ │ ├── abi_encode_calldata_slice.sol │ │ │ │ ├── abi_encode_decode_simple.sol │ │ │ │ ├── abi_encode_empty_string.sol │ │ │ │ ├── abi_encode_rational.sol │ │ │ │ ├── bool_out_of_bounds.sol │ │ │ │ ├── byte_arrays.sol │ │ │ │ ├── calldata_arrays_too_large.sol │ │ │ │ ├── calldata_bytes_bytes32_arrays.sol │ │ │ │ ├── cleanup/ │ │ │ │ │ └── cleanup.sol │ │ │ │ ├── decode_slice.sol │ │ │ │ ├── dynamic_arrays.sol │ │ │ │ ├── dynamic_memory_copy.sol │ │ │ │ ├── enums.sol │ │ │ │ ├── memory_dynamic_array_and_calldata_bytes.sol │ │ │ │ ├── memory_params_in_external_function.sol │ │ │ │ ├── return_dynamic_types_cross_call_advanced.sol │ │ │ │ ├── return_dynamic_types_cross_call_out_of_range_1.sol │ │ │ │ ├── return_dynamic_types_cross_call_out_of_range_2.sol │ │ │ │ ├── return_dynamic_types_cross_call_simple.sol │ │ │ │ └── struct/ │ │ │ │ └── struct_storage_ptr.sol │ │ │ ├── abiEncoderV2/ │ │ │ │ ├── abi_encode_calldata_slice.sol │ │ │ │ ├── abi_encode_empty_string_v2.sol │ │ │ │ ├── abi_encode_rational_v2.sol │ │ │ │ ├── abi_encode_v2.sol │ │ │ │ ├── abi_encode_v2_in_function_inherited_in_v1_contract.sol │ │ │ │ ├── abi_encode_v2_in_modifier_used_in_v1_contract.sol │ │ │ │ ├── abi_encoder_v2_head_overflow_with_static_array_cleanup_bug.sol │ │ │ │ ├── bool_out_of_bounds.sol │ │ │ │ ├── byte_arrays.sol │ │ │ │ ├── calldata_array.sol │ │ │ │ ├── calldata_array_dynamic.sol │ │ │ │ ├── calldata_array_dynamic_index_access.sol │ │ │ │ ├── calldata_array_dynamic_static_dynamic.sol │ │ │ │ ├── calldata_array_dynamic_static_in_library.sol │ │ │ │ ├── calldata_array_dynamic_static_short_decode.sol │ │ │ │ ├── calldata_array_dynamic_static_short_reencode.sol │ │ │ │ ├── calldata_array_function_types.sol │ │ │ │ ├── calldata_array_multi_dynamic.sol │ │ │ │ ├── calldata_array_short.sol │ │ │ │ ├── calldata_array_short_no_revert_string.sol │ │ │ │ ├── calldata_array_static.sol │ │ │ │ ├── calldata_array_static_dynamic_static.sol │ │ │ │ ├── calldata_array_static_index_access.sol │ │ │ │ ├── calldata_array_struct_dynamic.sol │ │ │ │ ├── calldata_array_two_dynamic.sol │ │ │ │ ├── calldata_array_two_static.sol │ │ │ │ ├── calldata_dynamic_array_to_memory.sol │ │ │ │ ├── calldata_nested_array_reencode.sol │ │ │ │ ├── calldata_nested_array_static_reencode.sol │ │ │ │ ├── calldata_overlapped_dynamic_arrays.sol │ │ │ │ ├── calldata_overlapped_nested_dynamic_arrays.sol │ │ │ │ ├── calldata_struct_array_reencode.sol │ │ │ │ ├── calldata_struct_dynamic.sol │ │ │ │ ├── calldata_struct_member_offset.sol │ │ │ │ ├── calldata_struct_simple.sol │ │ │ │ ├── calldata_three_dimensional_dynamic_array_index_access.sol │ │ │ │ ├── calldata_with_garbage.sol │ │ │ │ ├── cleanup/ │ │ │ │ │ ├── address.sol │ │ │ │ │ ├── bool.sol │ │ │ │ │ ├── bytesx.sol │ │ │ │ │ ├── cleanup.sol │ │ │ │ │ ├── dynamic_array.sol │ │ │ │ │ ├── function.sol │ │ │ │ │ ├── intx.sol │ │ │ │ │ ├── reencoded_calldata_string.sol │ │ │ │ │ ├── simple_struct.sol │ │ │ │ │ ├── static_array.sol │ │ │ │ │ └── uintx.sol │ │ │ │ ├── dynamic_arrays.sol │ │ │ │ ├── dynamic_nested_arrays.sol │ │ │ │ ├── enums.sol │ │ │ │ ├── memory_dynamic_array_and_calldata_bytes.sol │ │ │ │ ├── memory_dynamic_array_and_calldata_static_array.sol │ │ │ │ ├── memory_params_in_external_function.sol │ │ │ │ ├── storage_array_encoding.sol │ │ │ │ └── struct/ │ │ │ │ ├── mediocre2_struct.sol │ │ │ │ ├── mediocre_struct.sol │ │ │ │ ├── struct_function.sol │ │ │ │ ├── struct_short.sol │ │ │ │ ├── struct_simple.sol │ │ │ │ ├── struct_validation.sol │ │ │ │ └── validation_function_type_inside_struct.sol │ │ │ ├── accessor/ │ │ │ │ ├── accessor_for_const_state_variable.sol │ │ │ │ └── accessor_for_state_variable.sol │ │ │ ├── arithmetics/ │ │ │ │ ├── addmod_mulmod.sol │ │ │ │ ├── addmod_mulmod_zero.sol │ │ │ │ ├── block_inside_unchecked.sol │ │ │ │ ├── check_var_init.sol │ │ │ │ ├── checked_add_v1.sol │ │ │ │ ├── checked_add_v2.sol │ │ │ │ ├── checked_called_by_unchecked.sol │ │ │ │ ├── checked_modifier_called_by_unchecked.sol │ │ │ │ ├── divisiod_by_zero.sol │ │ │ │ ├── exp_associativity.sol │ │ │ │ ├── signed_mod.sol │ │ │ │ ├── unchecked_called_by_checked.sol │ │ │ │ └── unchecked_div_by_zero.sol │ │ │ ├── array/ │ │ │ │ ├── arrayMemoryAllocation/ │ │ │ │ │ ├── array_2d_zeroed_memory_index_access.sol │ │ │ │ │ ├── array_array_static.sol │ │ │ │ │ ├── array_static_return_param_zeroed_memory_index_access.sol │ │ │ │ │ ├── array_static_zeroed_memory_index_access.sol │ │ │ │ │ └── array_zeroed_memory_index_access.sol │ │ │ │ ├── array_2d_assignment.sol │ │ │ │ ├── array_2d_new.sol │ │ │ │ ├── array_3d_assignment.sol │ │ │ │ ├── array_3d_new.sol │ │ │ │ ├── array_function_pointers.sol │ │ │ │ ├── array_memory_as_parameter.sol │ │ │ │ ├── array_memory_create.sol │ │ │ │ ├── array_memory_index_access.sol │ │ │ │ ├── array_push_return_reference.sol │ │ │ │ ├── array_push_with_arg.sol │ │ │ │ ├── array_storage_index_access.sol │ │ │ │ ├── array_storage_index_boundary_test.sol │ │ │ │ ├── array_storage_index_zeroed_test.sol │ │ │ │ ├── array_storage_length_access.sol │ │ │ │ ├── array_storage_pop_zero_length.sol │ │ │ │ ├── array_storage_push_empty.sol │ │ │ │ ├── array_storage_push_empty_length_address.sol │ │ │ │ ├── array_storage_push_pop.sol │ │ │ │ ├── arrays_complex_from_and_to_storage.sol │ │ │ │ ├── byte_array_storage_layout.sol │ │ │ │ ├── byte_array_transitional_2.sol │ │ │ │ ├── bytes_length_member.sol │ │ │ │ ├── bytes_to_fixed_bytes_cleanup.sol │ │ │ │ ├── bytes_to_fixed_bytes_simple.sol │ │ │ │ ├── bytes_to_fixed_bytes_too_long.sol │ │ │ │ ├── calldata_array.sol │ │ │ │ ├── calldata_array_as_argument_internal_function.sol │ │ │ │ ├── calldata_array_dynamic_invalid.sol │ │ │ │ ├── calldata_array_dynamic_invalid_static_middle.sol │ │ │ │ ├── calldata_array_of_struct.sol │ │ │ │ ├── calldata_array_two_dimensional.sol │ │ │ │ ├── calldata_array_two_dimensional_1.sol │ │ │ │ ├── calldata_bytes_array_bounds.sol │ │ │ │ ├── calldata_slice_access.sol │ │ │ │ ├── concat/ │ │ │ │ │ ├── bytes_concat_2_args.sol │ │ │ │ │ ├── bytes_concat_3_args.sol │ │ │ │ │ ├── bytes_concat_as_argument.sol │ │ │ │ │ ├── bytes_concat_different_types.sol │ │ │ │ │ ├── bytes_concat_empty_argument_list.sol │ │ │ │ │ ├── bytes_concat_empty_strings.sol │ │ │ │ │ └── bytes_concat_nested.sol │ │ │ │ ├── constant_var_as_array_length.sol │ │ │ │ ├── copying/ │ │ │ │ │ ├── array_copy_calldata_storage.sol │ │ │ │ │ ├── array_copy_cleanup_uint128.sol │ │ │ │ │ ├── array_copy_cleanup_uint40.sol │ │ │ │ │ ├── array_copy_clear_storage.sol │ │ │ │ │ ├── array_copy_clear_storage_packed.sol │ │ │ │ │ ├── array_copy_different_packing.sol │ │ │ │ │ ├── array_copy_including_array.sol │ │ │ │ │ ├── array_copy_memory_to_storage.sol │ │ │ │ │ ├── array_copy_nested_array.sol │ │ │ │ │ ├── array_copy_storage_abi_signed.sol │ │ │ │ │ ├── array_copy_storage_storage_different_base.sol │ │ │ │ │ ├── array_copy_storage_storage_different_base_nested.sol │ │ │ │ │ ├── array_copy_storage_storage_dyn_dyn.sol │ │ │ │ │ ├── array_copy_storage_storage_dynamic_dynamic.sol │ │ │ │ │ ├── array_copy_storage_storage_static_dynamic.sol │ │ │ │ │ ├── array_copy_storage_storage_static_simple.sol │ │ │ │ │ ├── array_copy_storage_storage_static_static.sol │ │ │ │ │ ├── array_copy_storage_storage_struct.sol │ │ │ │ │ ├── array_copy_storage_to_memory.sol │ │ │ │ │ ├── array_copy_storage_to_memory_nested.sol │ │ │ │ │ ├── array_copy_target_leftover.sol │ │ │ │ │ ├── array_copy_target_leftover2.sol │ │ │ │ │ ├── array_copy_target_simple.sol │ │ │ │ │ ├── array_copy_target_simple_2.sol │ │ │ │ │ ├── array_elements_to_mapping.sol │ │ │ │ │ ├── array_nested_calldata_to_memory.sol │ │ │ │ │ ├── array_nested_calldata_to_storage.sol │ │ │ │ │ ├── array_nested_memory_to_storage.sol │ │ │ │ │ ├── array_nested_storage_to_memory.sol │ │ │ │ │ ├── array_of_function_external_storage_to_storage_dynamic.sol │ │ │ │ │ ├── array_of_function_external_storage_to_storage_dynamic_different_mutability.sol │ │ │ │ │ ├── array_of_struct_calldata_to_memory.sol │ │ │ │ │ ├── array_of_struct_calldata_to_storage.sol │ │ │ │ │ ├── array_of_struct_memory_to_storage.sol │ │ │ │ │ ├── array_of_structs_containing_arrays_calldata_to_memory.sol │ │ │ │ │ ├── array_of_structs_containing_arrays_calldata_to_storage.sol │ │ │ │ │ ├── array_of_structs_containing_arrays_memory_to_storage.sol │ │ │ │ │ ├── array_storage_multi_items_per_slot.sol │ │ │ │ │ ├── array_to_mapping.sol │ │ │ │ │ ├── arrays_from_and_to_storage.sol │ │ │ │ │ ├── bytes_calldata_to_string_calldata.sol │ │ │ │ │ ├── bytes_inside_mappings.sol │ │ │ │ │ ├── bytes_memory_to_storage.sol │ │ │ │ │ ├── bytes_storage_to_memory.sol │ │ │ │ │ ├── bytes_storage_to_storage.sol │ │ │ │ │ ├── calldata_1d_array_into_2d_memory_array_element.sol │ │ │ │ │ ├── calldata_2d_bytes_to_memory.sol │ │ │ │ │ ├── calldata_2d_bytes_to_memory_2.sol │ │ │ │ │ ├── calldata_array_dynamic_to_storage.sol │ │ │ │ │ ├── calldata_array_of_struct_to_memory.sol │ │ │ │ │ ├── calldata_array_static_to_memory.sol │ │ │ │ │ ├── calldata_array_to_mapping.sol │ │ │ │ │ ├── calldata_bytes_array_to_memory.sol │ │ │ │ │ ├── calldata_bytes_to_storage.sol │ │ │ │ │ ├── calldata_dyn_2d_bytes_to_memory.sol │ │ │ │ │ ├── calldata_dynamic_array_to_memory.sol │ │ │ │ │ ├── calldata_nested_array_copy_to_memory.sol │ │ │ │ │ ├── calldata_to_storage_different_base.sol │ │ │ │ │ ├── cleanup_during_multi_element_per_slot_copy.sol │ │ │ │ │ ├── copy_byte_array_in_struct_to_storage.sol │ │ │ │ │ ├── copy_byte_array_to_storage.sol │ │ │ │ │ ├── copy_function_internal_storage_array.sol │ │ │ │ │ ├── copy_internal_function_array_to_storage.sol │ │ │ │ │ ├── copy_removes_bytes_data.sol │ │ │ │ │ ├── copying_bytes_multiassign.sol │ │ │ │ │ ├── dirty_memory_bytes_to_storage_copy.sol │ │ │ │ │ ├── dirty_memory_bytes_to_storage_copy_ir.sol │ │ │ │ │ ├── elements_of_nested_array_of_structs_calldata_to_storage.sol │ │ │ │ │ ├── elements_of_nested_array_of_structs_memory_to_storage.sol │ │ │ │ │ ├── empty_bytes_copy.sol │ │ │ │ │ ├── function_type_array_to_storage.sol │ │ │ │ │ ├── memory_dyn_2d_bytes_to_storage.sol │ │ │ │ │ ├── memory_to_storage_different_base.sol │ │ │ │ │ ├── nested_array_element_calldata_to_memory.sol │ │ │ │ │ ├── nested_array_element_calldata_to_storage.sol │ │ │ │ │ ├── nested_array_element_memory_to_memory.sol │ │ │ │ │ ├── nested_array_element_memory_to_storage.sol │ │ │ │ │ ├── nested_array_element_storage_to_memory.sol │ │ │ │ │ ├── nested_array_element_storage_to_storage.sol │ │ │ │ │ ├── nested_array_of_structs_calldata_to_memory.sol │ │ │ │ │ ├── nested_array_of_structs_calldata_to_storage.sol │ │ │ │ │ ├── nested_array_of_structs_memory_to_memory.sol │ │ │ │ │ ├── nested_array_of_structs_memory_to_storage.sol │ │ │ │ │ ├── nested_array_of_structs_storage_to_storage.sol │ │ │ │ │ ├── nested_array_of_structs_with_nested_array_from_storage_to_memory.sol │ │ │ │ │ ├── nested_dynamic_array_element_calldata_to_storage.sol │ │ │ │ │ ├── storage_memory_nested.sol │ │ │ │ │ ├── storage_memory_nested_bytes.sol │ │ │ │ │ ├── storage_memory_nested_from_pointer.sol │ │ │ │ │ ├── storage_memory_nested_struct.sol │ │ │ │ │ ├── storage_memory_packed.sol │ │ │ │ │ ├── storage_memory_packed_dyn.sol │ │ │ │ │ └── string_calldata_to_bytes_calldata.sol │ │ │ │ ├── create_dynamic_array_with_zero_length.sol │ │ │ │ ├── create_memory_array.sol │ │ │ │ ├── create_memory_array_too_large.sol │ │ │ │ ├── create_memory_byte_array.sol │ │ │ │ ├── create_multiple_dynamic_arrays.sol │ │ │ │ ├── delete/ │ │ │ │ │ ├── bytes_delete_element.sol │ │ │ │ │ ├── delete_bytes_array.sol │ │ │ │ │ ├── delete_memory_array.sol │ │ │ │ │ ├── delete_on_array_of_structs.sol │ │ │ │ │ ├── delete_removes_bytes_data.sol │ │ │ │ │ ├── delete_storage_array.sol │ │ │ │ │ ├── delete_storage_array_packed.sol │ │ │ │ │ └── memory_arrays_delete.sol │ │ │ │ ├── dynamic_array_cleanup.sol │ │ │ │ ├── dynamic_arrays_in_storage.sol │ │ │ │ ├── dynamic_multi_array_cleanup.sol │ │ │ │ ├── dynamic_out_of_bounds_array_access.sol │ │ │ │ ├── evm_exceptions_out_of_band_access.sol │ │ │ │ ├── external_array_args.sol │ │ │ │ ├── fixed_array_cleanup.sol │ │ │ │ ├── fixed_arrays_as_return_type.sol │ │ │ │ ├── fixed_arrays_in_constructors.sol │ │ │ │ ├── fixed_arrays_in_storage.sol │ │ │ │ ├── fixed_bytes_length_access.sol │ │ │ │ ├── fixed_out_of_bounds_array_access.sol │ │ │ │ ├── function_array_cross_calls.sol │ │ │ │ ├── function_memory_array.sol │ │ │ │ ├── indexAccess/ │ │ │ │ │ ├── arrays_complex_memory_index_access.sol │ │ │ │ │ ├── bytes_index_access.sol │ │ │ │ │ ├── bytes_index_access_memory.sol │ │ │ │ │ ├── bytes_memory_index_access.sol │ │ │ │ │ ├── fixed_bytes_index_access.sol │ │ │ │ │ ├── index_access.sol │ │ │ │ │ ├── inline_array_index_access_ints.sol │ │ │ │ │ ├── inline_array_index_access_strings.sol │ │ │ │ │ ├── memory_arrays_dynamic_index_access_write.sol │ │ │ │ │ └── memory_arrays_index_access_write.sol │ │ │ │ ├── inline_array_return.sol │ │ │ │ ├── inline_array_singleton.sol │ │ │ │ ├── inline_array_storage_to_memory_conversion_ints.sol │ │ │ │ ├── inline_array_storage_to_memory_conversion_strings.sol │ │ │ │ ├── inline_array_strings_from_document.sol │ │ │ │ ├── invalid_encoding_for_storage_byte_array.sol │ │ │ │ ├── long_byte_array_cleanup_after_delete.sol │ │ │ │ ├── long_byte_array_cleanup_after_overwrite_with_long.sol │ │ │ │ ├── memory.sol │ │ │ │ ├── memory_arrays_of_various_sizes.sol │ │ │ │ ├── nested_calldata_storage.sol │ │ │ │ ├── nested_calldata_storage2.sol │ │ │ │ ├── pop/ │ │ │ │ │ ├── array_pop.sol │ │ │ │ │ ├── array_pop_array_transition.sol │ │ │ │ │ ├── array_pop_empty_exception.sol │ │ │ │ │ ├── array_pop_isolated.sol │ │ │ │ │ ├── array_pop_storage_empty.sol │ │ │ │ │ ├── array_pop_uint16_transition.sol │ │ │ │ │ ├── array_pop_uint24_transition.sol │ │ │ │ │ ├── byte_array_pop.sol │ │ │ │ │ ├── byte_array_pop_copy_long.sol │ │ │ │ │ ├── byte_array_pop_empty_exception.sol │ │ │ │ │ ├── byte_array_pop_isolated.sol │ │ │ │ │ ├── byte_array_pop_long_storage_empty.sol │ │ │ │ │ ├── byte_array_pop_long_storage_empty_garbage_ref.sol │ │ │ │ │ ├── byte_array_pop_masking_long.sol │ │ │ │ │ ├── byte_array_pop_storage_empty.sol │ │ │ │ │ └── parenthesized.sol │ │ │ │ ├── push/ │ │ │ │ │ ├── array_push.sol │ │ │ │ │ ├── array_push_nested.sol │ │ │ │ │ ├── array_push_nested_from_calldata.sol │ │ │ │ │ ├── array_push_nested_from_memory.sol │ │ │ │ │ ├── array_push_packed_array.sol │ │ │ │ │ ├── array_push_struct.sol │ │ │ │ │ ├── array_push_struct_from_calldata.sol │ │ │ │ │ ├── byte_array_push.sol │ │ │ │ │ ├── byte_array_push_transition.sol │ │ │ │ │ ├── nested_bytes_push.sol │ │ │ │ │ ├── push_no_args_1d.sol │ │ │ │ │ ├── push_no_args_2d.sol │ │ │ │ │ ├── push_no_args_bytes.sol │ │ │ │ │ └── push_no_args_struct.sol │ │ │ │ ├── reusing_memory.sol │ │ │ │ ├── short_fixed_array_cleanup.sol │ │ │ │ ├── slices/ │ │ │ │ │ ├── array_calldata_assignment.sol │ │ │ │ │ ├── array_slice_calldata_as_argument_of_external_calls.sol │ │ │ │ │ ├── array_slice_calldata_to_calldata.sol │ │ │ │ │ ├── array_slice_calldata_to_memory.sol │ │ │ │ │ └── array_slice_calldata_to_storage.sol │ │ │ │ ├── storage_array_ref.sol │ │ │ │ ├── string_allocation_bug.sol │ │ │ │ ├── string_bytes_conversion.sol │ │ │ │ ├── string_literal_assign_to_storage_bytes.sol │ │ │ │ └── strings_in_struct.sol │ │ │ ├── builtinFunctions/ │ │ │ │ ├── assignment_to_const_var_involving_keccak.sol │ │ │ │ ├── blobhash.sol │ │ │ │ ├── blobhash_shadow_resolution.sol │ │ │ │ ├── blockhash.sol │ │ │ │ ├── blockhash_shadow_resolution.sol │ │ │ │ ├── erc7201_equivalent_solidity_spec.sol │ │ │ │ ├── erc7201_equivalent_solidity_spec_comptime.sol │ │ │ │ ├── erc7201_layout_specifier_slot_match_comptime.sol │ │ │ │ ├── erc7201_overflow_expression.sol │ │ │ │ ├── erc7201_param_abi_encode.sol │ │ │ │ ├── erc7201_param_array_string_literal.sol │ │ │ │ ├── erc7201_param_locations.sol │ │ │ │ ├── erc7201_param_pure_function.sol │ │ │ │ ├── erc7201_param_string_concat.sol │ │ │ │ ├── erc7201_param_string_literal_with_escaped_chars.sol │ │ │ │ ├── erc7201_param_ternary_operator.sol │ │ │ │ ├── erc7201_param_unicode_string_literal.sol │ │ │ │ ├── erc7201_param_unicode_string_variable.sol │ │ │ │ ├── erc7201_param_with_zero_last_byte_of_inner_hash.sol │ │ │ │ ├── erc7201_param_with_zero_last_byte_of_inner_hash_comptime.sol │ │ │ │ ├── function_types_sig.sol │ │ │ │ ├── iterated_keccak256_with_bytes.sol │ │ │ │ ├── keccak256.sol │ │ │ │ ├── keccak256_empty.sol │ │ │ │ ├── keccak256_multiple_arguments.sol │ │ │ │ ├── keccak256_multiple_arguments_with_numeric_literals.sol │ │ │ │ ├── keccak256_multiple_arguments_with_string_literals.sol │ │ │ │ ├── keccak256_packed.sol │ │ │ │ ├── keccak256_packed_complex_types.sol │ │ │ │ ├── keccak256_with_bytes.sol │ │ │ │ ├── msg_sig.sol │ │ │ │ ├── msg_sig_after_internal_call_is_same.sol │ │ │ │ ├── ripemd160.sol │ │ │ │ ├── ripemd160_empty.sol │ │ │ │ ├── ripemd160_packed.sol │ │ │ │ ├── sha256.sol │ │ │ │ ├── sha256_empty.sol │ │ │ │ └── sha256_packed.sol │ │ │ ├── calldata/ │ │ │ │ ├── calldata_array_access.sol │ │ │ │ ├── calldata_array_dynamic_bytes.sol │ │ │ │ ├── calldata_array_index_range_access.sol │ │ │ │ ├── calldata_array_length.sol │ │ │ │ ├── calldata_array_three_dimensional.sol │ │ │ │ ├── calldata_attached_to_bytes.sol │ │ │ │ ├── calldata_attached_to_dynamic_array_or_slice.sol │ │ │ │ ├── calldata_attached_to_static_array.sol │ │ │ │ ├── calldata_attached_to_struct.sol │ │ │ │ ├── calldata_bytes_array_bounds.sol │ │ │ │ ├── calldata_bytes_external.sol │ │ │ │ ├── calldata_bytes_internal.sol │ │ │ │ ├── calldata_bytes_to_memory.sol │ │ │ │ ├── calldata_bytes_to_memory_encode.sol │ │ │ │ ├── calldata_internal_function_pointer.sol │ │ │ │ ├── calldata_internal_library.sol │ │ │ │ ├── calldata_internal_multi_array.sol │ │ │ │ ├── calldata_internal_multi_fixed_array.sol │ │ │ │ ├── calldata_memory_mixed.sol │ │ │ │ ├── calldata_string_array.sol │ │ │ │ ├── calldata_struct.sol │ │ │ │ ├── calldata_struct_cleaning.sol │ │ │ │ ├── calldata_struct_internal.sol │ │ │ │ └── copy_from_calldata_removes_bytes_data.sol │ │ │ ├── cleanup/ │ │ │ │ ├── bool_conversion_v1.sol │ │ │ │ ├── bool_conversion_v2.sol │ │ │ │ ├── byte_array_to_storage_cleanup.sol │ │ │ │ ├── cleanup_address_types_shortening.sol │ │ │ │ ├── cleanup_address_types_v1.sol │ │ │ │ ├── cleanup_address_types_v2.sol │ │ │ │ ├── cleanup_bytes_types_shortening_OldCodeGen.sol │ │ │ │ ├── cleanup_bytes_types_shortening_newCodeGen.sol │ │ │ │ ├── cleanup_bytes_types_v1.sol │ │ │ │ ├── cleanup_bytes_types_v2.sol │ │ │ │ ├── cleanup_in_compound_assign.sol │ │ │ │ ├── dirty_calldata_bytes.sol │ │ │ │ ├── dirty_calldata_dynamic_array.sol │ │ │ │ ├── exp_cleanup.sol │ │ │ │ ├── exp_cleanup_direct.sol │ │ │ │ ├── exp_cleanup_nonzero_base.sol │ │ │ │ ├── exp_cleanup_smaller_base.sol │ │ │ │ ├── indexed_log_topic_during_explicit_downcast.sol │ │ │ │ └── indexed_log_topic_during_explicit_downcast_during_emissions.sol │ │ │ ├── constantEvaluator/ │ │ │ │ ├── negative_fractional_mod.sol │ │ │ │ └── rounding.sol │ │ │ ├── constants/ │ │ │ │ ├── asm_address_constant_regression.sol │ │ │ │ ├── asm_constant_file_level.sol │ │ │ │ ├── assign_type_info.sol │ │ │ │ ├── constant_string.sol │ │ │ │ ├── constant_string_at_file_level.sol │ │ │ │ ├── constant_variables.sol │ │ │ │ ├── constants_at_file_level_referencing.sol │ │ │ │ ├── consteval_array_length.sol │ │ │ │ ├── function_unreferenced.sol │ │ │ │ ├── same_constants_different_files.sol │ │ │ │ └── simple_constant_variables_test.sol │ │ │ ├── constructor/ │ │ │ │ ├── arrays_in_constructors.sol │ │ │ │ ├── base_constructor_arguments.sol │ │ │ │ ├── bytes_in_constructors_packer.sol │ │ │ │ ├── bytes_in_constructors_unpacker.sol │ │ │ │ ├── callvalue_check.sol │ │ │ │ ├── constructor_arguments_external.sol │ │ │ │ ├── constructor_arguments_internal.sol │ │ │ │ ├── constructor_function_argument.sol │ │ │ │ ├── constructor_function_complex.sol │ │ │ │ ├── constructor_static_array_argument.sol │ │ │ │ ├── evm_exceptions_in_constructor_call_fail.sol │ │ │ │ ├── function_usage_in_constructor_arguments.sol │ │ │ │ ├── functions_called_by_constructor.sol │ │ │ │ ├── functions_called_by_constructor_through_dispatch.sol │ │ │ │ ├── inline_member_init_inheritence_without_constructor.sol │ │ │ │ ├── no_callvalue_check.sol │ │ │ │ ├── order_of_evaluation.sol │ │ │ │ ├── payable_constructor.sol │ │ │ │ ├── state_variable_initialization.sol │ │ │ │ ├── store_function_in_constructor.sol │ │ │ │ ├── store_function_in_constructor_packed.sol │ │ │ │ ├── store_internal_unused_function_in_constructor.sol │ │ │ │ ├── store_internal_unused_library_function_in_constructor.sol │ │ │ │ └── transient_state_variable_initialization.sol │ │ │ ├── conversions/ │ │ │ │ ├── function_type_array_to_storage.sol │ │ │ │ └── string_to_bytes.sol │ │ │ ├── deployedCodeExclusion/ │ │ │ │ ├── bound_function.sol │ │ │ │ ├── library_function.sol │ │ │ │ ├── library_function_deployed.sol │ │ │ │ ├── module_function.sol │ │ │ │ ├── module_function_deployed.sol │ │ │ │ ├── static_base_function.sol │ │ │ │ ├── static_base_function_deployed.sol │ │ │ │ ├── subassembly_deduplication.sol │ │ │ │ ├── super_function.sol │ │ │ │ ├── super_function_deployed.sol │ │ │ │ ├── virtual_function.sol │ │ │ │ └── virtual_function_deployed.sol │ │ │ ├── ecrecover/ │ │ │ │ ├── ecrecover.sol │ │ │ │ ├── ecrecover_abiV2.sol │ │ │ │ ├── failing_ecrecover_invalid_input.sol │ │ │ │ ├── failing_ecrecover_invalid_input_asm.sol │ │ │ │ └── failing_ecrecover_invalid_input_proper.sol │ │ │ ├── enums/ │ │ │ │ ├── constructing_enums_from_ints.sol │ │ │ │ ├── enum_explicit_overflow.sol │ │ │ │ ├── enum_explicit_overflow_homestead.sol │ │ │ │ ├── enum_referencing.sol │ │ │ │ ├── enum_with_256_members.sol │ │ │ │ ├── invalid_enum_logged.sol │ │ │ │ ├── minmax.sol │ │ │ │ ├── using_contract_enums_with_explicit_contract_name.sol │ │ │ │ ├── using_enums.sol │ │ │ │ ├── using_inherited_enum.sol │ │ │ │ └── using_inherited_enum_excplicitly.sol │ │ │ ├── errors/ │ │ │ │ ├── error_in_library_and_interface.sol │ │ │ │ ├── error_selector.sol │ │ │ │ ├── error_static_calldata_uint_array_and_dynamic_array.sol │ │ │ │ ├── error_throw_from_module_via_member_access.sol │ │ │ │ ├── errors_by_parameter_type.sol │ │ │ │ ├── named_error_args.sol │ │ │ │ ├── named_parameters_shadowing_types.sol │ │ │ │ ├── panic_via_import.sol │ │ │ │ ├── require_different_errors_same_parameters.sol │ │ │ │ ├── require_error_condition_evaluated_only_once.sol │ │ │ │ ├── require_error_evaluation_order_1.sol │ │ │ │ ├── require_error_evaluation_order_2.sol │ │ │ │ ├── require_error_evaluation_order_3.sol │ │ │ │ ├── require_error_function_join_control_flow.sol │ │ │ │ ├── require_error_function_pointer_parameter.sol │ │ │ │ ├── require_error_multiple_arguments.sol │ │ │ │ ├── require_error_stack_check.sol │ │ │ │ ├── require_error_string_literal.sol │ │ │ │ ├── require_error_string_memory.sol │ │ │ │ ├── require_error_uint256.sol │ │ │ │ ├── require_inherited_error.sol │ │ │ │ ├── revert_conversion.sol │ │ │ │ ├── simple.sol │ │ │ │ ├── small_error_optimization.sol │ │ │ │ ├── using_structs.sol │ │ │ │ ├── via_contract_type.sol │ │ │ │ ├── via_import.sol │ │ │ │ └── weird_name.sol │ │ │ ├── events/ │ │ │ │ ├── emit_three_identical_events.sol │ │ │ │ ├── emit_two_identical_events.sol │ │ │ │ ├── event.sol │ │ │ │ ├── event_access_through_base_name_emit.sol │ │ │ │ ├── event_anonymous.sol │ │ │ │ ├── event_anonymous_with_signature_collision.sol │ │ │ │ ├── event_anonymous_with_signature_collision2.sol │ │ │ │ ├── event_anonymous_with_topics.sol │ │ │ │ ├── event_constructor.sol │ │ │ │ ├── event_dynamic_array_memory.sol │ │ │ │ ├── event_dynamic_array_memory_v2.sol │ │ │ │ ├── event_dynamic_array_storage.sol │ │ │ │ ├── event_dynamic_array_storage_v2.sol │ │ │ │ ├── event_dynamic_nested_array_memory_v2.sol │ │ │ │ ├── event_dynamic_nested_array_storage_v2.sol │ │ │ │ ├── event_emit.sol │ │ │ │ ├── event_emit_file_level.sol │ │ │ │ ├── event_emit_from_a_foreign_contract.sol │ │ │ │ ├── event_emit_from_a_foreign_contract_same_name.sol │ │ │ │ ├── event_emit_from_module_via_member_access.sol │ │ │ │ ├── event_emit_from_other_contract.sol │ │ │ │ ├── event_emit_interface_event_via_library.sol │ │ │ │ ├── event_emit_via_interface.sol │ │ │ │ ├── event_indexed_function.sol │ │ │ │ ├── event_indexed_function2.sol │ │ │ │ ├── event_indexed_mixed.sol │ │ │ │ ├── event_indexed_string.sol │ │ │ │ ├── event_lots_of_data.sol │ │ │ │ ├── event_no_arguments.sol │ │ │ │ ├── event_really_lots_of_data.sol │ │ │ │ ├── event_really_lots_of_data_from_storage.sol │ │ │ │ ├── event_really_really_lots_of_data_from_storage.sol │ │ │ │ ├── event_selector.sol │ │ │ │ ├── event_selector_file_level.sol │ │ │ │ ├── event_shadowing_file_level.sol │ │ │ │ ├── event_signature_in_library.sol │ │ │ │ ├── event_static_calldata_uint_array_and_dynamic_array.sol │ │ │ │ ├── event_string.sol │ │ │ │ ├── event_struct_memory_v2.sol │ │ │ │ ├── event_struct_storage_v2.sol │ │ │ │ ├── events_with_same_name.sol │ │ │ │ ├── events_with_same_name_file_level.sol │ │ │ │ ├── events_with_same_name_inherited_emit.sol │ │ │ │ └── simple.sol │ │ │ ├── experimental/ │ │ │ │ ├── stub.sol │ │ │ │ └── type_class.sol │ │ │ ├── exponentiation/ │ │ │ │ ├── literal_base.sol │ │ │ │ ├── signed_base.sol │ │ │ │ └── small_exp.sol │ │ │ ├── expressions/ │ │ │ │ ├── bit_operators.sol │ │ │ │ ├── bytes_comparison.sol │ │ │ │ ├── conditional_expression_different_types.sol │ │ │ │ ├── conditional_expression_false_literal.sol │ │ │ │ ├── conditional_expression_functions.sol │ │ │ │ ├── conditional_expression_multiple.sol │ │ │ │ ├── conditional_expression_storage_memory_1.sol │ │ │ │ ├── conditional_expression_storage_memory_2.sol │ │ │ │ ├── conditional_expression_true_literal.sol │ │ │ │ ├── conditional_expression_tuples.sol │ │ │ │ ├── conditional_expression_with_return_values.sol │ │ │ │ ├── exp_operator_const.sol │ │ │ │ ├── exp_operator_const_signed.sol │ │ │ │ ├── exp_zero_literal.sol │ │ │ │ ├── inc_dec_operators.sol │ │ │ │ ├── module_from_ternary_expression.sol │ │ │ │ ├── tuple_from_ternary_expression.sol │ │ │ │ ├── unary_too_long_literal.sol │ │ │ │ └── uncalled_address_transfer_send.sol │ │ │ ├── externalContracts/ │ │ │ │ ├── FixedFeeRegistrar.sol │ │ │ │ ├── _base64/ │ │ │ │ │ ├── base64_inline_asm.sol │ │ │ │ │ └── base64_no_inline_asm.sol │ │ │ │ ├── _prbmath/ │ │ │ │ │ ├── LICENSE.md │ │ │ │ │ ├── PRBMathCommon.sol │ │ │ │ │ ├── PRBMathSD59x18.sol │ │ │ │ │ ├── PRBMathUD60x18.sol │ │ │ │ │ └── README.md │ │ │ │ ├── _stringutils/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── README.md │ │ │ │ │ └── stringutils.sol │ │ │ │ ├── base64.sol │ │ │ │ ├── deposit_contract.sol │ │ │ │ ├── prbmath_signed.sol │ │ │ │ ├── prbmath_unsigned.sol │ │ │ │ ├── ramanujan_pi.sol │ │ │ │ ├── snark.sol │ │ │ │ └── strings.sol │ │ │ ├── externalSource/ │ │ │ │ ├── _external/ │ │ │ │ │ ├── external.sol │ │ │ │ │ ├── external.sol=sol │ │ │ │ │ ├── import.sol │ │ │ │ │ ├── import_with_subdir.sol │ │ │ │ │ ├── other_external.sol │ │ │ │ │ └── subdir/ │ │ │ │ │ ├── import.sol │ │ │ │ │ └── sub_external.sol │ │ │ │ ├── _nonNormalizedPaths/ │ │ │ │ │ ├── a.sol │ │ │ │ │ ├── c.sol │ │ │ │ │ └── d.sol │ │ │ │ ├── _relativeImports/ │ │ │ │ │ ├── D/ │ │ │ │ │ │ └── d.sol │ │ │ │ │ ├── c.sol │ │ │ │ │ ├── dir/ │ │ │ │ │ │ ├── B/ │ │ │ │ │ │ │ └── b.sol │ │ │ │ │ │ ├── G/ │ │ │ │ │ │ │ └── g.sol │ │ │ │ │ │ ├── a.sol │ │ │ │ │ │ └── contract.sol │ │ │ │ │ └── h.sol │ │ │ │ ├── _sourceNameStartingWithDots/ │ │ │ │ │ ├── b.sol │ │ │ │ │ ├── dir/ │ │ │ │ │ │ ├── a.sol │ │ │ │ │ │ └── contract.sol │ │ │ │ │ ├── dot_a.sol │ │ │ │ │ └── dot_dot_b.sol │ │ │ │ ├── multiple_equals_signs.sol │ │ │ │ ├── multiple_external_source.sol │ │ │ │ ├── multisource.sol │ │ │ │ ├── non_normalized_paths.sol │ │ │ │ ├── relative_imports.sol │ │ │ │ ├── source.sol │ │ │ │ ├── source_import.sol │ │ │ │ ├── source_import_subdir.sol │ │ │ │ ├── source_name_starting_with_dots.sol │ │ │ │ └── source_remapping.sol │ │ │ ├── fallback/ │ │ │ │ ├── call_forward_bytes.sol │ │ │ │ ├── falback_return.sol │ │ │ │ ├── fallback_argument.sol │ │ │ │ ├── fallback_argument_to_storage.sol │ │ │ │ ├── fallback_or_receive.sol │ │ │ │ ├── fallback_override.sol │ │ │ │ ├── fallback_override2.sol │ │ │ │ ├── fallback_override_multi.sol │ │ │ │ ├── fallback_return_data.sol │ │ │ │ ├── inherited.sol │ │ │ │ └── short_data_calls_fallback.sol │ │ │ ├── freeFunctions/ │ │ │ │ ├── easy.sol │ │ │ │ ├── free_namesake_contract_function.sol │ │ │ │ ├── free_runtimecode.sol │ │ │ │ ├── import.sol │ │ │ │ ├── libraries_from_free.sol │ │ │ │ ├── new_operator.sol │ │ │ │ ├── overloads.sol │ │ │ │ ├── recursion.sol │ │ │ │ └── storage_calldata_refs.sol │ │ │ ├── functionCall/ │ │ │ │ ├── array_multiple_local_vars.sol │ │ │ │ ├── bare_call_no_returndatacopy.sol │ │ │ │ ├── call_attached_library_function_on_function.sol │ │ │ │ ├── call_attached_library_function_on_storage_variable.sol │ │ │ │ ├── call_attached_library_function_on_string.sol │ │ │ │ ├── call_function_returning_function.sol │ │ │ │ ├── call_function_returning_nothing_via_pointer.sol │ │ │ │ ├── call_internal_function_via_expression.sol │ │ │ │ ├── call_internal_function_with_multislot_arguments_via_pointer.sol │ │ │ │ ├── call_options_overload.sol │ │ │ │ ├── calling_nonexisting_contract_throws.sol │ │ │ │ ├── calling_other_functions.sol │ │ │ │ ├── calling_uninitialized_function.sol │ │ │ │ ├── calling_uninitialized_function_in_detail.sol │ │ │ │ ├── calling_uninitialized_function_through_array.sol │ │ │ │ ├── conditional_with_arguments.sol │ │ │ │ ├── creation_function_call_no_args.sol │ │ │ │ ├── creation_function_call_with_args.sol │ │ │ │ ├── creation_function_call_with_salt.sol │ │ │ │ ├── delegatecall_return_value.sol │ │ │ │ ├── delegatecall_return_value_pre_byzantium.sol │ │ │ │ ├── disordered_named_args.sol │ │ │ │ ├── eof/ │ │ │ │ │ ├── call_options_overload.sol │ │ │ │ │ ├── calling_nonexisting_contract.sol │ │ │ │ │ ├── external_call_at_construction_time.sol │ │ │ │ │ └── external_call_to_nonexisting.sol │ │ │ │ ├── external_call.sol │ │ │ │ ├── external_call_at_construction_time.sol │ │ │ │ ├── external_call_dynamic_returndata.sol │ │ │ │ ├── external_call_to_nonexisting.sol │ │ │ │ ├── external_call_to_nonexisting_debugstrings.sol │ │ │ │ ├── external_call_value.sol │ │ │ │ ├── external_function.sol │ │ │ │ ├── external_public_override.sol │ │ │ │ ├── failed_create.sol │ │ │ │ ├── file_level_call_via_module.sol │ │ │ │ ├── gas_and_value_basic.sol │ │ │ │ ├── inheritance/ │ │ │ │ │ ├── base_base_overload.sol │ │ │ │ │ ├── base_overload.sol │ │ │ │ │ ├── call_base.sol │ │ │ │ │ ├── call_base_base.sol │ │ │ │ │ ├── call_base_base_explicit.sol │ │ │ │ │ ├── call_base_explicit.sol │ │ │ │ │ ├── call_unimplemented_base.sol │ │ │ │ │ ├── super_skip_unimplemented_in_abstract_contract.sol │ │ │ │ │ └── super_skip_unimplemented_in_interface.sol │ │ │ │ ├── mapping_array_internal_argument.sol │ │ │ │ ├── mapping_internal_argument.sol │ │ │ │ ├── mapping_internal_return.sol │ │ │ │ ├── member_accessors.sol │ │ │ │ ├── multiple_functions.sol │ │ │ │ ├── multiple_return_values.sol │ │ │ │ ├── named_args.sol │ │ │ │ ├── named_args_overload.sol │ │ │ │ ├── precompile_extcodesize_check.sol │ │ │ │ ├── return_size_bigger_than_expected.sol │ │ │ │ ├── return_size_shorter_than_expected.sol │ │ │ │ ├── return_size_shorter_than_expected_evm_version_after_homestead.sol │ │ │ │ ├── send_zero_ether.sol │ │ │ │ ├── transaction_status.sol │ │ │ │ └── value_test.sol │ │ │ ├── functionSelector/ │ │ │ │ └── function_selector_via_contract_name.sol │ │ │ ├── functionTypes/ │ │ │ │ ├── address_member.sol │ │ │ │ ├── call_to_zero_initialized_function_type_ir.sol │ │ │ │ ├── call_to_zero_initialized_function_type_legacy.sol │ │ │ │ ├── comparison_operator_for_external_function_cleans_dirty_bits.sol │ │ │ │ ├── comparison_operators_for_external_functions.sol │ │ │ │ ├── duplicated_function_definition_with_same_id_in_internal_dispatcher.sol │ │ │ │ ├── external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol │ │ │ │ ├── function_delete_stack.sol │ │ │ │ ├── function_delete_storage.sol │ │ │ │ ├── function_external_delete_storage.sol │ │ │ │ ├── function_type_library_internal.sol │ │ │ │ ├── inline_array_with_value_call_option.sol │ │ │ │ ├── mapping_of_functions.sol │ │ │ │ ├── pass_function_types_externally.sol │ │ │ │ ├── pass_function_types_internally.sol │ │ │ │ ├── same_function_in_construction_and_runtime.sol │ │ │ │ ├── same_function_in_construction_and_runtime_equality_check.sol │ │ │ │ ├── selector_1.sol │ │ │ │ ├── selector_2.sol │ │ │ │ ├── selector_assignment_expression.sol │ │ │ │ ├── selector_expression_side_effect.sol │ │ │ │ ├── selector_ternary.sol │ │ │ │ ├── selector_ternary_function_pointer_from_function_call.sol │ │ │ │ ├── stack_height_check_on_adding_gas_variable_to_function.sol │ │ │ │ ├── store_function.sol │ │ │ │ ├── struct_with_external_function.sol │ │ │ │ ├── struct_with_functions.sol │ │ │ │ ├── ternary_contract_internal_function.sol │ │ │ │ ├── ternary_contract_library_internal_function.sol │ │ │ │ ├── ternary_contract_public_function.sol │ │ │ │ └── uninitialized_internal_storage_function_call.sol │ │ │ ├── getters/ │ │ │ │ ├── array_mapping_struct.sol │ │ │ │ ├── arrays.sol │ │ │ │ ├── bytes.sol │ │ │ │ ├── mapping.sol │ │ │ │ ├── mapping_array_struct.sol │ │ │ │ ├── mapping_of_string.sol │ │ │ │ ├── mapping_to_struct.sol │ │ │ │ ├── mapping_with_names.sol │ │ │ │ ├── string_and_bytes.sol │ │ │ │ ├── struct_with_bytes.sol │ │ │ │ ├── struct_with_bytes_simple.sol │ │ │ │ ├── transient_value_types.sol │ │ │ │ ├── transient_value_types_multi_frame_call.sol │ │ │ │ └── value_types.sol │ │ │ ├── immutable/ │ │ │ │ ├── assign_at_declaration.sol │ │ │ │ ├── assign_from_immutables.sol │ │ │ │ ├── delete.sol │ │ │ │ ├── fun_read_in_ctor.sol │ │ │ │ ├── getter.sol │ │ │ │ ├── getter_call_in_constructor.sol │ │ │ │ ├── immutable_signed.sol │ │ │ │ ├── immutable_tag_too_large_bug.sol │ │ │ │ ├── increment_decrement.sol │ │ │ │ ├── inheritance.sol │ │ │ │ ├── internal_function_pointer.sol │ │ │ │ ├── multi_creation.sol │ │ │ │ ├── multiple_initializations.sol │ │ │ │ ├── read_in_ctor.sol │ │ │ │ ├── small_types_in_reverse.sol │ │ │ │ ├── stub.sol │ │ │ │ ├── uninitialized.sol │ │ │ │ └── use_scratch.sol │ │ │ ├── inheritance/ │ │ │ │ ├── access_base_storage.sol │ │ │ │ ├── address_overload_resolution.sol │ │ │ │ ├── base_access_to_function_type_variables.sol │ │ │ │ ├── constructor_inheritance_init_order.sol │ │ │ │ ├── constructor_inheritance_init_order_2.sol │ │ │ │ ├── constructor_inheritance_init_order_3_legacy.sol │ │ │ │ ├── constructor_inheritance_init_order_3_viaIR.sol │ │ │ │ ├── constructor_with_params.sol │ │ │ │ ├── constructor_with_params_diamond_inheritance.sol │ │ │ │ ├── constructor_with_params_inheritance.sol │ │ │ │ ├── constructor_with_params_inheritance_2.sol │ │ │ │ ├── dataLocation/ │ │ │ │ │ └── external_public_calldata.sol │ │ │ │ ├── derived_overload_base_function_direct.sol │ │ │ │ ├── derived_overload_base_function_indirect.sol │ │ │ │ ├── explicit_base_class.sol │ │ │ │ ├── inherited_constant_state_var.sol │ │ │ │ ├── inherited_function.sol │ │ │ │ ├── inherited_function_calldata_calldata_interface.sol │ │ │ │ ├── inherited_function_calldata_memory.sol │ │ │ │ ├── inherited_function_calldata_memory_interface.sol │ │ │ │ ├── inherited_function_from_a_library.sol │ │ │ │ ├── inherited_function_through_dispatch.sol │ │ │ │ ├── interface_inheritance_conversions.sol │ │ │ │ ├── member_notation_ctor.sol │ │ │ │ ├── overloaded_function_call_resolve_to_first.sol │ │ │ │ ├── overloaded_function_call_resolve_to_second.sol │ │ │ │ ├── overloaded_function_call_with_if_else.sol │ │ │ │ ├── pass_dynamic_arguments_to_the_base.sol │ │ │ │ ├── pass_dynamic_arguments_to_the_base_base.sol │ │ │ │ ├── pass_dynamic_arguments_to_the_base_base_with_gap.sol │ │ │ │ ├── state_variables_init_order.sol │ │ │ │ ├── state_variables_init_order_2.sol │ │ │ │ ├── state_variables_init_order_3.sol │ │ │ │ ├── super_in_constructor.sol │ │ │ │ ├── super_in_constructor_assignment.sol │ │ │ │ ├── super_overload.sol │ │ │ │ ├── transient_storage_state_variable.sol │ │ │ │ ├── transient_storage_state_variable_abstract_contract.sol │ │ │ │ └── value_for_constructor.sol │ │ │ ├── inlineAssembly/ │ │ │ │ ├── basefee_berlin_function.sol │ │ │ │ ├── blobbasefee_shanghai_function.sol │ │ │ │ ├── blobhash.sol │ │ │ │ ├── blobhash_index_exceeding_blob_count.sol │ │ │ │ ├── blobhash_pre_cancun.sol │ │ │ │ ├── calldata_array_assign_dynamic.sol │ │ │ │ ├── calldata_array_assign_static.sol │ │ │ │ ├── calldata_array_read.sol │ │ │ │ ├── calldata_assign.sol │ │ │ │ ├── calldata_assign_from_nowhere.sol │ │ │ │ ├── calldata_length_read.sol │ │ │ │ ├── calldata_offset_read.sol │ │ │ │ ├── calldata_offset_read_write.sol │ │ │ │ ├── calldata_struct_assign.sol │ │ │ │ ├── calldata_struct_assign_and_return.sol │ │ │ │ ├── chainid.sol │ │ │ │ ├── clz.sol │ │ │ │ ├── clz_pre_osaka.sol │ │ │ │ ├── constant_access.sol │ │ │ │ ├── constant_access_referencing.sol │ │ │ │ ├── difficulty.sol │ │ │ │ ├── external_function_pointer_address.sol │ │ │ │ ├── external_function_pointer_address_assignment.sol │ │ │ │ ├── external_function_pointer_selector.sol │ │ │ │ ├── external_function_pointer_selector_assignment.sol │ │ │ │ ├── external_identifier_access_shadowing.sol │ │ │ │ ├── for_loop_break.sol │ │ │ │ ├── for_loop_continue.sol │ │ │ │ ├── for_loop_nested.sol │ │ │ │ ├── function_name_clash.sol │ │ │ │ ├── inline_assembly_embedded_function_call.sol │ │ │ │ ├── inline_assembly_for.sol │ │ │ │ ├── inline_assembly_for2.sol │ │ │ │ ├── inline_assembly_function_call.sol │ │ │ │ ├── inline_assembly_function_call2.sol │ │ │ │ ├── inline_assembly_function_call_assignment.sol │ │ │ │ ├── inline_assembly_if.sol │ │ │ │ ├── inline_assembly_in_modifiers.sol │ │ │ │ ├── inline_assembly_memory_access.sol │ │ │ │ ├── inline_assembly_read_and_write_stack.sol │ │ │ │ ├── inline_assembly_recursion.sol │ │ │ │ ├── inline_assembly_storage_access.sol │ │ │ │ ├── inline_assembly_storage_access_inside_function.sol │ │ │ │ ├── inline_assembly_storage_access_local_var.sol │ │ │ │ ├── inline_assembly_storage_access_via_pointer.sol │ │ │ │ ├── inline_assembly_switch.sol │ │ │ │ ├── inline_assembly_transient_storage_access_inside_function.sol │ │ │ │ ├── inline_assembly_write_to_stack.sol │ │ │ │ ├── inlineasm_empty_let.sol │ │ │ │ ├── keccak256_assembly.sol │ │ │ │ ├── keccak256_optimization.sol │ │ │ │ ├── keccak256_optimizer_bug_different_memory_location.sol │ │ │ │ ├── keccak256_optimizer_cache_bug.sol │ │ │ │ ├── keccak_optimization_bug_string.sol │ │ │ │ ├── keccak_yul_optimization.sol │ │ │ │ ├── leave.sol │ │ │ │ ├── mcopy.sol │ │ │ │ ├── mcopy_as_identifier_pre_cancun.sol │ │ │ │ ├── mcopy_empty.sol │ │ │ │ ├── mcopy_overlap.sol │ │ │ │ ├── optimize_memory_store_multi_block.sol │ │ │ │ ├── optimize_memory_store_multi_block_bugreport.sol │ │ │ │ ├── prevrandao.sol │ │ │ │ ├── selfbalance.sol │ │ │ │ ├── shadowing_local_function_opcode.sol │ │ │ │ ├── slot_access.sol │ │ │ │ ├── slot_access_via_mapping_pointer.sol │ │ │ │ ├── tload_tstore_not_reserved_before_cancun.sol │ │ │ │ ├── transient_storage_creation.sol │ │ │ │ ├── transient_storage_low_level_calls.sol │ │ │ │ ├── transient_storage_multiple_calls_different_transactions.sol │ │ │ │ ├── transient_storage_multiple_transactions.sol │ │ │ │ ├── transient_storage_reset_between_creation_runtime.sol │ │ │ │ ├── transient_storage_sanity_checks.sol │ │ │ │ ├── transient_storage_selfdestruct.sol │ │ │ │ ├── transient_storage_simple_reentrancy_lock.sol │ │ │ │ ├── truefalse.sol │ │ │ │ └── tstore_hidden_staticcall.sol │ │ │ ├── integer/ │ │ │ │ ├── basic.sol │ │ │ │ ├── int.sol │ │ │ │ ├── many_local_variables.sol │ │ │ │ ├── small_signed_types.sol │ │ │ │ └── uint.sol │ │ │ ├── interfaceID/ │ │ │ │ ├── homer.sol │ │ │ │ ├── homer_interfaceId.sol │ │ │ │ ├── interfaceId_events.sol │ │ │ │ ├── interfaces.sol │ │ │ │ ├── lisa.sol │ │ │ │ └── lisa_interfaceId.sol │ │ │ ├── isoltestTesting/ │ │ │ │ ├── account.sol │ │ │ │ ├── balance_other_contract.sol │ │ │ │ ├── balance_with_balance.sol │ │ │ │ ├── balance_with_balance2.sol │ │ │ │ ├── balance_without_balance.sol │ │ │ │ ├── builtins.sol │ │ │ │ ├── effects.sol │ │ │ │ ├── empty_contract.sol │ │ │ │ ├── format_raw_string_with_control_chars.sol │ │ │ │ ├── isoltestFormatting.sol │ │ │ │ ├── precompiles_ignoring_trailing_input.sol │ │ │ │ └── storage/ │ │ │ │ ├── storage_empty.sol │ │ │ │ └── storage_nonempty.sol │ │ │ ├── libraries/ │ │ │ │ ├── attached_internal_library_function_accepting_calldata.sol │ │ │ │ ├── attached_internal_library_function_returning_calldata.sol │ │ │ │ ├── attached_public_library_function_accepting_calldata.sol.sol │ │ │ │ ├── attached_public_library_function_returning_calldata.sol │ │ │ │ ├── external_call_with_function_pointer_parameter.sol │ │ │ │ ├── external_call_with_storage_array_parameter.sol │ │ │ │ ├── external_call_with_storage_mapping_parameter.sol │ │ │ │ ├── internal_call_attached_with_parentheses.sol │ │ │ │ ├── internal_call_unattached_with_parentheses.sol │ │ │ │ ├── internal_library_function.sol │ │ │ │ ├── internal_library_function_attached_to_address.sol │ │ │ │ ├── internal_library_function_attached_to_address_named_send_transfer.sol │ │ │ │ ├── internal_library_function_attached_to_array_named_pop_push.sol │ │ │ │ ├── internal_library_function_attached_to_bool.sol │ │ │ │ ├── internal_library_function_attached_to_contract.sol │ │ │ │ ├── internal_library_function_attached_to_dynamic_array.sol │ │ │ │ ├── internal_library_function_attached_to_enum.sol │ │ │ │ ├── internal_library_function_attached_to_external_function_type.sol │ │ │ │ ├── internal_library_function_attached_to_fixed_array.sol │ │ │ │ ├── internal_library_function_attached_to_fixed_bytes.sol │ │ │ │ ├── internal_library_function_attached_to_integer.sol │ │ │ │ ├── internal_library_function_attached_to_interface.sol │ │ │ │ ├── internal_library_function_attached_to_internal_function_type.sol │ │ │ │ ├── internal_library_function_attached_to_internal_function_type_named_selector.sol │ │ │ │ ├── internal_library_function_attached_to_literal.sol │ │ │ │ ├── internal_library_function_attached_to_mapping.sol │ │ │ │ ├── internal_library_function_attached_to_string_accepting_memory.sol │ │ │ │ ├── internal_library_function_attached_to_string_accepting_storage.sol │ │ │ │ ├── internal_library_function_attached_to_struct.sol │ │ │ │ ├── internal_library_function_calling_private.sol │ │ │ │ ├── internal_library_function_pointer.sol │ │ │ │ ├── internal_library_function_return_var_size.sol │ │ │ │ ├── internal_types_in_library.sol │ │ │ │ ├── library_address.sol │ │ │ │ ├── library_address_homestead.sol │ │ │ │ ├── library_address_via_module.sol │ │ │ │ ├── library_call_in_homestead.sol │ │ │ │ ├── library_delegatecall_guard_pure.sol │ │ │ │ ├── library_delegatecall_guard_view_needed.sol │ │ │ │ ├── library_delegatecall_guard_view_not_needed.sol │ │ │ │ ├── library_delegatecall_guard_view_staticcall.sol │ │ │ │ ├── library_enum_as_an_expression.sol │ │ │ │ ├── library_function_selectors.sol │ │ │ │ ├── library_function_selectors_struct.sol │ │ │ │ ├── library_references_preserve.sol │ │ │ │ ├── library_return_struct_with_mapping.sol │ │ │ │ ├── library_staticcall_delegatecall.sol │ │ │ │ ├── library_stray_values.sol │ │ │ │ ├── library_struct_as_an_expression.sol │ │ │ │ ├── mapping_arguments_in_library.sol │ │ │ │ ├── mapping_returns_in_library.sol │ │ │ │ ├── mapping_returns_in_library_named.sol │ │ │ │ ├── payable_function_calls_library.sol │ │ │ │ ├── stub.sol │ │ │ │ ├── stub_internal.sol │ │ │ │ ├── using_for_by_name.sol │ │ │ │ ├── using_for_function_on_int.sol │ │ │ │ ├── using_for_overload.sol │ │ │ │ ├── using_for_storage_structs.sol │ │ │ │ ├── using_library_mappings_public.sol │ │ │ │ ├── using_library_mappings_return.sol │ │ │ │ └── using_library_structs.sol │ │ │ ├── literals/ │ │ │ │ ├── denominations.sol │ │ │ │ ├── denominations_in_array_sizes.sol │ │ │ │ ├── escape.sol │ │ │ │ ├── ether.sol │ │ │ │ ├── fractional_denominations.sol │ │ │ │ ├── gwei.sol │ │ │ │ ├── hex_string_with_non_printable_characters.sol │ │ │ │ ├── hex_string_with_underscore.sol │ │ │ │ ├── scientific_notation.sol │ │ │ │ ├── ternary_operator_with_literal_types_overflow.sol │ │ │ │ └── wei.sol │ │ │ ├── memoryManagement/ │ │ │ │ ├── assembly_access.sol │ │ │ │ ├── memory_types_initialisation.sol │ │ │ │ ├── return_variable.sol │ │ │ │ ├── static_memory_array_allocation.sol │ │ │ │ └── struct_allocation.sol │ │ │ ├── metaTypes/ │ │ │ │ └── name_other_contract.sol │ │ │ ├── modifiers/ │ │ │ │ ├── access_through_contract_name.sol │ │ │ │ ├── access_through_module_name.sol │ │ │ │ ├── break_in_modifier.sol │ │ │ │ ├── continue_in_modifier.sol │ │ │ │ ├── evaluation_order.sol │ │ │ │ ├── function_modifier.sol │ │ │ │ ├── function_modifier_calling_functions_in_creation_context.sol │ │ │ │ ├── function_modifier_empty.sol │ │ │ │ ├── function_modifier_for_constructor.sol │ │ │ │ ├── function_modifier_library.sol │ │ │ │ ├── function_modifier_library_inheritance.sol │ │ │ │ ├── function_modifier_local_variables.sol │ │ │ │ ├── function_modifier_loop.sol │ │ │ │ ├── function_modifier_loop_viair.sol │ │ │ │ ├── function_modifier_multi_invocation.sol │ │ │ │ ├── function_modifier_multi_invocation_viair.sol │ │ │ │ ├── function_modifier_multi_with_return.sol │ │ │ │ ├── function_modifier_multiple_times.sol │ │ │ │ ├── function_modifier_multiple_times_local_vars.sol │ │ │ │ ├── function_modifier_overriding.sol │ │ │ │ ├── function_modifier_return_reference.sol │ │ │ │ ├── function_return_parameter.sol │ │ │ │ ├── function_return_parameter_complex.sol │ │ │ │ ├── modifer_recursive.sol │ │ │ │ ├── modifier_in_constructor_ice.sol │ │ │ │ ├── modifier_init_return.sol │ │ │ │ ├── modifiers_in_construction_context.sol │ │ │ │ ├── return_does_not_skip_modifier.sol │ │ │ │ ├── return_in_modifier.sol │ │ │ │ ├── stacked_return_with_modifiers.sol │ │ │ │ └── transient_state_variable_value_type.sol │ │ │ ├── multiSource/ │ │ │ │ ├── circular_import.sol │ │ │ │ ├── circular_import_2.sol │ │ │ │ ├── circular_reimport.sol │ │ │ │ ├── circular_reimport_2.sol │ │ │ │ ├── free_different_interger_types.sol │ │ │ │ ├── free_function_resolution_base_contract.sol │ │ │ │ ├── free_function_resolution_override_virtual.sol │ │ │ │ ├── free_function_resolution_override_virtual_super.sol │ │ │ │ ├── free_function_resolution_override_virtual_transitive.sol │ │ │ │ ├── free_function_transitive_import.sol │ │ │ │ ├── import.sol │ │ │ │ ├── import_overloaded_function.sol │ │ │ │ ├── imported_free_function_via_alias.sol │ │ │ │ ├── imported_free_function_via_alias_direct_call.sol │ │ │ │ └── reimport_imported_function.sol │ │ │ ├── operators/ │ │ │ │ ├── compound_assign.sol │ │ │ │ ├── compound_assign_transient_storage.sol │ │ │ │ ├── shifts/ │ │ │ │ │ ├── bitwise_shifting_constantinople.sol │ │ │ │ │ ├── bitwise_shifting_constantinople_combined.sol │ │ │ │ │ ├── bitwise_shifting_constants_constantinople.sol │ │ │ │ │ ├── shift_bytes_cleanup.sol │ │ │ │ │ ├── shift_bytes_cleanup_viaYul.sol │ │ │ │ │ ├── shift_cleanup.sol │ │ │ │ │ ├── shift_cleanup_garbled.sol │ │ │ │ │ ├── shift_constant_left.sol │ │ │ │ │ ├── shift_constant_left_assignment.sol │ │ │ │ │ ├── shift_constant_right.sol │ │ │ │ │ ├── shift_constant_right_assignment.sol │ │ │ │ │ ├── shift_left.sol │ │ │ │ │ ├── shift_left_assignment.sol │ │ │ │ │ ├── shift_left_assignment_different_type.sol │ │ │ │ │ ├── shift_left_larger_type.sol │ │ │ │ │ ├── shift_left_uint32.sol │ │ │ │ │ ├── shift_left_uint8.sol │ │ │ │ │ ├── shift_negative_constant_left.sol │ │ │ │ │ ├── shift_negative_constant_right.sol │ │ │ │ │ ├── shift_overflow.sol │ │ │ │ │ ├── shift_right.sol │ │ │ │ │ ├── shift_right_assignment.sol │ │ │ │ │ ├── shift_right_garbled_signed_v1.sol │ │ │ │ │ ├── shift_right_garbled_signed_v2.sol │ │ │ │ │ ├── shift_right_garbled_v1.sol │ │ │ │ │ ├── shift_right_garbled_v2.sol │ │ │ │ │ ├── shift_right_negative_literal.sol │ │ │ │ │ ├── shift_right_negative_lvalue.sol │ │ │ │ │ ├── shift_right_negative_lvalue_assignment.sol │ │ │ │ │ ├── shift_right_negative_lvalue_int16.sol │ │ │ │ │ ├── shift_right_negative_lvalue_int32.sol │ │ │ │ │ ├── shift_right_negative_lvalue_int8.sol │ │ │ │ │ ├── shift_right_negative_lvalue_signextend_int16_v1.sol │ │ │ │ │ ├── shift_right_negative_lvalue_signextend_int16_v2.sol │ │ │ │ │ ├── shift_right_negative_lvalue_signextend_int32_v1.sol │ │ │ │ │ ├── shift_right_negative_lvalue_signextend_int32_v2.sol │ │ │ │ │ ├── shift_right_negative_lvalue_signextend_int8_v1.sol │ │ │ │ │ ├── shift_right_negative_lvalue_signextend_int8_v2.sol │ │ │ │ │ ├── shift_right_uint32.sol │ │ │ │ │ ├── shift_right_uint8.sol │ │ │ │ │ ├── shift_underflow_negative_rvalue.sol │ │ │ │ │ └── shifts.sol │ │ │ │ ├── transient_storage_variable_increment_decrement.sol │ │ │ │ └── userDefined/ │ │ │ │ ├── all_possible_operators.sol │ │ │ │ ├── all_possible_user_defined_value_types_with_operators.sol │ │ │ │ ├── attaching_and_defining_operator_with_same_function.sol │ │ │ │ ├── checked_operators.sol │ │ │ │ ├── consecutive_operator_invocations.sol │ │ │ │ ├── fixed_point_udvt_with_operators.sol │ │ │ │ ├── multiple_operator_definitions_different_types_different_functions_separate_directives.sol │ │ │ │ ├── multiple_operator_definitions_same_type_same_function_same_directive.sol │ │ │ │ ├── operator_definition_shadowing_builtin_keccak256.sol │ │ │ │ ├── operator_evaluation_order.sol │ │ │ │ ├── operator_making_pure_external_call.sol │ │ │ │ ├── operator_making_view_external_call.sol │ │ │ │ ├── operator_parameter_and_return_cleanup_between_calls.sol │ │ │ │ ├── operator_parameter_cleanup.sol │ │ │ │ ├── operator_precendence.sol │ │ │ │ ├── operator_return_parameter_cleanup.sol │ │ │ │ ├── recursive_operator.sol │ │ │ │ └── unchecked_operators.sol │ │ │ ├── optimizer/ │ │ │ │ ├── shift_bytes.sol │ │ │ │ └── unused_store_storage_removal_bug.sol │ │ │ ├── payable/ │ │ │ │ └── no_nonpayable_circumvention_by_modifier.sol │ │ │ ├── receive/ │ │ │ │ ├── empty_calldata_calls_receive.sol │ │ │ │ ├── ether_and_data.sol │ │ │ │ └── inherited.sol │ │ │ ├── revertStrings/ │ │ │ │ ├── array_slices.sol │ │ │ │ ├── bubble.sol │ │ │ │ ├── calldata_array_dynamic_invalid.sol │ │ │ │ ├── calldata_array_dynamic_static_short_decode.sol │ │ │ │ ├── calldata_array_dynamic_static_short_reencode.sol │ │ │ │ ├── calldata_array_invalid_length.sol │ │ │ │ ├── calldata_arrays_too_large.sol │ │ │ │ ├── calldata_tail_short.sol │ │ │ │ ├── calldata_too_short_v1.sol │ │ │ │ ├── called_contract_has_code.sol │ │ │ │ ├── empty_v1.sol │ │ │ │ ├── empty_v2.sol │ │ │ │ ├── enum_v1.sol │ │ │ │ ├── enum_v2.sol │ │ │ │ ├── ether_non_payable_function.sol │ │ │ │ ├── function_entry_checks_v1.sol │ │ │ │ ├── function_entry_checks_v2.sol │ │ │ │ ├── invalid_abi_decoding_calldata_v1.sol │ │ │ │ ├── invalid_abi_decoding_memory_v1.sol │ │ │ │ ├── library_non_view_call.sol │ │ │ │ ├── short_input_array.sol │ │ │ │ ├── short_input_bytes.sol │ │ │ │ ├── transfer.sol │ │ │ │ └── unknown_sig_no_fallback.sol │ │ │ ├── reverts/ │ │ │ │ ├── assert_require.sol │ │ │ │ ├── eof/ │ │ │ │ │ └── revert_return_area.sol │ │ │ │ ├── error_struct.sol │ │ │ │ ├── invalid_enum_as_external_arg.sol │ │ │ │ ├── invalid_enum_as_external_ret.sol │ │ │ │ ├── invalid_enum_compared.sol │ │ │ │ ├── invalid_enum_stored.sol │ │ │ │ ├── invalid_instruction.sol │ │ │ │ ├── revert.sol │ │ │ │ ├── revert_return_area.sol │ │ │ │ └── simple_throw.sol │ │ │ ├── saltedCreate/ │ │ │ │ ├── eof/ │ │ │ │ │ └── salted_create_with_value.sol │ │ │ │ ├── prediction_example.sol │ │ │ │ ├── salted_create.sol │ │ │ │ └── salted_create_with_value.sol │ │ │ ├── scoping/ │ │ │ │ └── c99_scoping_activation.sol │ │ │ ├── shanghai/ │ │ │ │ ├── evmone_support.sol │ │ │ │ └── push0.sol │ │ │ ├── smoke/ │ │ │ │ ├── alignment.sol │ │ │ │ ├── arrays.sol │ │ │ │ ├── basic.sol │ │ │ │ ├── bytes_and_strings.sol │ │ │ │ ├── constructor.sol │ │ │ │ ├── failure.sol │ │ │ │ ├── fallback.sol │ │ │ │ ├── multiline.sol │ │ │ │ ├── multiline_comments.sol │ │ │ │ └── structs.sol │ │ │ ├── specialFunctions/ │ │ │ │ ├── abi_encode_with_signature_from_string.sol │ │ │ │ ├── abi_functions_member_access.sol │ │ │ │ └── keccak256_optimized.sol │ │ │ ├── state/ │ │ │ │ ├── blobhash.sol │ │ │ │ ├── block_basefee.sol │ │ │ │ ├── block_blobbasefee.sol │ │ │ │ ├── block_chainid.sol │ │ │ │ ├── block_coinbase.sol │ │ │ │ ├── block_difficulty.sol │ │ │ │ ├── block_difficulty_post_paris.sol │ │ │ │ ├── block_gaslimit.sol │ │ │ │ ├── block_number.sol │ │ │ │ ├── block_prevrandao.sol │ │ │ │ ├── block_prevrandao_pre_paris.sol │ │ │ │ ├── block_timestamp.sol │ │ │ │ ├── blockhash_basic.sol │ │ │ │ ├── gasleft.sol │ │ │ │ ├── msg_data.sol │ │ │ │ ├── msg_sender.sol │ │ │ │ ├── msg_sig.sol │ │ │ │ ├── msg_value.sol │ │ │ │ ├── tx_gasprice.sol │ │ │ │ ├── tx_origin.sol │ │ │ │ ├── uncalled_blobhash.sol │ │ │ │ └── uncalled_blockhash.sol │ │ │ ├── statements/ │ │ │ │ ├── do_while_loop_continue.sol │ │ │ │ └── empty_for_loop.sol │ │ │ ├── storage/ │ │ │ │ ├── accessors_mapping_for_array.sol │ │ │ │ ├── array_accessor.sol │ │ │ │ ├── chop_sign_bits.sol │ │ │ │ ├── complex_accessors.sol │ │ │ │ ├── delete_overlapping_transient_after_inherited_storage_same_value_type.sol │ │ │ │ ├── delete_overlapping_transient_after_storage_array_delete_different_base_type.sol │ │ │ │ ├── delete_overlapping_transient_after_storage_array_pop_same_base_type.sol │ │ │ │ ├── delete_overlapping_transient_after_storage_delete_same_value_type.sol │ │ │ │ ├── delete_overlapping_transient_after_storage_mapping_delete_same_value_type.sol │ │ │ │ ├── delete_overlapping_transient_after_storage_struct_delete_same_value_type.sol │ │ │ │ ├── delete_overlapping_transient_before_inherited_storage_same_value_type.sol │ │ │ │ ├── delete_overlapping_transient_before_storage_array_delete_different_base_type.sol │ │ │ │ ├── delete_overlapping_transient_before_storage_array_partial_assignment_same_base_type.sol │ │ │ │ ├── delete_overlapping_transient_before_storage_delete_same_value_type.sol │ │ │ │ ├── delete_overlapping_transient_before_storage_mapping_delete_same_value_type.sol │ │ │ │ ├── delete_overlapping_transient_before_storage_struct_delete_same_value_type.sol │ │ │ │ ├── empty_nonempty_empty.sol │ │ │ │ ├── mapping_state.sol │ │ │ │ ├── mapping_string_key.sol │ │ │ │ ├── mappings_array2d_pop_delete.sol │ │ │ │ ├── mappings_array_pop_delete.sol │ │ │ │ ├── packed_functions.sol │ │ │ │ ├── packed_storage_overflow.sol │ │ │ │ ├── packed_storage_signed.sol │ │ │ │ ├── packed_storage_structs_bytes.sol │ │ │ │ ├── packed_storage_structs_enum.sol │ │ │ │ ├── packed_storage_structs_uint.sol │ │ │ │ ├── simple_accessor.sol │ │ │ │ ├── state_smoke_test.sol │ │ │ │ ├── static_array_copy_cleanup.sol │ │ │ │ ├── storage_boundary_array_and_partial_assignment_with_layout.sol │ │ │ │ ├── storage_boundary_array_assignment.sol │ │ │ │ ├── storage_boundary_array_copy.sol │ │ │ │ ├── storage_boundary_array_delete.sol │ │ │ │ ├── storage_boundary_array_delete_overlapping_variable.sol │ │ │ │ ├── storage_boundary_array_packing_not_overlapping_variable.sol │ │ │ │ ├── storage_boundary_array_partial_assignment.sol │ │ │ │ ├── storage_boundary_delete_overflow_bug.sol │ │ │ │ ├── storage_boundary_packed_array.sol │ │ │ │ ├── storage_boundary_struct_array_mixed_types.sol │ │ │ │ ├── storage_boundary_struct_array_multislot.sol │ │ │ │ ├── storage_boundary_struct_array_packed.sol │ │ │ │ ├── storage_packed_array_copy.sol │ │ │ │ └── struct_accessor.sol │ │ │ ├── storageLayoutSpecifier/ │ │ │ │ ├── base_slot_max_value.sol │ │ │ │ ├── constructor.sol │ │ │ │ ├── delete.sol │ │ │ │ ├── delete_transient_storage.sol │ │ │ │ ├── dynamic_array_storage_end.sol │ │ │ │ ├── function_from_base_contract.sol │ │ │ │ ├── getters.sol │ │ │ │ ├── inheritance_from_abstract_contract.sol │ │ │ │ ├── inheritance_from_interface.sol │ │ │ │ ├── inheritance_from_same_base_state_var_slots.sol │ │ │ │ ├── inheritance_simple.sol │ │ │ │ ├── inheritance_state_variable_slot_offset.sol │ │ │ │ ├── inline_assembly_direct_load.sol │ │ │ │ ├── inline_assembly_direct_store.sol │ │ │ │ ├── last_allowed_storage_slot.sol │ │ │ │ ├── mapping_storage_end.sol │ │ │ │ ├── multiple_inheritance.sol │ │ │ │ ├── multiple_inheritance_state_var_slots.sol │ │ │ │ ├── state_variable_arithmetic_expression.sol │ │ │ │ ├── state_variable_constant_and_immutable.sol │ │ │ │ ├── state_variable_dynamic_array.sol │ │ │ │ ├── state_variable_enum.sol │ │ │ │ ├── state_variable_mapping.sol │ │ │ │ ├── state_variable_reference_types_slot_offset.sol │ │ │ │ ├── state_variable_slot_offset.sol │ │ │ │ ├── state_variable_struct.sol │ │ │ │ ├── state_variables_transient.sol │ │ │ │ ├── storage_reference_array.sol │ │ │ │ ├── storage_reference_inheritance.sol │ │ │ │ ├── storage_reference_library_function.sol │ │ │ │ ├── transient_state_variable_slot_offset.sol │ │ │ │ ├── variable_cleanup.sol │ │ │ │ ├── variable_cleanup_sstore.sol │ │ │ │ └── virtual_functions.sol │ │ │ ├── strings/ │ │ │ │ ├── concat/ │ │ │ │ │ ├── string_concat_2_args.sol │ │ │ │ │ ├── string_concat_different_types.sol │ │ │ │ │ ├── string_concat_empty_argument_list.sol │ │ │ │ │ ├── string_concat_empty_strings.sol │ │ │ │ │ └── string_concat_nested.sol │ │ │ │ ├── constant_string_literal.sol │ │ │ │ ├── empty_storage_string.sol │ │ │ │ ├── empty_string.sol │ │ │ │ ├── empty_string_input.sol │ │ │ │ ├── return_string.sol │ │ │ │ ├── string_escapes.sol │ │ │ │ ├── unicode_escapes.sol │ │ │ │ └── unicode_string.sol │ │ │ ├── structs/ │ │ │ │ ├── array_of_recursive_struct.sol │ │ │ │ ├── calldata/ │ │ │ │ │ ├── calldata_nested_structs.sol │ │ │ │ │ ├── calldata_struct.sol │ │ │ │ │ ├── calldata_struct_and_ints.sol │ │ │ │ │ ├── calldata_struct_array_member.sol │ │ │ │ │ ├── calldata_struct_array_member_dynamic.sol │ │ │ │ │ ├── calldata_struct_as_argument_of_lib_function.sol │ │ │ │ │ ├── calldata_struct_as_memory_argument.sol │ │ │ │ │ ├── calldata_struct_struct_member.sol │ │ │ │ │ ├── calldata_struct_struct_member_dynamic.sol │ │ │ │ │ ├── calldata_struct_to_memory.sol │ │ │ │ │ ├── calldata_struct_to_memory_tuple_assignment.sol │ │ │ │ │ ├── calldata_struct_to_storage.sol │ │ │ │ │ ├── calldata_struct_with_array_to_memory.sol │ │ │ │ │ ├── calldata_struct_with_bytes_to_memory.sol │ │ │ │ │ ├── calldata_struct_with_nested_array_to_memory.sol │ │ │ │ │ ├── calldata_struct_with_nested_array_to_storage.sol │ │ │ │ │ ├── calldata_structs.sol │ │ │ │ │ ├── dynamic_nested.sol │ │ │ │ │ └── dynamically_encoded.sol │ │ │ │ ├── conversion/ │ │ │ │ │ ├── recursive_storage_memory.sol │ │ │ │ │ └── recursive_storage_memory_complex.sol │ │ │ │ ├── copy_from_mapping.sol │ │ │ │ ├── copy_from_storage.sol │ │ │ │ ├── copy_struct_array_from_storage.sol │ │ │ │ ├── copy_struct_with_nested_array_from_calldata_to_memory.sol │ │ │ │ ├── copy_struct_with_nested_array_from_calldata_to_storage.sol │ │ │ │ ├── copy_struct_with_nested_array_from_memory_to_memory.sol │ │ │ │ ├── copy_struct_with_nested_array_from_storage_to_storage.sol │ │ │ │ ├── copy_substructures_from_mapping.sol │ │ │ │ ├── copy_substructures_to_mapping.sol │ │ │ │ ├── copy_to_mapping.sol │ │ │ │ ├── delete_struct.sol │ │ │ │ ├── event.sol │ │ │ │ ├── function_type_copy.sol │ │ │ │ ├── global.sol │ │ │ │ ├── lone_struct_array_type.sol │ │ │ │ ├── memory_struct_named_constructor.sol │ │ │ │ ├── memory_structs_as_function_args.sol │ │ │ │ ├── memory_structs_nested.sol │ │ │ │ ├── memory_structs_nested_load.sol │ │ │ │ ├── memory_structs_read_write.sol │ │ │ │ ├── msg_data_to_struct_member_copy.sol │ │ │ │ ├── multislot_struct_allocation.sol │ │ │ │ ├── nested_struct_allocation.sol │ │ │ │ ├── packed_storage_structs_delete.sol │ │ │ │ ├── recursive_struct_2.sol │ │ │ │ ├── recursive_structs.sol │ │ │ │ ├── simple_struct_allocation.sol │ │ │ │ ├── struct_assign_reference_to_struct.sol │ │ │ │ ├── struct_constructor_nested.sol │ │ │ │ ├── struct_containing_bytes_copy_and_delete.sol │ │ │ │ ├── struct_copy.sol │ │ │ │ ├── struct_copy_via_local.sol │ │ │ │ ├── struct_delete_member.sol │ │ │ │ ├── struct_delete_storage.sol │ │ │ │ ├── struct_delete_storage_nested_small.sol │ │ │ │ ├── struct_delete_storage_small.sol │ │ │ │ ├── struct_delete_storage_with_array.sol │ │ │ │ ├── struct_delete_storage_with_arrays_small.sol │ │ │ │ ├── struct_delete_struct_in_mapping.sol │ │ │ │ ├── struct_memory_to_storage.sol │ │ │ │ ├── struct_memory_to_storage_function_ptr.sol │ │ │ │ ├── struct_named_constructor.sol │ │ │ │ ├── struct_reference.sol │ │ │ │ ├── struct_referencing.sol │ │ │ │ ├── struct_storage_push_zero_value.sol │ │ │ │ ├── struct_storage_to_mapping.sol │ │ │ │ ├── struct_storage_to_memory.sol │ │ │ │ ├── struct_storage_to_memory_function_ptr.sol │ │ │ │ ├── structs.sol │ │ │ │ └── using_for_function_on_struct.sol │ │ │ ├── tryCatch/ │ │ │ │ ├── assert.sol │ │ │ │ ├── assert_pre_byzantium.sol │ │ │ │ ├── create.sol │ │ │ │ ├── invalid_error_encoding.sol │ │ │ │ ├── lowLevel.sol │ │ │ │ ├── malformed_error.sol │ │ │ │ ├── malformed_panic.sol │ │ │ │ ├── malformed_panic_2.sol │ │ │ │ ├── malformed_panic_3.sol │ │ │ │ ├── malformed_panic_4.sol │ │ │ │ ├── nested.sol │ │ │ │ ├── panic.sol │ │ │ │ ├── require.sol │ │ │ │ ├── require_pre_byzantium.sol │ │ │ │ ├── return_function.sol │ │ │ │ ├── simple.sol │ │ │ │ ├── simple_notuple.sol │ │ │ │ ├── structured.sol │ │ │ │ ├── structuredAndLowLevel.sol │ │ │ │ └── try_catch_library_call.sol │ │ │ ├── types/ │ │ │ │ ├── array_mapping_abstract_constructor_param.sol │ │ │ │ ├── assign_calldata_value_type.sol │ │ │ │ ├── convert_fixed_bytes_to_fixed_bytes_greater_size.sol │ │ │ │ ├── convert_fixed_bytes_to_fixed_bytes_same_size.sol │ │ │ │ ├── convert_fixed_bytes_to_fixed_bytes_smaller_size.sol │ │ │ │ ├── convert_fixed_bytes_to_uint_greater_size.sol │ │ │ │ ├── convert_fixed_bytes_to_uint_same_min_size.sol │ │ │ │ ├── convert_fixed_bytes_to_uint_same_type.sol │ │ │ │ ├── convert_fixed_bytes_to_uint_smaller_size.sol │ │ │ │ ├── convert_uint_to_fixed_bytes_greater_size.sol │ │ │ │ ├── convert_uint_to_fixed_bytes_same_min_size.sol │ │ │ │ ├── convert_uint_to_fixed_bytes_same_size.sol │ │ │ │ ├── convert_uint_to_fixed_bytes_smaller_size.sol │ │ │ │ ├── external_function_to_address.sol │ │ │ │ ├── mapping/ │ │ │ │ │ ├── copy_from_mapping_to_mapping.sol │ │ │ │ │ ├── copy_struct_to_array_stored_in_mapping.sol │ │ │ │ │ └── user_defined_types_mapping_storage.sol │ │ │ │ ├── mapping_abstract_constructor_param.sol │ │ │ │ ├── mapping_contract_key.sol │ │ │ │ ├── mapping_contract_key_getter.sol │ │ │ │ ├── mapping_contract_key_library.sol │ │ │ │ ├── mapping_enum_key_getter_v1.sol │ │ │ │ ├── mapping_enum_key_getter_v2.sol │ │ │ │ ├── mapping_enum_key_library_v1.sol │ │ │ │ ├── mapping_enum_key_library_v2.sol │ │ │ │ ├── mapping_enum_key_v1.sol │ │ │ │ ├── mapping_enum_key_v2.sol │ │ │ │ ├── mapping_simple.sol │ │ │ │ ├── nested_tuples.sol │ │ │ │ ├── packing_signed_types.sol │ │ │ │ ├── packing_unpacking_types.sol │ │ │ │ ├── strings.sol │ │ │ │ ├── struct_mapping_abstract_constructor_param.sol │ │ │ │ ├── tuple_assign_multi_slot_grow.sol │ │ │ │ └── type_conversion_cleanup.sol │ │ │ ├── underscore/ │ │ │ │ └── as_function.sol │ │ │ ├── uninitializedFunctionPointer/ │ │ │ │ ├── invalidInConstructor.sol │ │ │ │ ├── invalidStoredInConstructor.sol │ │ │ │ ├── store2.sol │ │ │ │ ├── storeInConstructor.sol │ │ │ │ ├── uninitialized_internal_storage_function_legacy.sol │ │ │ │ └── uninitialized_internal_storage_function_via_yul.sol │ │ │ ├── userDefinedValueType/ │ │ │ │ ├── abicodec.sol │ │ │ │ ├── assembly_access_bytes2_abicoder_v1.sol │ │ │ │ ├── assembly_access_bytes2_abicoder_v2.sol │ │ │ │ ├── calldata.sol │ │ │ │ ├── calldata_to_storage.sol │ │ │ │ ├── cleanup.sol │ │ │ │ ├── cleanup_abicoderv1.sol │ │ │ │ ├── constant.sol │ │ │ │ ├── conversion.sol │ │ │ │ ├── conversion_abicoderv1.sol │ │ │ │ ├── dirty_slot.sol │ │ │ │ ├── dirty_uint8_read.sol │ │ │ │ ├── erc20.sol │ │ │ │ ├── fixedpoint.sol │ │ │ │ ├── immutable_signed.sol │ │ │ │ ├── in_parenthesis.sol │ │ │ │ ├── mapping_key.sol │ │ │ │ ├── memory_to_storage.sol │ │ │ │ ├── multisource.sol │ │ │ │ ├── multisource_module.sol │ │ │ │ ├── ownable.sol │ │ │ │ ├── parameter.sol │ │ │ │ ├── simple.sol │ │ │ │ ├── storage_layout.sol │ │ │ │ ├── storage_layout_struct.sol │ │ │ │ ├── storage_signed.sol │ │ │ │ ├── wrap_unwrap.sol │ │ │ │ ├── wrap_unwrap_via_contract_name.sol │ │ │ │ ├── zero_cost_abstraction_comparison_elementary.sol │ │ │ │ └── zero_cost_abstraction_comparison_userdefined.sol │ │ │ ├── using/ │ │ │ │ ├── calldata_memory_copy.sol │ │ │ │ ├── free_function_braces.sol │ │ │ │ ├── free_function_multi.sol │ │ │ │ ├── free_functions_individual.sol │ │ │ │ ├── imported_functions.sol │ │ │ │ ├── library_functions_inside_contract.sol │ │ │ │ ├── library_on_interface.sol │ │ │ │ ├── library_through_module.sol │ │ │ │ ├── module_renamed.sol │ │ │ │ ├── private_library_function.sol │ │ │ │ ├── recursive_import.sol │ │ │ │ ├── using_global_all_the_types.sol │ │ │ │ ├── using_global_for_global.sol │ │ │ │ ├── using_global_invisible.sol │ │ │ │ └── using_global_library.sol │ │ │ ├── variables/ │ │ │ │ ├── delete_local.sol │ │ │ │ ├── delete_locals.sol │ │ │ │ ├── delete_transient_state_variable.sol │ │ │ │ ├── delete_transient_state_variable_non_zero_offset.sol │ │ │ │ ├── mapping_local_assignment.sol │ │ │ │ ├── mapping_local_compound_assignment.sol │ │ │ │ ├── mapping_local_tuple_assignment.sol │ │ │ │ ├── public_state_overridding.sol │ │ │ │ ├── public_state_overridding_dynamic_struct.sol │ │ │ │ ├── public_state_overridding_mapping_to_dynamic_struct.sol │ │ │ │ ├── storing_invalid_boolean.sol │ │ │ │ ├── transient_function_type_state_variable.sol │ │ │ │ ├── transient_state_address_variable_members.sol │ │ │ │ ├── transient_state_enum_variable.sol │ │ │ │ ├── transient_state_variable.sol │ │ │ │ ├── transient_state_variable_cleanup_assignment.sol │ │ │ │ ├── transient_state_variable_cleanup_tstore.sol │ │ │ │ ├── transient_state_variable_slot_inline_assembly.sol │ │ │ │ ├── transient_state_variable_slots_and_offsets.sol │ │ │ │ ├── transient_state_variable_tuple_assignment.sol │ │ │ │ └── transient_state_variable_udvt.sol │ │ │ ├── various/ │ │ │ │ ├── address_code.sol │ │ │ │ ├── address_code_complex.sol │ │ │ │ ├── assignment_to_const_var_involving_expression.sol │ │ │ │ ├── balance.sol │ │ │ │ ├── byte_optimization_bug.sol │ │ │ │ ├── code_access_content.sol │ │ │ │ ├── code_access_create.sol │ │ │ │ ├── code_access_padding.sol │ │ │ │ ├── code_access_runtime.sol │ │ │ │ ├── code_length.sol │ │ │ │ ├── code_length_contract_member.sol │ │ │ │ ├── codebalance_assembly.sol │ │ │ │ ├── codehash.sol │ │ │ │ ├── codehash_assembly.sol │ │ │ │ ├── contract_binary_dependencies.sol │ │ │ │ ├── crazy_elementary_typenames_on_stack.sol │ │ │ │ ├── create_calldata.sol │ │ │ │ ├── create_random.sol │ │ │ │ ├── cross_contract_types.sol │ │ │ │ ├── decayed_tuple.sol │ │ │ │ ├── destructuring_assignment.sol │ │ │ │ ├── different_call_type_transient.sol │ │ │ │ ├── empty_name_return_parameter.sol │ │ │ │ ├── eof/ │ │ │ │ │ └── create_calldata.sol │ │ │ │ ├── erc20.sol │ │ │ │ ├── external_types_in_calls.sol │ │ │ │ ├── flipping_sign_tests.sol │ │ │ │ ├── gasleft_decrease.sol │ │ │ │ ├── gasleft_shadow_resolution.sol │ │ │ │ ├── inline_member_init.sol │ │ │ │ ├── inline_member_init_inheritence.sol │ │ │ │ ├── inline_tuple_with_rational_numbers.sol │ │ │ │ ├── iszero_bnot_correct.sol │ │ │ │ ├── literal_empty_string.sol │ │ │ │ ├── many_subassemblies.sol │ │ │ │ ├── memory_overwrite.sol │ │ │ │ ├── multi_modifiers.sol │ │ │ │ ├── multi_variable_declaration.sol │ │ │ │ ├── negative_stack_height.sol │ │ │ │ ├── nested_calldata_struct.sol │ │ │ │ ├── nested_calldata_struct_to_memory.sol │ │ │ │ ├── positive_integers_to_signed.sol │ │ │ │ ├── selfdestruct_post_cancun.sol │ │ │ │ ├── selfdestruct_post_cancun_multiple_beneficiaries.sol │ │ │ │ ├── selfdestruct_post_cancun_redeploy.sol │ │ │ │ ├── selfdestruct_pre_cancun.sol │ │ │ │ ├── selfdestruct_pre_cancun_multiple_beneficiaries.sol │ │ │ │ ├── selfdestruct_pre_cancun_redeploy.sol │ │ │ │ ├── senders_balance.sol │ │ │ │ ├── single_copy_with_multiple_inheritance.sol │ │ │ │ ├── skip_dynamic_types.sol │ │ │ │ ├── skip_dynamic_types_for_static_arrays_with_dynamic_elements.sol │ │ │ │ ├── skip_dynamic_types_for_structs.sol │ │ │ │ ├── state_variable_local_variable_mixture.sol │ │ │ │ ├── state_variable_under_contract_name.sol │ │ │ │ ├── staticcall_for_view_and_pure.sol │ │ │ │ ├── staticcall_for_view_and_pure_pre_byzantium.sol │ │ │ │ ├── storage_string_as_mapping_key_without_variable.sol │ │ │ │ ├── store_bytes.sol │ │ │ │ ├── string_tuples.sol │ │ │ │ ├── super.sol │ │ │ │ ├── super_alone.sol │ │ │ │ ├── super_parentheses.sol │ │ │ │ ├── swap_in_storage_overwrite.sol │ │ │ │ ├── test_underscore_in_hex.sol │ │ │ │ ├── transient_storage_reentrancy_lock.sol │ │ │ │ ├── tuples.sol │ │ │ │ ├── typed_multi_variable_declaration.sol │ │ │ │ └── write_storage_external.sol │ │ │ ├── viaYul/ │ │ │ │ ├── assert.sol │ │ │ │ ├── assert_and_require.sol │ │ │ │ ├── assign_tuple_from_function_call.sol │ │ │ │ ├── cleanup/ │ │ │ │ │ ├── checked_arithmetic.sol │ │ │ │ │ └── comparison.sol │ │ │ │ ├── comparison.sol │ │ │ │ ├── comparison_functions.sol │ │ │ │ ├── conditional/ │ │ │ │ │ ├── conditional_multiple.sol │ │ │ │ │ ├── conditional_true_false_literal.sol │ │ │ │ │ ├── conditional_tuple.sol │ │ │ │ │ ├── conditional_with_assignment.sol │ │ │ │ │ └── conditional_with_variables.sol │ │ │ │ ├── conversion/ │ │ │ │ │ ├── explicit_cast_assignment.sol │ │ │ │ │ ├── explicit_cast_function_call.sol │ │ │ │ │ ├── explicit_cast_local_assignment.sol │ │ │ │ │ ├── explicit_string_bytes_calldata_cast.sol │ │ │ │ │ ├── function_cast.sol │ │ │ │ │ ├── implicit_cast_assignment.sol │ │ │ │ │ ├── implicit_cast_function_call.sol │ │ │ │ │ └── implicit_cast_local_assignment.sol │ │ │ │ ├── copy_struct_invalid_ir_bug.sol │ │ │ │ ├── define_tuple_from_function_call.sol │ │ │ │ ├── delete.sol │ │ │ │ ├── detect_add_overflow.sol │ │ │ │ ├── detect_add_overflow_signed.sol │ │ │ │ ├── detect_div_overflow.sol │ │ │ │ ├── detect_mod_zero.sol │ │ │ │ ├── detect_mod_zero_signed.sol │ │ │ │ ├── detect_mul_overflow.sol │ │ │ │ ├── detect_mul_overflow_signed.sol │ │ │ │ ├── detect_sub_overflow.sol │ │ │ │ ├── detect_sub_overflow_signed.sol │ │ │ │ ├── dirty_calldata_struct.sol │ │ │ │ ├── dirty_memory_dynamic_array.sol │ │ │ │ ├── dirty_memory_int32.sol │ │ │ │ ├── dirty_memory_static_array.sol │ │ │ │ ├── dirty_memory_struct.sol │ │ │ │ ├── dirty_memory_uint32.sol │ │ │ │ ├── empty_return_corrupted_free_memory_pointer.sol │ │ │ │ ├── exp.sol │ │ │ │ ├── exp_literals.sol │ │ │ │ ├── exp_literals_success.sol │ │ │ │ ├── exp_neg.sol │ │ │ │ ├── exp_neg_overflow.sol │ │ │ │ ├── exp_overflow.sol │ │ │ │ ├── exp_various.sol │ │ │ │ ├── function_address.sol │ │ │ │ ├── function_entry_checks.sol │ │ │ │ ├── function_pointers.sol │ │ │ │ ├── function_selector.sol │ │ │ │ ├── if.sol │ │ │ │ ├── keccak.sol │ │ │ │ ├── local_address_assignment.sol │ │ │ │ ├── local_assignment.sol │ │ │ │ ├── local_bool_assignment.sol │ │ │ │ ├── local_tuple_assignment.sol │ │ │ │ ├── local_variable_without_init.sol │ │ │ │ ├── loops/ │ │ │ │ │ ├── break.sol │ │ │ │ │ ├── continue.sol │ │ │ │ │ ├── return.sol │ │ │ │ │ └── simple.sol │ │ │ │ ├── mapping_enum_key_getter.sol │ │ │ │ ├── mapping_getters.sol │ │ │ │ ├── mapping_string_key.sol │ │ │ │ ├── memory_struct_allow.sol │ │ │ │ ├── msg_sender.sol │ │ │ │ ├── negation_bug.sol │ │ │ │ ├── require.sol │ │ │ │ ├── return.sol │ │ │ │ ├── return_and_convert.sol │ │ │ │ ├── return_storage_pointers.sol │ │ │ │ ├── short_circuit.sol │ │ │ │ ├── simple_assignment.sol │ │ │ │ ├── simple_inline_asm.sol │ │ │ │ ├── smoke_test.sol │ │ │ │ ├── storage/ │ │ │ │ │ ├── dirty_storage_bytes.sol │ │ │ │ │ ├── dirty_storage_bytes_long.sol │ │ │ │ │ ├── dirty_storage_dynamic_array.sol │ │ │ │ │ ├── dirty_storage_static_array.sol │ │ │ │ │ ├── dirty_storage_struct.sol │ │ │ │ │ ├── mappings.sol │ │ │ │ │ ├── packed_storage.sol │ │ │ │ │ └── simple_storage.sol │ │ │ │ ├── string_format.sol │ │ │ │ ├── string_literals.sol │ │ │ │ ├── struct_member_access.sol │ │ │ │ ├── tuple_evaluation_order.sol │ │ │ │ ├── unary_fixedbytes.sol │ │ │ │ ├── unary_operations.sol │ │ │ │ ├── various_inline_asm.sol │ │ │ │ └── virtual_functions.sol │ │ │ └── virtualFunctions/ │ │ │ ├── internal_virtual_function_calls.sol │ │ │ ├── internal_virtual_function_calls_through_dispatch.sol │ │ │ ├── virtual_function_calls.sol │ │ │ ├── virtual_function_usage_in_constructor_arguments.sol │ │ │ ├── virtual_override_changing_mutability_internal.sol │ │ │ └── virtual_override_changing_mutability_public.sol │ │ ├── smtCheckerTests/ │ │ │ ├── abi/ │ │ │ │ ├── abi_decode_1_tuple.sol │ │ │ │ ├── abi_decode_array.sol │ │ │ │ ├── abi_decode_simple.sol │ │ │ │ ├── abi_encode_array_slice.sol │ │ │ │ ├── abi_encode_array_slice_2.sol │ │ │ │ ├── abi_encode_call_simple_1.sol │ │ │ │ ├── abi_encode_call_simple_2.sol │ │ │ │ ├── abi_encode_call_simple_3.sol │ │ │ │ ├── abi_encode_call_simple_4.sol │ │ │ │ ├── abi_encode_call_simple_5.sol │ │ │ │ ├── abi_encode_function.sol │ │ │ │ ├── abi_encode_hash.sol │ │ │ │ ├── abi_encode_no_arguments.sol │ │ │ │ ├── abi_encode_packed_array_slice.sol │ │ │ │ ├── abi_encode_packed_array_slice_2.sol │ │ │ │ ├── abi_encode_packed_hash.sol │ │ │ │ ├── abi_encode_packed_simple.sol │ │ │ │ ├── abi_encode_packed_string_literal.sol │ │ │ │ ├── abi_encode_packed_string_literal_no_unproved.sol │ │ │ │ ├── abi_encode_simple.sol │ │ │ │ ├── abi_encode_string_literal.sol │ │ │ │ ├── abi_encode_with_selector_array_slice.sol │ │ │ │ ├── abi_encode_with_selector_array_slice_2.sol │ │ │ │ ├── abi_encode_with_selector_hash.sol │ │ │ │ ├── abi_encode_with_selector_simple.sol │ │ │ │ ├── abi_encode_with_selector_string_literal.sol │ │ │ │ ├── abi_encode_with_selector_string_literal_2.sol │ │ │ │ ├── abi_encode_with_selector_vs_sig.sol │ │ │ │ ├── abi_encode_with_sig_array_slice.sol │ │ │ │ ├── abi_encode_with_sig_array_slice_2.sol │ │ │ │ ├── abi_encode_with_sig_hash.sol │ │ │ │ ├── abi_encode_with_sig_simple.sol │ │ │ │ └── abi_encode_with_sig_string_literal.sol │ │ │ ├── array_members/ │ │ │ │ ├── array_pop_length_1.sol │ │ │ │ ├── array_pop_length_2.sol │ │ │ │ ├── array_pop_length_3.sol │ │ │ │ ├── array_pop_length_4.sol │ │ │ │ ├── array_pop_length_5.sol │ │ │ │ ├── array_pop_length_6.sol │ │ │ │ ├── array_pop_length_7.sol │ │ │ │ ├── array_pop_length_8.sol │ │ │ │ ├── array_push_string_literal.sol │ │ │ │ ├── length_1d_assignment_2d_memory_to_memory.sol │ │ │ │ ├── length_1d_assignment_2d_storage_to_storage.sol │ │ │ │ ├── length_1d_copy_2d_memory_to_storage.sol │ │ │ │ ├── length_1d_copy_2d_storage_to_memory.sol │ │ │ │ ├── length_1d_mapping_array_1.sol │ │ │ │ ├── length_1d_mapping_array_2.sol │ │ │ │ ├── length_1d_mapping_array_2d_1.sol │ │ │ │ ├── length_1d_struct_array_1.sol │ │ │ │ ├── length_1d_struct_array_2d_1.sol │ │ │ │ ├── length_assignment_2d_memory_to_memory.sol │ │ │ │ ├── length_assignment_memory_to_memory.sol │ │ │ │ ├── length_assignment_storage_to_storage.sol │ │ │ │ ├── length_basic.sol │ │ │ │ ├── length_copy_memory_to_storage.sol │ │ │ │ ├── length_copy_storage_to_memory.sol │ │ │ │ ├── length_function_call.sol │ │ │ │ ├── length_same_after_assignment.sol │ │ │ │ ├── length_same_after_assignment_2.sol │ │ │ │ ├── length_same_after_assignment_2_fail.sol │ │ │ │ ├── length_same_after_assignment_3.sol │ │ │ │ ├── length_same_after_assignment_3_fail.sol │ │ │ │ ├── pop_1_safe.sol │ │ │ │ ├── pop_1_unsafe.sol │ │ │ │ ├── pop_2d_safe.sol │ │ │ │ ├── pop_2d_unsafe.sol │ │ │ │ ├── pop_constructor_safe.sol │ │ │ │ ├── pop_constructor_unsafe.sol │ │ │ │ ├── pop_loop_safe.sol │ │ │ │ ├── pop_loop_unsafe.sol │ │ │ │ ├── push_2d_arg_1_safe.sol │ │ │ │ ├── push_2d_arg_1_unsafe.sol │ │ │ │ ├── push_arg_1.sol │ │ │ │ ├── push_as_lhs_1d.sol │ │ │ │ ├── push_as_lhs_2d.sol │ │ │ │ ├── push_as_lhs_2d_2.sol │ │ │ │ ├── push_as_lhs_3d.sol │ │ │ │ ├── push_as_lhs_and_rhs_1d.sol │ │ │ │ ├── push_as_lhs_and_rhs_2d_1.sol │ │ │ │ ├── push_as_lhs_and_rhs_2d_2.sol │ │ │ │ ├── push_as_lhs_and_rhs_bytes.sol │ │ │ │ ├── push_as_lhs_bytes.sol │ │ │ │ ├── push_as_lhs_bytes_2d.sol │ │ │ │ ├── push_as_lhs_compound_assignment.sol │ │ │ │ ├── push_as_lhs_struct.sol │ │ │ │ ├── push_function_return_value.sol │ │ │ │ ├── push_overflow_1_safe.sol │ │ │ │ ├── push_overflow_1_safe_no_overflow_assumption.sol │ │ │ │ ├── push_overflow_2_safe.sol │ │ │ │ ├── push_overflow_2_safe_no_overflow_assumption.sol │ │ │ │ ├── push_push_no_args_1.sol │ │ │ │ ├── push_push_no_args_1_fail.sol │ │ │ │ ├── push_push_no_args_2.sol │ │ │ │ ├── push_push_no_args_2_fail.sol │ │ │ │ ├── push_storage_ref_safe_aliasing.sol │ │ │ │ ├── push_storage_ref_unsafe_aliasing.sol │ │ │ │ ├── push_storage_ref_unsafe_length.sol │ │ │ │ ├── push_struct_member_1.sol │ │ │ │ ├── push_struct_member_2.sol │ │ │ │ ├── push_zero_2d_safe.sol │ │ │ │ ├── push_zero_2d_unsafe.sol │ │ │ │ ├── push_zero_safe.sol │ │ │ │ ├── push_zero_unsafe.sol │ │ │ │ ├── storage_pointer_push_1.sol │ │ │ │ └── storage_pointer_push_1_safe.sol │ │ │ ├── blockchain_state/ │ │ │ │ ├── balance_non_zero.sol │ │ │ │ ├── balance_non_zero_2.sol │ │ │ │ ├── balance_receive.sol │ │ │ │ ├── balance_receive_2.sol │ │ │ │ ├── balance_receive_3.sol │ │ │ │ ├── balance_receive_4.sol │ │ │ │ ├── balance_receive_5.sol │ │ │ │ ├── balance_receive_calls.sol │ │ │ │ ├── balance_receive_ext_calls.sol │ │ │ │ ├── balance_receive_ext_calls_2.sol │ │ │ │ ├── balance_receive_ext_calls_mutex.sol │ │ │ │ ├── balance_spend.sol │ │ │ │ ├── balance_spend_2.sol │ │ │ │ ├── balance_zero.sol │ │ │ │ ├── balance_zero_2.sol │ │ │ │ ├── balance_zero_3.sol │ │ │ │ ├── balance_zero_4.sol │ │ │ │ ├── decreasing_balance.sol │ │ │ │ ├── free_function_1.sol │ │ │ │ ├── free_function_2.sol │ │ │ │ ├── library_internal_1.sol │ │ │ │ ├── library_internal_2.sol │ │ │ │ ├── library_public_1.sol │ │ │ │ ├── library_public_2.sol │ │ │ │ ├── library_public_3.sol │ │ │ │ ├── library_public_4.sol │ │ │ │ ├── this_does_not_change.sol │ │ │ │ ├── this_does_not_change_external_call.sol │ │ │ │ ├── this_does_not_change_internal_call.sol │ │ │ │ ├── transfer_1.sol │ │ │ │ ├── transfer_2.sol │ │ │ │ ├── transfer_3.sol │ │ │ │ └── transfer_4.sol │ │ │ ├── bmc_coverage/ │ │ │ │ ├── assert.sol │ │ │ │ ├── assert_in_constructor.sol │ │ │ │ ├── branches_with_return/ │ │ │ │ │ ├── branches_in_modifiers.sol │ │ │ │ │ ├── branches_in_modifiers_2.sol │ │ │ │ │ ├── constructor_state_variable_init.sol │ │ │ │ │ ├── constructor_state_variable_init_chain_alternate.sol │ │ │ │ │ ├── constructor_state_variable_init_diamond.sol │ │ │ │ │ ├── constructors.sol │ │ │ │ │ ├── nested_if.sol │ │ │ │ │ ├── return_in_both_branches.sol │ │ │ │ │ ├── simple_if.sol │ │ │ │ │ ├── simple_if2.sol │ │ │ │ │ ├── simple_if_array.sol │ │ │ │ │ ├── simple_if_state_var.sol │ │ │ │ │ ├── simple_if_struct.sol │ │ │ │ │ ├── simple_if_struct_2.sol │ │ │ │ │ ├── simple_if_tuple.sol │ │ │ │ │ └── triple_nested_if.sol │ │ │ │ ├── call_balance.sol │ │ │ │ ├── call_state_var.sol │ │ │ │ ├── compound_bitwise_or_uint_3.sol │ │ │ │ ├── cross_contract_getter_call.sol │ │ │ │ ├── funds.sol │ │ │ │ ├── implicit_constructor_with_function_calls.sol │ │ │ │ ├── math.sol │ │ │ │ ├── math_constructor.sol │ │ │ │ ├── msg_value_4.sol │ │ │ │ ├── range_check.sol │ │ │ │ ├── staticcall_balance.sol │ │ │ │ ├── staticcall_state_var.sol │ │ │ │ ├── timestamp.sol │ │ │ │ ├── try_multiple_catch_clauses_2.sol │ │ │ │ ├── try_multiple_returned_values_with_tuple.sol │ │ │ │ ├── unary_add_minus_overflow_detected.sol │ │ │ │ └── unchecked_function_call_with_unchecked_block.sol │ │ │ ├── bytes_concat/ │ │ │ │ ├── equals.sol │ │ │ │ ├── one_arg_call.sol │ │ │ │ └── simple.sol │ │ │ ├── complex/ │ │ │ │ ├── MerkleProof.sol │ │ │ │ ├── slither/ │ │ │ │ │ ├── const_state_variables.sol │ │ │ │ │ ├── data_dependency.sol │ │ │ │ │ └── external_function.sol │ │ │ │ └── warn_on_typecast.sol │ │ │ ├── control_flow/ │ │ │ │ ├── assignment_in_declaration.sol │ │ │ │ ├── branches_assert_condition_1.sol │ │ │ │ ├── branches_assert_condition_2.sol │ │ │ │ ├── branches_inside_modifiers_1.sol │ │ │ │ ├── branches_inside_modifiers_2.sol │ │ │ │ ├── branches_inside_modifiers_3.sol │ │ │ │ ├── branches_inside_modifiers_4.sol │ │ │ │ ├── branches_merge_variables_1.sol │ │ │ │ ├── branches_merge_variables_2.sol │ │ │ │ ├── branches_merge_variables_3.sol │ │ │ │ ├── branches_merge_variables_4.sol │ │ │ │ ├── branches_merge_variables_5.sol │ │ │ │ ├── branches_merge_variables_6.sol │ │ │ │ ├── branches_with_return/ │ │ │ │ │ ├── branches_in_modifiers.sol │ │ │ │ │ ├── branches_in_modifiers_2.sol │ │ │ │ │ ├── constructor_state_variable_init.sol │ │ │ │ │ ├── constructor_state_variable_init_chain_alternate.sol │ │ │ │ │ ├── constructor_state_variable_init_diamond.sol │ │ │ │ │ ├── constructors.sol │ │ │ │ │ ├── nested_if.sol │ │ │ │ │ ├── return_in_both_branches.sol │ │ │ │ │ ├── simple_if.sol │ │ │ │ │ ├── simple_if2.sol │ │ │ │ │ ├── simple_if_array.sol │ │ │ │ │ ├── simple_if_state_var.sol │ │ │ │ │ ├── simple_if_struct.sol │ │ │ │ │ ├── simple_if_struct_2.sol │ │ │ │ │ ├── simple_if_tuple.sol │ │ │ │ │ └── triple_nested_if.sol │ │ │ │ ├── function_call_inside_branch.sol │ │ │ │ ├── function_call_inside_branch_2.sol │ │ │ │ ├── function_call_inside_branch_3.sol │ │ │ │ ├── function_call_inside_branch_4.sol │ │ │ │ ├── function_call_inside_else_branch.sol │ │ │ │ ├── function_call_inside_modifier_branch.sol │ │ │ │ ├── function_call_inside_placeholder_inside_modifier_branch.sol │ │ │ │ ├── require.sol │ │ │ │ ├── return_1.sol │ │ │ │ ├── return_1_fail.sol │ │ │ │ ├── return_2.sol │ │ │ │ ├── return_2_fail.sol │ │ │ │ ├── revert.sol │ │ │ │ ├── revert_complex_flow.sol │ │ │ │ ├── short_circuit_and.sol │ │ │ │ ├── short_circuit_and_fail.sol │ │ │ │ ├── short_circuit_and_inside_branch.sol │ │ │ │ ├── short_circuit_and_need_both.sol │ │ │ │ ├── short_circuit_and_need_both_fail.sol │ │ │ │ ├── short_circuit_and_touched.sol │ │ │ │ ├── short_circuit_and_touched_function.sol │ │ │ │ ├── short_circuit_or.sol │ │ │ │ ├── short_circuit_or_fail.sol │ │ │ │ ├── short_circuit_or_inside_branch.sol │ │ │ │ ├── short_circuit_or_need_both.sol │ │ │ │ ├── short_circuit_or_need_both_fail.sol │ │ │ │ ├── short_circuit_or_touched.sol │ │ │ │ ├── short_circuit_or_touched_function.sol │ │ │ │ ├── side_effects_inside_if_1.sol │ │ │ │ ├── side_effects_inside_if_2.sol │ │ │ │ ├── side_effects_inside_if_3.sol │ │ │ │ ├── side_effects_inside_if_4.sol │ │ │ │ ├── side_effects_inside_ternary_1.sol │ │ │ │ ├── side_effects_inside_ternary_2.sol │ │ │ │ ├── side_effects_inside_ternary_3.sol │ │ │ │ ├── side_effects_inside_ternary_4.sol │ │ │ │ ├── try_catch_1.sol │ │ │ │ ├── try_catch_2.sol │ │ │ │ ├── virtual_function_call_inside_branch_1.sol │ │ │ │ ├── virtual_function_call_inside_branch_2.sol │ │ │ │ ├── ways_to_merge_variables_1.sol │ │ │ │ ├── ways_to_merge_variables_2.sol │ │ │ │ └── ways_to_merge_variables_3.sol │ │ │ ├── crypto/ │ │ │ │ ├── crypto_functions_compare_hashes.sol │ │ │ │ ├── crypto_functions_fail.sol │ │ │ │ ├── crypto_functions_not_same.sol │ │ │ │ ├── crypto_functions_over_blocks.sol │ │ │ │ ├── crypto_functions_same_array.sol │ │ │ │ ├── crypto_functions_same_input_over_state_same_output.sol │ │ │ │ ├── crypto_functions_same_input_over_state_same_output_fail.sol │ │ │ │ ├── crypto_functions_same_input_same_output.sol │ │ │ │ └── crypto_functions_same_string_literal.sol │ │ │ ├── deployment/ │ │ │ │ ├── deploy_bmc_trusted.sol │ │ │ │ ├── deploy_bmc_untrusted.sol │ │ │ │ ├── deploy_trusted.sol │ │ │ │ ├── deploy_trusted_addresses.sol │ │ │ │ ├── deploy_trusted_flow.sol │ │ │ │ ├── deploy_trusted_keep_storage_constraints.sol │ │ │ │ ├── deploy_trusted_state_flow.sol │ │ │ │ ├── deploy_trusted_state_flow_2.sol │ │ │ │ ├── deploy_trusted_state_flow_3.sol │ │ │ │ ├── deploy_trusted_state_flow_4.sol │ │ │ │ ├── deploy_untrusted.sol │ │ │ │ ├── deploy_untrusted_addresses.sol │ │ │ │ ├── deploy_untrusted_erase_storage_constraints.sol │ │ │ │ └── deployment_trusted_with_value_1.sol │ │ │ ├── external_calls/ │ │ │ │ ├── call_abstract_constructor_trusted_1.sol │ │ │ │ ├── call_abstract_constructor_trusted_2.sol │ │ │ │ ├── call_abstract_trusted_1.sol │ │ │ │ ├── call_abstract_trusted_2.sol │ │ │ │ ├── call_abstract_trusted_3.sol │ │ │ │ ├── call_constructor_1.sol │ │ │ │ ├── call_constructor_2.sol │ │ │ │ ├── call_mutex.sol │ │ │ │ ├── call_mutex_unsafe.sol │ │ │ │ ├── call_reentrancy_1.sol │ │ │ │ ├── call_reentrancy_view.sol │ │ │ │ ├── call_return_1.sol │ │ │ │ ├── call_return_2.sol │ │ │ │ ├── call_safe.sol │ │ │ │ ├── call_with_value_1.sol │ │ │ │ ├── call_with_value_2.sol │ │ │ │ ├── call_with_value_3.sol │ │ │ │ ├── external.sol │ │ │ │ ├── external_call_extra_parentheses_1.sol │ │ │ │ ├── external_call_extra_parentheses_2.sol │ │ │ │ ├── external_call_from_constructor_1.sol │ │ │ │ ├── external_call_from_constructor_1_trusted.sol │ │ │ │ ├── external_call_from_constructor_2.sol │ │ │ │ ├── external_call_from_constructor_2_trusted.sol │ │ │ │ ├── external_call_from_constructor_3.sol │ │ │ │ ├── external_call_from_constructor_3_trusted.sol │ │ │ │ ├── external_call_from_constructor_reentrancy_1.sol │ │ │ │ ├── external_call_indirect_1.sol │ │ │ │ ├── external_call_indirect_2.sol │ │ │ │ ├── external_call_indirect_3.sol │ │ │ │ ├── external_call_indirect_4.sol │ │ │ │ ├── external_call_indirect_5.sol │ │ │ │ ├── external_call_semantic_this_1.sol │ │ │ │ ├── external_call_semantic_this_2.sol │ │ │ │ ├── external_call_semantic_this_3.sol │ │ │ │ ├── external_call_state_var_address_inside_array_struct_trusted_1.sol │ │ │ │ ├── external_call_state_var_address_inside_array_struct_trusted_2.sol │ │ │ │ ├── external_call_state_var_address_inside_array_trusted_1.sol │ │ │ │ ├── external_call_state_var_address_inside_array_trusted_2.sol │ │ │ │ ├── external_call_state_var_address_inside_struct_trusted_1.sol │ │ │ │ ├── external_call_state_var_address_inside_struct_trusted_2.sol │ │ │ │ ├── external_call_state_var_address_inside_struct_trusted_3.sol │ │ │ │ ├── external_call_state_var_address_inside_struct_trusted_4.sol │ │ │ │ ├── external_call_state_var_contract_inside_array_struct_trusted_1.sol │ │ │ │ ├── external_call_state_var_contract_inside_array_struct_trusted_2.sol │ │ │ │ ├── external_call_state_var_contract_inside_array_trusted_1.sol │ │ │ │ ├── external_call_state_var_contract_inside_array_trusted_2.sol │ │ │ │ ├── external_call_state_var_contract_inside_struct_trusted_1.sol │ │ │ │ ├── external_call_state_var_contract_inside_struct_trusted_2.sol │ │ │ │ ├── external_call_state_var_contract_inside_struct_trusted_3.sol │ │ │ │ ├── external_call_state_var_contract_inside_struct_trusted_4.sol │ │ │ │ ├── external_call_this_with_value_1.sol │ │ │ │ ├── external_call_this_with_value_2.sol │ │ │ │ ├── external_call_with_gas_1.sol │ │ │ │ ├── external_call_with_value_1.sol │ │ │ │ ├── external_call_with_value_2.sol │ │ │ │ ├── external_call_with_value_3.sol │ │ │ │ ├── external_hash.sol │ │ │ │ ├── external_hash_known_code_pure.sol │ │ │ │ ├── external_hash_known_code_pure_trusted.sol │ │ │ │ ├── external_hash_known_code_state.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_2.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_2_trusted.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_3.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_indirect.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_indirect_trusted.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_trusted.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_unsafe.sol │ │ │ │ ├── external_hash_known_code_state_reentrancy_unsafe_trusted.sol │ │ │ │ ├── external_hash_known_code_state_trusted.sol │ │ │ │ ├── external_hash_known_code_state_unsafe.sol │ │ │ │ ├── external_hash_known_code_state_unsafe_trusted.sol │ │ │ │ ├── external_inc.sol │ │ │ │ ├── external_inc1_inc2.sol │ │ │ │ ├── external_reentrancy_1.sol │ │ │ │ ├── external_reentrancy_2.sol │ │ │ │ ├── external_reentrancy_3.sol │ │ │ │ ├── external_reentrancy_crypto.sol │ │ │ │ ├── external_safe.sol │ │ │ │ ├── external_single_inc.sol │ │ │ │ ├── internal_library_external_call_1.sol │ │ │ │ ├── internal_library_external_call_2.sol │ │ │ │ ├── internal_library_external_call_3.sol │ │ │ │ ├── mutex.sol │ │ │ │ ├── mutex_f_no_guard.sol │ │ │ │ ├── staticcall_mutex.sol │ │ │ │ ├── staticcall_mutex_2.sol │ │ │ │ ├── staticcall_reentrancy_view.sol │ │ │ │ ├── token_trusted_transfer_correct.sol │ │ │ │ ├── token_trusted_transfer_wrong.sol │ │ │ │ └── underflow_only_in_external_call.sol │ │ │ ├── file_level/ │ │ │ │ ├── abi_function_different_source.sol │ │ │ │ ├── abi_function_different_source_2.sol │ │ │ │ ├── constant_different_source.sol │ │ │ │ ├── constant_easy.sol │ │ │ │ ├── constant_string_at_file_level.sol │ │ │ │ ├── constants_at_file_level_referencing.sol │ │ │ │ ├── easy.sol │ │ │ │ ├── enum.sol │ │ │ │ ├── file_level_call_via_module.sol │ │ │ │ ├── free_constant_1.sol │ │ │ │ ├── free_constant_2.sol │ │ │ │ ├── free_function_1.sol │ │ │ │ ├── free_function_2.sol │ │ │ │ ├── free_function_3.sol │ │ │ │ ├── free_function_4.sol │ │ │ │ ├── free_function_5.sol │ │ │ │ ├── free_function_and_constant_1.sol │ │ │ │ ├── free_namesake_contract_function.sol │ │ │ │ ├── free_runtimecode.sol │ │ │ │ ├── import.sol │ │ │ │ ├── libraries_from_free.sol │ │ │ │ ├── module_constants_1.sol │ │ │ │ ├── module_constants_functions_1.sol │ │ │ │ ├── new_operator.sol │ │ │ │ ├── overloads.sol │ │ │ │ ├── recursion.sol │ │ │ │ ├── same_constants_different_files.sol │ │ │ │ └── struct.sol │ │ │ ├── function_selector/ │ │ │ │ ├── function_selector_via_contract_name.sol │ │ │ │ ├── function_types_sig.sol │ │ │ │ ├── homer.sol │ │ │ │ ├── selector.sol │ │ │ │ ├── selector_2.sol │ │ │ │ └── selector_3.sol │ │ │ ├── functions/ │ │ │ │ ├── abi_encode_functions.sol │ │ │ │ ├── constructor_base_basic.sol │ │ │ │ ├── constructor_hierarchy.sol │ │ │ │ ├── constructor_hierarchy_2.sol │ │ │ │ ├── constructor_hierarchy_3.sol │ │ │ │ ├── constructor_hierarchy_4.sol │ │ │ │ ├── constructor_hierarchy_diamond.sol │ │ │ │ ├── constructor_hierarchy_diamond_2.sol │ │ │ │ ├── constructor_hierarchy_diamond_3.sol │ │ │ │ ├── constructor_hierarchy_diamond_empty_middle.sol │ │ │ │ ├── constructor_hierarchy_diamond_empty_middle_empty_base.sol │ │ │ │ ├── constructor_hierarchy_empty_chain.sol │ │ │ │ ├── constructor_hierarchy_empty_middle.sol │ │ │ │ ├── constructor_hierarchy_empty_middle_no_invocation.sol │ │ │ │ ├── constructor_hierarchy_mixed_chain.sol │ │ │ │ ├── constructor_hierarchy_mixed_chain_empty_base.sol │ │ │ │ ├── constructor_hierarchy_mixed_chain_local_vars.sol │ │ │ │ ├── constructor_hierarchy_mixed_chain_with_params.sol │ │ │ │ ├── constructor_hierarchy_mixed_chain_with_params_2.sol │ │ │ │ ├── constructor_hierarchy_modifier.sol │ │ │ │ ├── constructor_hierarchy_same_var.sol │ │ │ │ ├── constructor_simple.sol │ │ │ │ ├── constructor_state_value.sol │ │ │ │ ├── constructor_state_value_inherited.sol │ │ │ │ ├── constructor_state_value_parameter.sol │ │ │ │ ├── constructor_this.sol │ │ │ │ ├── free_function_multiple_contracts.sol │ │ │ │ ├── function_call_does_not_clear_local_vars.sol │ │ │ │ ├── function_call_state_var_init.sol │ │ │ │ ├── function_external_call_should_not_inline_1.sol │ │ │ │ ├── function_external_call_should_not_inline_2.sol │ │ │ │ ├── function_inline_chain.sol │ │ │ │ ├── function_inside_branch_modify_state_var.sol │ │ │ │ ├── function_inside_branch_modify_state_var_2.sol │ │ │ │ ├── function_inside_branch_modify_state_var_3.sol │ │ │ │ ├── functions_attached_1.sol │ │ │ │ ├── functions_attached_1_fail.sol │ │ │ │ ├── functions_external_1.sol │ │ │ │ ├── functions_external_2.sol │ │ │ │ ├── functions_external_3.sol │ │ │ │ ├── functions_external_4.sol │ │ │ │ ├── functions_identifier_nested_tuple_1.sol │ │ │ │ ├── functions_identifier_nested_tuple_2.sol │ │ │ │ ├── functions_identifier_nested_tuple_3.sol │ │ │ │ ├── functions_identity_1.sol │ │ │ │ ├── functions_identity_1_fail.sol │ │ │ │ ├── functions_identity_2.sol │ │ │ │ ├── functions_identity_2_fail.sol │ │ │ │ ├── functions_identity_as_tuple.sol │ │ │ │ ├── functions_identity_as_tuple_fail.sol │ │ │ │ ├── functions_library_1.sol │ │ │ │ ├── functions_library_1_fail.sol │ │ │ │ ├── functions_library_internal.sol │ │ │ │ ├── functions_recursive.sol │ │ │ │ ├── functions_recursive_indirect.sol │ │ │ │ ├── functions_storage_var_1.sol │ │ │ │ ├── functions_storage_var_1_fail.sol │ │ │ │ ├── functions_storage_var_2.sol │ │ │ │ ├── functions_storage_var_2_fail.sol │ │ │ │ ├── functions_trivial_condition_for_only_call.sol │ │ │ │ ├── functions_trivial_condition_if.sol │ │ │ │ ├── functions_trivial_condition_require.sol │ │ │ │ ├── functions_trivial_condition_require_only_call.sol │ │ │ │ ├── functions_trivial_condition_while_only_call.sol │ │ │ │ ├── getters/ │ │ │ │ │ ├── address.sol │ │ │ │ │ ├── array_1.sol │ │ │ │ │ ├── array_2.sol │ │ │ │ │ ├── array_of_structs_1.sol │ │ │ │ │ ├── array_of_structs_2.sol │ │ │ │ │ ├── array_of_structs_3.sol │ │ │ │ │ ├── bytes.sol │ │ │ │ │ ├── contract.sol │ │ │ │ │ ├── double_access.sol │ │ │ │ │ ├── enum.sol │ │ │ │ │ ├── external_getter_1.sol │ │ │ │ │ ├── external_getter_2.sol │ │ │ │ │ ├── external_getter_this_1.sol │ │ │ │ │ ├── external_getter_this_2.sol │ │ │ │ │ ├── fixed_bytes.sol │ │ │ │ │ ├── function.sol │ │ │ │ │ ├── inaccessible_dynamic_type_1.sol │ │ │ │ │ ├── inaccessible_dynamic_type_2.sol │ │ │ │ │ ├── inaccessible_dynamic_type_3.sol │ │ │ │ │ ├── inaccessible_dynamic_type_4.sol │ │ │ │ │ ├── mapping_1.sol │ │ │ │ │ ├── mapping_2.sol │ │ │ │ │ ├── mapping_with_cast.sol │ │ │ │ │ ├── nested_arrays_mappings_1.sol │ │ │ │ │ ├── nested_arrays_mappings_10.sol │ │ │ │ │ ├── nested_arrays_mappings_2.sol │ │ │ │ │ ├── nested_arrays_mappings_3.sol │ │ │ │ │ ├── nested_arrays_mappings_4.sol │ │ │ │ │ ├── nested_arrays_mappings_5.sol │ │ │ │ │ ├── nested_arrays_mappings_6.sol │ │ │ │ │ ├── nested_arrays_mappings_7.sol │ │ │ │ │ ├── nested_arrays_mappings_8.sol │ │ │ │ │ ├── nested_arrays_mappings_9.sol │ │ │ │ │ ├── static_array.sol │ │ │ │ │ ├── string.sol │ │ │ │ │ ├── struct_1.sol │ │ │ │ │ ├── struct_2.sol │ │ │ │ │ ├── struct_3.sol │ │ │ │ │ ├── struct_4.sol │ │ │ │ │ ├── struct_with_reassignment.sol │ │ │ │ │ └── uint.sol │ │ │ │ ├── internal_call_inheritance.sol │ │ │ │ ├── internal_call_state_var_init.sol │ │ │ │ ├── internal_call_state_var_init_2.sol │ │ │ │ ├── internal_call_with_assertion_1.sol │ │ │ │ ├── internal_call_with_assertion_1_fail.sol │ │ │ │ ├── internal_call_with_assertion_inheritance_1.sol │ │ │ │ ├── internal_call_with_assertion_inheritance_1_fail.sol │ │ │ │ ├── internal_multiple_calls_with_assertion_1.sol │ │ │ │ ├── internal_multiple_calls_with_assertion_1_fail.sol │ │ │ │ ├── library_after_contract.sol │ │ │ │ ├── library_constant.sol │ │ │ │ ├── library_constant_2.sol │ │ │ │ ├── library_public_called_as_internal_1.sol │ │ │ │ ├── library_public_called_as_internal_2.sol │ │ │ │ ├── payable_1.sol │ │ │ │ ├── payable_2.sol │ │ │ │ ├── recursive_multi_return.sol │ │ │ │ ├── recursive_multi_return_2.sol │ │ │ │ ├── super_function_assert.sol │ │ │ │ ├── this_external_call.sol │ │ │ │ ├── this_external_call_2.sol │ │ │ │ ├── this_external_call_return.sol │ │ │ │ ├── this_external_call_sender.sol │ │ │ │ ├── this_external_call_tx_origin.sol │ │ │ │ ├── this_state.sol │ │ │ │ ├── virtual_function_assert.sol │ │ │ │ └── virtual_function_called_by_constructor.sol │ │ │ ├── imports/ │ │ │ │ ├── ExtCall.sol │ │ │ │ ├── duplicated_errors_1.sol │ │ │ │ ├── import_as_module_1.sol │ │ │ │ ├── import_as_module_2.sol │ │ │ │ ├── import_base.sol │ │ │ │ ├── import_free_functions.sol │ │ │ │ ├── import_library.sol │ │ │ │ ├── import_library_2.sol │ │ │ │ ├── imported_fail_1.sol │ │ │ │ ├── imported_fail_2.sol │ │ │ │ ├── imported_fail_3.sol │ │ │ │ ├── private_vars.sol │ │ │ │ ├── simple.sol │ │ │ │ ├── target_in_imported_contract_analyzed_when_called_from_selection_with_trusted_calls.sol │ │ │ │ └── target_in_imported_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol │ │ │ ├── inheritance/ │ │ │ │ ├── base_contract_assertion_fail_1.sol │ │ │ │ ├── base_contract_assertion_fail_2.sol │ │ │ │ ├── base_contract_assertion_fail_3.sol │ │ │ │ ├── base_contract_assertion_fail_4.sol │ │ │ │ ├── base_contract_assertion_fail_5.sol │ │ │ │ ├── base_contract_assertion_fail_6.sol │ │ │ │ ├── base_contract_assertion_fail_7.sol │ │ │ │ ├── base_contract_assertion_fail_8.sol │ │ │ │ ├── base_contract_assertion_fail_9.sol │ │ │ │ ├── constructor_hierarchy_base_calls_inheritance_specifier_1.sol │ │ │ │ ├── constructor_hierarchy_base_calls_inheritance_specifier_2.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_1.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_2.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_3.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_4.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_5.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_6.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_7.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_8.sol │ │ │ │ ├── constructor_hierarchy_base_calls_with_side_effects_9.sol │ │ │ │ ├── constructor_hierarchy_mixed_chain_with_params.sol │ │ │ │ ├── constructor_state_variable_init.sol │ │ │ │ ├── constructor_state_variable_init_asserts.sol │ │ │ │ ├── constructor_state_variable_init_base.sol │ │ │ │ ├── constructor_state_variable_init_chain.sol │ │ │ │ ├── constructor_state_variable_init_chain_alternate.sol │ │ │ │ ├── constructor_state_variable_init_chain_run_all.sol │ │ │ │ ├── constructor_state_variable_init_chain_run_all_2.sol │ │ │ │ ├── constructor_state_variable_init_chain_tree.sol │ │ │ │ ├── constructor_state_variable_init_diamond.sol │ │ │ │ ├── constructor_state_variable_init_diamond_middle.sol │ │ │ │ ├── constructor_state_variable_init_function_call.sol │ │ │ │ ├── constructor_uses_function_base.sol │ │ │ │ ├── diamond_super_1.sol │ │ │ │ ├── diamond_super_2.sol │ │ │ │ ├── diamond_super_3.sol │ │ │ │ ├── fallback.sol │ │ │ │ ├── fallback_receive.sol │ │ │ │ ├── functions_1.sol │ │ │ │ ├── functions_2.sol │ │ │ │ ├── functions_3.sol │ │ │ │ ├── implicit_constructor_hierarchy.sol │ │ │ │ ├── implicit_only_constructor_hierarchy.sol │ │ │ │ ├── overridden_function_static_call_parent.sol │ │ │ │ ├── receive.sol │ │ │ │ ├── receive_fallback.sol │ │ │ │ ├── state_variables.sol │ │ │ │ ├── state_variables_2.sol │ │ │ │ └── state_variables_3.sol │ │ │ ├── inline_assembly/ │ │ │ │ ├── assembly_1.sol │ │ │ │ ├── assembly_2.sol │ │ │ │ ├── assembly_3.sol │ │ │ │ ├── assembly_4.sol │ │ │ │ ├── assembly_5.sol │ │ │ │ ├── assembly_6.sol │ │ │ │ ├── assembly_local_storage_access_inside_function.sol │ │ │ │ ├── assembly_local_storage_pointer.sol │ │ │ │ ├── assembly_memory_write.sol │ │ │ │ ├── empty.sol │ │ │ │ └── local_var.sol │ │ │ ├── invariants/ │ │ │ │ ├── aon_blog_post.sol │ │ │ │ ├── array_access.sol │ │ │ │ ├── array_access_2.sol │ │ │ │ ├── loop_basic.sol │ │ │ │ ├── loop_basic_for.sol │ │ │ │ ├── loop_nested.sol │ │ │ │ ├── loop_nested_for.sol │ │ │ │ ├── solver_response_involves_bv2int.sol │ │ │ │ ├── state_machine_1.sol │ │ │ │ ├── state_machine_1_fail.sol │ │ │ │ ├── struct_access.sol │ │ │ │ └── unary_minus_formatting.sol │ │ │ ├── loops/ │ │ │ │ ├── do_while_1.sol │ │ │ │ ├── do_while_1_fail.sol │ │ │ │ ├── do_while_bmc_iterations_1.sol │ │ │ │ ├── do_while_bmc_iterations_2.sol │ │ │ │ ├── do_while_bmc_iterations_3.sol │ │ │ │ ├── do_while_bmc_iterations_4.sol │ │ │ │ ├── do_while_bmc_iterations_5.sol │ │ │ │ ├── do_while_bmc_iterations_6.sol │ │ │ │ ├── do_while_bmc_iterations_7.sol │ │ │ │ ├── do_while_bmc_iterations_assertion_fails_1.sol │ │ │ │ ├── do_while_bmc_iterations_assertion_fails_2.sol │ │ │ │ ├── do_while_bmc_iterations_assertion_fails_3.sol │ │ │ │ ├── do_while_bmc_iterations_break_1.sol │ │ │ │ ├── do_while_bmc_iterations_break_2.sol │ │ │ │ ├── do_while_bmc_iterations_break_3.sol │ │ │ │ ├── do_while_bmc_iterations_break_4.sol │ │ │ │ ├── do_while_bmc_iterations_break_5.sol │ │ │ │ ├── do_while_bmc_iterations_break_6.sol │ │ │ │ ├── do_while_bmc_iterations_break_7.sol │ │ │ │ ├── do_while_bmc_iterations_break_8.sol │ │ │ │ ├── do_while_bmc_iterations_break_continue_1.sol │ │ │ │ ├── do_while_bmc_iterations_break_continue_2.sol │ │ │ │ ├── do_while_bmc_iterations_continue_1.sol │ │ │ │ ├── do_while_bmc_iterations_continue_2.sol │ │ │ │ ├── do_while_bmc_iterations_continue_3.sol │ │ │ │ ├── do_while_bmc_iterations_continue_4.sol │ │ │ │ ├── do_while_bmc_iterations_nested.sol │ │ │ │ ├── do_while_bmc_iterations_nested_break.sol │ │ │ │ ├── do_while_bmc_iterations_nested_continue.sol │ │ │ │ ├── do_while_bmc_iterations_semantics_1.sol │ │ │ │ ├── do_while_bmc_iterations_semantics_2.sol │ │ │ │ ├── do_while_bmc_iterations_semantics_3.sol │ │ │ │ ├── do_while_bmc_iterations_semantics_4.sol │ │ │ │ ├── do_while_bmc_iterations_shallow_unroll.sol │ │ │ │ ├── do_while_break.sol │ │ │ │ ├── do_while_break_2.sol │ │ │ │ ├── do_while_break_2_fail.sol │ │ │ │ ├── do_while_break_fail.sol │ │ │ │ ├── do_while_continue.sol │ │ │ │ ├── for_1_break.sol │ │ │ │ ├── for_1_break_fail.sol │ │ │ │ ├── for_1_continue.sol │ │ │ │ ├── for_1_continue_fail.sol │ │ │ │ ├── for_1_false_positive.sol │ │ │ │ ├── for_break_direct.sol │ │ │ │ ├── for_loop_1.sol │ │ │ │ ├── for_loop_2.sol │ │ │ │ ├── for_loop_3.sol │ │ │ │ ├── for_loop_4.sol │ │ │ │ ├── for_loop_5.sol │ │ │ │ ├── for_loop_6.sol │ │ │ │ ├── for_loop_array_assignment_memory_memory.sol │ │ │ │ ├── for_loop_array_assignment_memory_storage.sol │ │ │ │ ├── for_loop_array_assignment_storage_memory.sol │ │ │ │ ├── for_loop_array_assignment_storage_storage.sol │ │ │ │ ├── for_loop_bmc_iterations_1.sol │ │ │ │ ├── for_loop_bmc_iterations_10.sol │ │ │ │ ├── for_loop_bmc_iterations_2.sol │ │ │ │ ├── for_loop_bmc_iterations_3.sol │ │ │ │ ├── for_loop_bmc_iterations_4.sol │ │ │ │ ├── for_loop_bmc_iterations_5.sol │ │ │ │ ├── for_loop_bmc_iterations_6.sol │ │ │ │ ├── for_loop_bmc_iterations_7.sol │ │ │ │ ├── for_loop_bmc_iterations_8.sol │ │ │ │ ├── for_loop_bmc_iterations_9.sol │ │ │ │ ├── for_loop_bmc_iterations_assertion_fails_1.sol │ │ │ │ ├── for_loop_bmc_iterations_assertion_fails_2.sol │ │ │ │ ├── for_loop_bmc_iterations_assertion_fails_3.sol │ │ │ │ ├── for_loop_bmc_iterations_break_1.sol │ │ │ │ ├── for_loop_bmc_iterations_break_2.sol │ │ │ │ ├── for_loop_bmc_iterations_break_3.sol │ │ │ │ ├── for_loop_bmc_iterations_break_4.sol │ │ │ │ ├── for_loop_bmc_iterations_break_5.sol │ │ │ │ ├── for_loop_bmc_iterations_break_6.sol │ │ │ │ ├── for_loop_bmc_iterations_break_7.sol │ │ │ │ ├── for_loop_bmc_iterations_break_8.sol │ │ │ │ ├── for_loop_bmc_iterations_break_9.sol │ │ │ │ ├── for_loop_bmc_iterations_break_continue_1.sol │ │ │ │ ├── for_loop_bmc_iterations_break_continue_2.sol │ │ │ │ ├── for_loop_bmc_iterations_break_continue_3.sol │ │ │ │ ├── for_loop_bmc_iterations_continue_1.sol │ │ │ │ ├── for_loop_bmc_iterations_continue_2.sol │ │ │ │ ├── for_loop_bmc_iterations_continue_3.sol │ │ │ │ ├── for_loop_bmc_iterations_continue_4.sol │ │ │ │ ├── for_loop_bmc_iterations_continue_5.sol │ │ │ │ ├── for_loop_bmc_iterations_false_positive.sol │ │ │ │ ├── for_loop_bmc_iterations_nested.sol │ │ │ │ ├── for_loop_bmc_iterations_nested_break.sol │ │ │ │ ├── for_loop_bmc_iterations_nested_continue.sol │ │ │ │ ├── for_loop_bmc_iterations_semantics_1.sol │ │ │ │ ├── for_loop_bmc_iterations_semantics_2.sol │ │ │ │ ├── for_loop_bmc_iterations_semantics_3.sol │ │ │ │ ├── for_loop_bmc_iterations_shallow_unroll.sol │ │ │ │ ├── for_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol │ │ │ │ ├── for_loop_trivial_condition_1.sol │ │ │ │ ├── for_loop_trivial_condition_2.sol │ │ │ │ ├── for_loop_trivial_condition_3.sol │ │ │ │ ├── while_1.sol │ │ │ │ ├── while_1_break.sol │ │ │ │ ├── while_1_break_fail.sol │ │ │ │ ├── while_1_continue.sol │ │ │ │ ├── while_1_continue_fail.sol │ │ │ │ ├── while_1_fail.sol │ │ │ │ ├── while_1_infinite.sol │ │ │ │ ├── while_2.sol │ │ │ │ ├── while_2_break.sol │ │ │ │ ├── while_2_break_fail.sol │ │ │ │ ├── while_2_fail.sol │ │ │ │ ├── while_bmc_iterations_1.sol │ │ │ │ ├── while_bmc_iterations_2.sol │ │ │ │ ├── while_bmc_iterations_3.sol │ │ │ │ ├── while_bmc_iterations_4.sol │ │ │ │ ├── while_bmc_iterations_5.sol │ │ │ │ ├── while_bmc_iterations_6.sol │ │ │ │ ├── while_bmc_iterations_7.sol │ │ │ │ ├── while_bmc_iterations_8.sol │ │ │ │ ├── while_bmc_iterations_assertion_fails_1.sol │ │ │ │ ├── while_bmc_iterations_assertion_fails_2.sol │ │ │ │ ├── while_bmc_iterations_assertion_fails_3.sol │ │ │ │ ├── while_bmc_iterations_break_1.sol │ │ │ │ ├── while_bmc_iterations_break_2.sol │ │ │ │ ├── while_bmc_iterations_break_3.sol │ │ │ │ ├── while_bmc_iterations_break_4.sol │ │ │ │ ├── while_bmc_iterations_break_5.sol │ │ │ │ ├── while_bmc_iterations_break_6.sol │ │ │ │ ├── while_bmc_iterations_break_7.sol │ │ │ │ ├── while_bmc_iterations_break_8.sol │ │ │ │ ├── while_bmc_iterations_break_9.sol │ │ │ │ ├── while_bmc_iterations_break_continue_1.sol │ │ │ │ ├── while_bmc_iterations_break_continue_2.sol │ │ │ │ ├── while_bmc_iterations_continue_1.sol │ │ │ │ ├── while_bmc_iterations_continue_2.sol │ │ │ │ ├── while_bmc_iterations_nested.sol │ │ │ │ ├── while_bmc_iterations_nested_break.sol │ │ │ │ ├── while_bmc_iterations_nested_continue.sol │ │ │ │ ├── while_bmc_iterations_semantics_1.sol │ │ │ │ ├── while_bmc_iterations_semantics_2.sol │ │ │ │ ├── while_bmc_iterations_semantics_3.sol │ │ │ │ ├── while_bmc_iterations_shallow_unroll.sol │ │ │ │ ├── while_break_direct.sol │ │ │ │ ├── while_loop_array_assignment_memory_memory.sol │ │ │ │ ├── while_loop_array_assignment_memory_storage.sol │ │ │ │ ├── while_loop_array_assignment_storage_storage.sol │ │ │ │ ├── while_loop_condition_constant_true_in_first_iteration_and_constant_false_in_second.sol │ │ │ │ ├── while_loop_simple_1.sol │ │ │ │ ├── while_loop_simple_2.sol │ │ │ │ ├── while_loop_simple_3.sol │ │ │ │ ├── while_loop_simple_4.sol │ │ │ │ ├── while_loop_simple_5.sol │ │ │ │ ├── while_nested_break.sol │ │ │ │ ├── while_nested_break_fail.sol │ │ │ │ ├── while_nested_continue.sol │ │ │ │ └── while_nested_continue_fail.sol │ │ │ ├── math/ │ │ │ │ ├── addmod_1.sol │ │ │ │ ├── addmod_mulmod.sol │ │ │ │ ├── addmod_mulmod_zero.sol │ │ │ │ ├── addmulmod.sol │ │ │ │ └── mulmod_1.sol │ │ │ ├── modifiers/ │ │ │ │ ├── modifier_abstract.sol │ │ │ │ ├── modifier_assignment_outside_branch.sol │ │ │ │ ├── modifier_code_after_placeholder.sol │ │ │ │ ├── modifier_control_flow.sol │ │ │ │ ├── modifier_inline_function_inside_branch.sol │ │ │ │ ├── modifier_inside_branch.sol │ │ │ │ ├── modifier_inside_branch_assignment.sol │ │ │ │ ├── modifier_inside_branch_assignment_branch.sol │ │ │ │ ├── modifier_inside_branch_assignment_multi_branches.sol │ │ │ │ ├── modifier_multi.sol │ │ │ │ ├── modifier_multi_functions.sol │ │ │ │ ├── modifier_multi_functions_recursive.sol │ │ │ │ ├── modifier_multi_parameters.sol │ │ │ │ ├── modifier_overflow.sol │ │ │ │ ├── modifier_overriding_1.sol │ │ │ │ ├── modifier_overriding_2.sol │ │ │ │ ├── modifier_overriding_3.sol │ │ │ │ ├── modifier_overriding_4.sol │ │ │ │ ├── modifier_parameter_copy.sol │ │ │ │ ├── modifier_parameters.sol │ │ │ │ ├── modifier_return.sol │ │ │ │ ├── modifier_same_local_variables.sol │ │ │ │ ├── modifier_simple.sol │ │ │ │ ├── modifier_two_invocations.sol │ │ │ │ ├── modifier_two_invocations_2.sol │ │ │ │ ├── modifier_two_placeholders.sol │ │ │ │ ├── modifier_virtual_static_call_1.sol │ │ │ │ └── modifier_virtual_static_call_2.sol │ │ │ ├── natspec/ │ │ │ │ ├── abstract_free_function_1.sol │ │ │ │ ├── abstract_function_nondet_1.sol │ │ │ │ ├── abstract_function_nondet_pow_no_abstraction.sol │ │ │ │ ├── abstract_function_nondet_pow_with_abstraction.sol │ │ │ │ ├── natspec_smtchecker_empty.sol │ │ │ │ ├── natspec_smtchecker_error_1.sol │ │ │ │ ├── natspec_smtchecker_multi_errors_1.sol │ │ │ │ ├── safe_assert_false_positive.sol │ │ │ │ ├── safe_assert_false_positive_pure.sol │ │ │ │ └── unsafe_assert_remains_unsafe.sol │ │ │ ├── operators/ │ │ │ │ ├── assignment_chain_tuple_contract_1.sol │ │ │ │ ├── assignment_chain_tuple_contract_2.sol │ │ │ │ ├── assignment_chain_tuple_contract_3.sol │ │ │ │ ├── assignment_contract_member_variable.sol │ │ │ │ ├── assignment_contract_member_variable_array.sol │ │ │ │ ├── assignment_contract_member_variable_array_2.sol │ │ │ │ ├── assignment_contract_member_variable_array_3.sol │ │ │ │ ├── assignment_module_contract_member_variable.sol │ │ │ │ ├── bitwise_and_array.sol │ │ │ │ ├── bitwise_and_fixed_bytes.sol │ │ │ │ ├── bitwise_and_int.sol │ │ │ │ ├── bitwise_and_rational.sol │ │ │ │ ├── bitwise_and_uint.sol │ │ │ │ ├── bitwise_combo.sol │ │ │ │ ├── bitwise_not_fixed_bytes.sol │ │ │ │ ├── bitwise_not_int.sol │ │ │ │ ├── bitwise_not_uint.sol │ │ │ │ ├── bitwise_operators_do_not_throw_exceptions.sol │ │ │ │ ├── bitwise_or_fixed_bytes.sol │ │ │ │ ├── bitwise_or_int.sol │ │ │ │ ├── bitwise_or_uint.sol │ │ │ │ ├── bitwise_rational_1.sol │ │ │ │ ├── bitwise_rational_2.sol │ │ │ │ ├── bitwise_xor_fixed_bytes.sol │ │ │ │ ├── bitwise_xor_int.sol │ │ │ │ ├── bitwise_xor_uint.sol │ │ │ │ ├── bytes_new.sol │ │ │ │ ├── compound_add.sol │ │ │ │ ├── compound_add_array_index.sol │ │ │ │ ├── compound_add_chain.sol │ │ │ │ ├── compound_add_mapping.sol │ │ │ │ ├── compound_assignment_division_1.sol │ │ │ │ ├── compound_assignment_division_2.sol │ │ │ │ ├── compound_assignment_division_3.sol │ │ │ │ ├── compound_assignment_right_shift.sol │ │ │ │ ├── compound_bitwise_and_fixed_bytes.sol │ │ │ │ ├── compound_bitwise_and_int.sol │ │ │ │ ├── compound_bitwise_and_uint.sol │ │ │ │ ├── compound_bitwise_or_fixed_bytes.sol │ │ │ │ ├── compound_bitwise_or_int.sol │ │ │ │ ├── compound_bitwise_or_int_1.sol │ │ │ │ ├── compound_bitwise_or_uint.sol │ │ │ │ ├── compound_bitwise_or_uint_1.sol │ │ │ │ ├── compound_bitwise_or_uint_2.sol │ │ │ │ ├── compound_bitwise_or_uint_3.sol │ │ │ │ ├── compound_bitwise_string_literal.sol │ │ │ │ ├── compound_bitwise_string_literal_2.sol │ │ │ │ ├── compound_bitwise_string_literal_3.sol │ │ │ │ ├── compound_bitwise_xor_fixed_bytes.sol │ │ │ │ ├── compound_bitwise_xor_int.sol │ │ │ │ ├── compound_bitwise_xor_uint.sol │ │ │ │ ├── compound_mul.sol │ │ │ │ ├── compound_mul_array_index.sol │ │ │ │ ├── compound_mul_mapping.sol │ │ │ │ ├── compound_shl_1.sol │ │ │ │ ├── compound_shr_1.sol │ │ │ │ ├── compound_sub.sol │ │ │ │ ├── compound_sub_array_index.sol │ │ │ │ ├── compound_sub_mapping.sol │ │ │ │ ├── conditional_assignment_1.sol │ │ │ │ ├── conditional_assignment_2.sol │ │ │ │ ├── conditional_assignment_3.sol │ │ │ │ ├── conditional_assignment_4.sol │ │ │ │ ├── conditional_assignment_5.sol │ │ │ │ ├── conditional_assignment_6.sol │ │ │ │ ├── conditional_assignment_always_false.sol │ │ │ │ ├── conditional_assignment_always_true.sol │ │ │ │ ├── conditional_assignment_function_1.sol │ │ │ │ ├── conditional_assignment_function_2.sol │ │ │ │ ├── conditional_assignment_nested_always_true.sol │ │ │ │ ├── conditional_assignment_nested_unsafe.sol │ │ │ │ ├── conditional_assignment_statevar_1.sol │ │ │ │ ├── const_exp_1.sol │ │ │ │ ├── constant_evaluation_add.sol │ │ │ │ ├── constant_evaluation_bitwise_not.sol │ │ │ │ ├── constant_evaluation_sub.sol │ │ │ │ ├── constant_propagation_1.sol │ │ │ │ ├── constant_propagation_2.sol │ │ │ │ ├── delete_array.sol │ │ │ │ ├── delete_array_2d.sol │ │ │ │ ├── delete_array_index.sol │ │ │ │ ├── delete_array_index_2d.sol │ │ │ │ ├── delete_array_push.sol │ │ │ │ ├── delete_function.sol │ │ │ │ ├── delete_function_type_1.sol │ │ │ │ ├── delete_function_type_2.sol │ │ │ │ ├── delete_function_type_3.sol │ │ │ │ ├── delete_multid_array.sol │ │ │ │ ├── delete_struct.sol │ │ │ │ ├── delete_tuple.sol │ │ │ │ ├── div_zero.sol │ │ │ │ ├── division_1.sol │ │ │ │ ├── division_2.sol │ │ │ │ ├── division_3.sol │ │ │ │ ├── division_4.sol │ │ │ │ ├── division_5.sol │ │ │ │ ├── division_6.sol │ │ │ │ ├── division_7.sol │ │ │ │ ├── division_truncates_correctly_1.sol │ │ │ │ ├── division_truncates_correctly_2.sol │ │ │ │ ├── division_truncates_correctly_3.sol │ │ │ │ ├── division_truncates_correctly_4.sol │ │ │ │ ├── division_truncates_correctly_5.sol │ │ │ │ ├── exp.sol │ │ │ │ ├── fixed_point_add.sol │ │ │ │ ├── fixed_point_compound_add.sol │ │ │ │ ├── function_call_named_arguments.sol │ │ │ │ ├── index_access_for_bytes.sol │ │ │ │ ├── index_access_for_bytesNN.sol │ │ │ │ ├── index_access_for_string.sol │ │ │ │ ├── index_access_side_effect.sol │ │ │ │ ├── integer_new.sol │ │ │ │ ├── mod.sol │ │ │ │ ├── mod_even.sol │ │ │ │ ├── mod_n.sol │ │ │ │ ├── mod_n_uint16.sol │ │ │ │ ├── mod_signed.sol │ │ │ │ ├── named_arguments_in_any_order.sol │ │ │ │ ├── named_arguments_overload_in_any_order.sol │ │ │ │ ├── shifts/ │ │ │ │ │ ├── compound_shift_left.sol │ │ │ │ │ ├── compound_shift_right.sol │ │ │ │ │ ├── shift_cex.sol │ │ │ │ │ ├── shift_cleanup.sol │ │ │ │ │ ├── shift_left.sol │ │ │ │ │ ├── shift_left_larger_type.sol │ │ │ │ │ ├── shift_left_uint32.sol │ │ │ │ │ ├── shift_left_uint8.sol │ │ │ │ │ ├── shift_overflow.sol │ │ │ │ │ ├── shift_right.sol │ │ │ │ │ ├── shift_right_negative_literal.sol │ │ │ │ │ ├── shift_right_negative_lvalue.sol │ │ │ │ │ ├── shift_right_negative_lvalue_int16.sol │ │ │ │ │ ├── shift_right_negative_lvalue_int32.sol │ │ │ │ │ ├── shift_right_negative_lvalue_int8.sol │ │ │ │ │ ├── shift_right_uint32.sol │ │ │ │ │ ├── shift_right_uint8.sol │ │ │ │ │ ├── shift_underflow_negative_rvalue.sol │ │ │ │ │ └── shr_unused.sol │ │ │ │ ├── slice.sol │ │ │ │ ├── slice_access.sol │ │ │ │ ├── slice_bytes.sol │ │ │ │ ├── slice_default_end.sol │ │ │ │ ├── slice_default_start.sol │ │ │ │ ├── slices_1.sol │ │ │ │ ├── slices_2.sol │ │ │ │ ├── slices_3.sol │ │ │ │ ├── ternary_operator_1.sol │ │ │ │ ├── ternary_operator_2.sol │ │ │ │ ├── ternary_operator_3.sol │ │ │ │ ├── ternary_operator_double_function_call.sol │ │ │ │ ├── ternary_operator_external_code_1.sol │ │ │ │ ├── ternary_operator_nested_1.sol │ │ │ │ ├── ternary_operator_nested_2.sol │ │ │ │ ├── ternary_operator_nested_3.sol │ │ │ │ ├── ternary_operator_nested_4.sol │ │ │ │ ├── ternary_operator_with_functions.sol │ │ │ │ ├── ternary_operator_with_tuple.sol │ │ │ │ ├── tuple_rationals_conditional.sol │ │ │ │ ├── unary_add.sol │ │ │ │ ├── unary_add_array.sol │ │ │ │ ├── unary_add_array_push_1.sol │ │ │ │ ├── unary_add_array_push_2.sol │ │ │ │ ├── unary_add_mapping.sol │ │ │ │ ├── unary_add_minus_overflow_detected.sol │ │ │ │ ├── unary_add_overflows_correctly.sol │ │ │ │ ├── unary_add_overflows_correctly_struct.sol │ │ │ │ ├── unary_minus_bmc.sol │ │ │ │ ├── unary_minus_chc.sol │ │ │ │ ├── unary_operators_tuple_1.sol │ │ │ │ ├── unary_operators_tuple_2.sol │ │ │ │ ├── unary_operators_tuple_3.sol │ │ │ │ ├── unary_sub.sol │ │ │ │ ├── unary_sub_array.sol │ │ │ │ ├── unary_sub_mapping.sol │ │ │ │ └── userDefined/ │ │ │ │ ├── user_defined_division_same_as_builtin.sol │ │ │ │ ├── user_defined_division_with_safe_division_by_zero.sol │ │ │ │ ├── user_defined_operations_on_constants.sol │ │ │ │ ├── user_defined_operations_on_constants_fail.sol │ │ │ │ ├── user_defined_operator_matches_equivalent_function_call.sol │ │ │ │ └── user_defined_overflow.sol │ │ │ ├── options/ │ │ │ │ ├── engine_none.sol │ │ │ │ └── pragma.sol │ │ │ ├── out_of_bounds/ │ │ │ │ ├── array_1.sol │ │ │ │ ├── array_2.sol │ │ │ │ ├── array_2d_1.sol │ │ │ │ ├── array_2d_2.sol │ │ │ │ ├── array_2d_3.sol │ │ │ │ ├── array_2d_4.sol │ │ │ │ ├── array_3.sol │ │ │ │ ├── array_4.sol │ │ │ │ ├── fixed_bytes_1.sol │ │ │ │ ├── fixed_bytes_2.sol │ │ │ │ ├── fixed_bytes_3.sol │ │ │ │ └── fixed_bytes_4.sol │ │ │ ├── overflow/ │ │ │ │ ├── overflow_and_underflow_bmc.sol │ │ │ │ ├── overflow_and_underflow_bmc_show_proved.sol │ │ │ │ ├── overflow_and_underflow_chc.sol │ │ │ │ ├── overflow_constant_bound.sol │ │ │ │ ├── overflow_mul.sol │ │ │ │ ├── overflow_mul_cex_with_array.sol │ │ │ │ ├── overflow_mul_signed.sol │ │ │ │ ├── overflow_sum.sol │ │ │ │ ├── overflow_sum_signed.sol │ │ │ │ ├── safe_sub_1.sol │ │ │ │ ├── signed_div_overflow.sol │ │ │ │ ├── signed_guard_sub_overflow.sol │ │ │ │ ├── signed_guard_sum_overflow.sol │ │ │ │ ├── signed_mod_overflow.sol │ │ │ │ ├── signed_mul_overflow.sol │ │ │ │ ├── signed_sub_overflow.sol │ │ │ │ ├── signed_sum_overflow.sol │ │ │ │ ├── simple_overflow.sol │ │ │ │ ├── underflow_sub.sol │ │ │ │ ├── underflow_sub_signed.sol │ │ │ │ ├── unsigned_div_overflow.sol │ │ │ │ ├── unsigned_guard_sub_overflow.sol │ │ │ │ ├── unsigned_guard_sum_overflow.sol │ │ │ │ ├── unsigned_mod_overflow.sol │ │ │ │ ├── unsigned_mul_overflow.sol │ │ │ │ ├── unsigned_sub_overflow.sol │ │ │ │ └── unsigned_sum_overflow.sol │ │ │ ├── simple/ │ │ │ │ ├── cex_smoke_test.sol │ │ │ │ ├── smoke_test.sol │ │ │ │ └── static_array.sol │ │ │ ├── special/ │ │ │ │ ├── abi_decode_memory_v2.sol │ │ │ │ ├── abi_decode_memory_v2_value_types.sol │ │ │ │ ├── abi_decode_simple.sol │ │ │ │ ├── abi_encode_slice.sol │ │ │ │ ├── blobhash_beyond_limit.sol │ │ │ │ ├── block_vars_bmc_internal.sol │ │ │ │ ├── block_vars_chc_internal.sol │ │ │ │ ├── blockhash.sol │ │ │ │ ├── chainid.sol │ │ │ │ ├── ether_units.sol │ │ │ │ ├── event.sol │ │ │ │ ├── gasleft.sol │ │ │ │ ├── many.sol │ │ │ │ ├── many_internal.sol │ │ │ │ ├── msg_data.sol │ │ │ │ ├── msg_parens_1.sol │ │ │ │ ├── msg_sender_1.sol │ │ │ │ ├── msg_sender_2.sol │ │ │ │ ├── msg_sender_3.sol │ │ │ │ ├── msg_sender_fail_1.sol │ │ │ │ ├── msg_sender_range.sol │ │ │ │ ├── msg_sig.sol │ │ │ │ ├── msg_value_1.sol │ │ │ │ ├── msg_value_2.sol │ │ │ │ ├── msg_value_3.sol │ │ │ │ ├── msg_value_4.sol │ │ │ │ ├── msg_value_inheritance_1.sol │ │ │ │ ├── msg_value_inheritance_2.sol │ │ │ │ ├── msg_value_inheritance_3.sol │ │ │ │ ├── msg_vars_bmc_internal.sol │ │ │ │ ├── msg_vars_chc_internal.sol │ │ │ │ ├── prevrandao.sol │ │ │ │ ├── range_check.sol │ │ │ │ ├── shadowing_1.sol │ │ │ │ ├── this.sol │ │ │ │ ├── this_state.sol │ │ │ │ ├── time_units.sol │ │ │ │ ├── timestamp.sol │ │ │ │ ├── timestamp_2.sol │ │ │ │ ├── tx_data_gasleft_changes.sol │ │ │ │ ├── tx_data_immutable.sol │ │ │ │ ├── tx_data_immutable_fail.sol │ │ │ │ ├── tx_vars_bmc_internal.sol │ │ │ │ ├── tx_vars_chc_internal.sol │ │ │ │ ├── tx_vars_reentrancy_1.sol │ │ │ │ └── tx_vars_reentrancy_2.sol │ │ │ ├── try_catch/ │ │ │ │ ├── try_1.sol │ │ │ │ ├── try_2.sol │ │ │ │ ├── try_3.sol │ │ │ │ ├── try_4.sol │ │ │ │ ├── try_5.sol │ │ │ │ ├── try_call_in_catch_1.sol │ │ │ │ ├── try_call_in_catch_2.sol │ │ │ │ ├── try_inside_if.sol │ │ │ │ ├── try_inside_while.sol │ │ │ │ ├── try_multiple_catch_clauses.sol │ │ │ │ ├── try_multiple_catch_clauses_2.sol │ │ │ │ ├── try_multiple_returned_values.sol │ │ │ │ ├── try_multiple_returned_values_with_tuple.sol │ │ │ │ ├── try_nested_1.sol │ │ │ │ ├── try_nested_2.sol │ │ │ │ ├── try_nested_3.sol │ │ │ │ ├── try_new.sol │ │ │ │ ├── try_public_var.sol │ │ │ │ ├── try_public_var_mapping.sol │ │ │ │ ├── try_string_literal_to_bytes_array.sol │ │ │ │ └── try_string_literal_to_fixed_bytes.sol │ │ │ ├── typecast/ │ │ │ │ ├── address_literal.sol │ │ │ │ ├── bytes_to_fixed_bytes_1.sol │ │ │ │ ├── bytes_to_fixed_bytes_1_fail.sol │ │ │ │ ├── cast_address_1.sol │ │ │ │ ├── cast_different_size_1.sol │ │ │ │ ├── cast_larger_1.sol │ │ │ │ ├── cast_larger_2.sol │ │ │ │ ├── cast_larger_2_fail.sol │ │ │ │ ├── cast_larger_3.sol │ │ │ │ ├── cast_smaller_1.sol │ │ │ │ ├── cast_smaller_2.sol │ │ │ │ ├── cast_smaller_3.sol │ │ │ │ ├── downcast.sol │ │ │ │ ├── enum_from_uint.sol │ │ │ │ ├── enum_to_uint_max_value.sol │ │ │ │ ├── fixed_bytes_array_from_strig_inline_array.sol │ │ │ │ ├── function_type_to_function_type_external.sol │ │ │ │ ├── function_type_to_function_type_internal.sol │ │ │ │ ├── implicit_cast_string_literal_byte.sol │ │ │ │ ├── number_literal.sol │ │ │ │ ├── same_size.sol │ │ │ │ ├── slice_to_bytes.sol │ │ │ │ ├── slice_to_fixed_bytes_1.sol │ │ │ │ ├── string_literal_to_dynamic_bytes.sol │ │ │ │ ├── string_literal_to_fixed_bytes_constant_initialization_1.sol │ │ │ │ ├── string_literal_to_fixed_bytes_constant_initialization_2.sol │ │ │ │ ├── string_literal_to_fixed_bytes_constructor_for_deployment.sol │ │ │ │ ├── string_literal_to_fixed_bytes_explicit.sol │ │ │ │ ├── string_literal_to_fixed_bytes_function_call.sol │ │ │ │ ├── string_literal_to_fixed_bytes_modifier.sol │ │ │ │ ├── string_literal_to_fixed_bytes_return.sol │ │ │ │ ├── string_literal_to_fixed_bytes_return_multi.sol │ │ │ │ ├── string_literal_to_fixed_bytes_upcast.sol │ │ │ │ ├── string_to_bytes_push_1.sol │ │ │ │ ├── string_to_bytes_push_2.sol │ │ │ │ └── upcast.sol │ │ │ ├── types/ │ │ │ │ ├── abi_type_type_1.sol │ │ │ │ ├── abi_type_type_2.sol │ │ │ │ ├── address_balance.sol │ │ │ │ ├── address_call.sol │ │ │ │ ├── address_delegatecall.sol │ │ │ │ ├── address_staticcall.sol │ │ │ │ ├── address_transfer.sol │ │ │ │ ├── address_transfer_2.sol │ │ │ │ ├── address_transfer_3.sol │ │ │ │ ├── address_transfer_insufficient.sol │ │ │ │ ├── array_aliasing_memory_1.sol │ │ │ │ ├── array_aliasing_memory_2.sol │ │ │ │ ├── array_aliasing_memory_3.sol │ │ │ │ ├── array_aliasing_storage_1.sol │ │ │ │ ├── array_aliasing_storage_2.sol │ │ │ │ ├── array_aliasing_storage_3.sol │ │ │ │ ├── array_aliasing_storage_4.sol │ │ │ │ ├── array_aliasing_storage_5.sol │ │ │ │ ├── array_branch_1d.sol │ │ │ │ ├── array_branch_2d.sol │ │ │ │ ├── array_branch_3d.sol │ │ │ │ ├── array_branches_1d.sol │ │ │ │ ├── array_branches_2d.sol │ │ │ │ ├── array_branches_3d.sol │ │ │ │ ├── array_dynamic_1.sol │ │ │ │ ├── array_dynamic_1_fail.sol │ │ │ │ ├── array_dynamic_2.sol │ │ │ │ ├── array_dynamic_2_fail.sol │ │ │ │ ├── array_dynamic_3.sol │ │ │ │ ├── array_dynamic_3_fail.sol │ │ │ │ ├── array_dynamic_parameter_1.sol │ │ │ │ ├── array_dynamic_parameter_1_fail.sol │ │ │ │ ├── array_literal_1.sol │ │ │ │ ├── array_literal_2.sol │ │ │ │ ├── array_literal_3.sol │ │ │ │ ├── array_literal_4.sol │ │ │ │ ├── array_literal_5.sol │ │ │ │ ├── array_literal_6.sol │ │ │ │ ├── array_literal_7.sol │ │ │ │ ├── array_mapping_aliasing_1.sol │ │ │ │ ├── array_mapping_aliasing_2.sol │ │ │ │ ├── array_of_addresses.sol │ │ │ │ ├── array_of_contracts.sol │ │ │ │ ├── array_of_functions.sol │ │ │ │ ├── array_static_1.sol │ │ │ │ ├── array_static_1_fail.sol │ │ │ │ ├── array_static_2.sol │ │ │ │ ├── array_static_2_fail.sol │ │ │ │ ├── array_static_3.sol │ │ │ │ ├── array_static_3_fail.sol │ │ │ │ ├── array_static_aliasing_memory_5.sol │ │ │ │ ├── array_static_aliasing_storage_5.sol │ │ │ │ ├── array_static_mapping_aliasing_1.sol │ │ │ │ ├── array_static_mapping_aliasing_2.sol │ │ │ │ ├── array_struct_array_branches_2d.sol │ │ │ │ ├── bool_int_mixed_1.sol │ │ │ │ ├── bool_int_mixed_2.sol │ │ │ │ ├── bool_int_mixed_3.sol │ │ │ │ ├── bool_simple_1.sol │ │ │ │ ├── bool_simple_2.sol │ │ │ │ ├── bool_simple_3.sol │ │ │ │ ├── bool_simple_4.sol │ │ │ │ ├── bool_simple_5.sol │ │ │ │ ├── bool_simple_6.sol │ │ │ │ ├── bytes_1.sol │ │ │ │ ├── bytes_2.sol │ │ │ │ ├── bytes_2_fail.sol │ │ │ │ ├── bytes_length.sol │ │ │ │ ├── contract.sol │ │ │ │ ├── contract_2.sol │ │ │ │ ├── contract_3.sol │ │ │ │ ├── contract_address_conversion.sol │ │ │ │ ├── contract_address_conversion_2.sol │ │ │ │ ├── data_location_in_function_type.sol │ │ │ │ ├── enum_explicit_values.sol │ │ │ │ ├── enum_explicit_values_2.sol │ │ │ │ ├── enum_in_library.sol │ │ │ │ ├── enum_in_library_2.sol │ │ │ │ ├── enum_in_struct.sol │ │ │ │ ├── enum_range.sol │ │ │ │ ├── enum_storage_eq.sol │ │ │ │ ├── enum_transitivity.sol │ │ │ │ ├── event_with_rational_size_array.sol │ │ │ │ ├── fixed_bytes_1.sol │ │ │ │ ├── fixed_bytes_2.sol │ │ │ │ ├── fixed_bytes_access_1.sol │ │ │ │ ├── fixed_bytes_access_2.sol │ │ │ │ ├── fixed_bytes_access_3.sol │ │ │ │ ├── fixed_bytes_access_4.sol │ │ │ │ ├── fixed_bytes_access_5.sol │ │ │ │ ├── fixed_bytes_access_6.sol │ │ │ │ ├── fixed_bytes_access_7.sol │ │ │ │ ├── fixed_bytes_range.sol │ │ │ │ ├── function_in_tuple_1.sol │ │ │ │ ├── function_in_tuple_2.sol │ │ │ │ ├── function_type_array_as_reference_type.sol │ │ │ │ ├── function_type_arrays.sol │ │ │ │ ├── function_type_as_argument.sol │ │ │ │ ├── function_type_call.sol │ │ │ │ ├── function_type_external_address.sol │ │ │ │ ├── function_type_members.sol │ │ │ │ ├── function_type_nested.sol │ │ │ │ ├── function_type_nested_return.sol │ │ │ │ ├── mapping_1.sol │ │ │ │ ├── mapping_1_fail.sol │ │ │ │ ├── mapping_2.sol │ │ │ │ ├── mapping_2d_1.sol │ │ │ │ ├── mapping_2d_1_fail.sol │ │ │ │ ├── mapping_3.sol │ │ │ │ ├── mapping_3d_1.sol │ │ │ │ ├── mapping_3d_1_fail.sol │ │ │ │ ├── mapping_4.sol │ │ │ │ ├── mapping_5.sol │ │ │ │ ├── mapping_6.sol │ │ │ │ ├── mapping_aliasing_1.sol │ │ │ │ ├── mapping_aliasing_2.sol │ │ │ │ ├── mapping_and_array_of_functions.sol │ │ │ │ ├── mapping_as_local_var_1.sol │ │ │ │ ├── mapping_as_parameter_1.sol │ │ │ │ ├── mapping_equal_keys_1.sol │ │ │ │ ├── mapping_equal_keys_2.sol │ │ │ │ ├── mapping_integer_signedness_compatibility.sol │ │ │ │ ├── mapping_struct_assignment.sol │ │ │ │ ├── mapping_unsupported_key_type_1.sol │ │ │ │ ├── no_effect_statements.sol │ │ │ │ ├── rational_large_1.sol │ │ │ │ ├── static_array_implicit_push_1.sol │ │ │ │ ├── static_array_implicit_push_2.sol │ │ │ │ ├── static_array_implicit_push_3.sol │ │ │ │ ├── static_array_implicit_push_4.sol │ │ │ │ ├── static_array_length_1.sol │ │ │ │ ├── static_array_length_2.sol │ │ │ │ ├── static_array_length_3.sol │ │ │ │ ├── static_array_length_4.sol │ │ │ │ ├── static_array_length_5.sol │ │ │ │ ├── storage_value_vars_1.sol │ │ │ │ ├── storage_value_vars_2.sol │ │ │ │ ├── storage_value_vars_3.sol │ │ │ │ ├── storage_value_vars_4.sol │ │ │ │ ├── string_1.sol │ │ │ │ ├── string_2.sol │ │ │ │ ├── string_length.sol │ │ │ │ ├── string_literal_assignment_1.sol │ │ │ │ ├── string_literal_assignment_2.sol │ │ │ │ ├── string_literal_assignment_3.sol │ │ │ │ ├── string_literal_assignment_4.sol │ │ │ │ ├── string_literal_assignment_5.sol │ │ │ │ ├── string_literal_comparison_1.sol │ │ │ │ ├── string_literal_comparison_2.sol │ │ │ │ ├── struct/ │ │ │ │ │ ├── array_struct_array_struct_memory_safe.sol │ │ │ │ │ ├── array_struct_array_struct_memory_unsafe.sol │ │ │ │ │ ├── array_struct_array_struct_storage_safe.sol │ │ │ │ │ ├── struct_aliasing_memory.sol │ │ │ │ │ ├── struct_aliasing_parameter_memory_1.sol │ │ │ │ │ ├── struct_aliasing_parameter_memory_2.sol │ │ │ │ │ ├── struct_aliasing_parameter_memory_3.sol │ │ │ │ │ ├── struct_aliasing_parameter_storage_1.sol │ │ │ │ │ ├── struct_aliasing_parameter_storage_2.sol │ │ │ │ │ ├── struct_aliasing_parameter_storage_3.sol │ │ │ │ │ ├── struct_aliasing_parameter_storage_4.sol │ │ │ │ │ ├── struct_aliasing_storage.sol │ │ │ │ │ ├── struct_array_struct_array_memory_safe.sol │ │ │ │ │ ├── struct_array_struct_array_memory_unsafe_1.sol │ │ │ │ │ ├── struct_array_struct_array_memory_unsafe_2.sol │ │ │ │ │ ├── struct_array_struct_array_storage_safe.sol │ │ │ │ │ ├── struct_array_struct_array_storage_unsafe_1.sol │ │ │ │ │ ├── struct_constructor_fixed_bytes_from_string_1.sol │ │ │ │ │ ├── struct_constructor_named_args.sol │ │ │ │ │ ├── struct_constructor_named_args_2.sol │ │ │ │ │ ├── struct_constructor_recursive_1.sol │ │ │ │ │ ├── struct_constructor_recursive_2.sol │ │ │ │ │ ├── struct_delete_memory.sol │ │ │ │ │ ├── struct_delete_storage.sol │ │ │ │ │ ├── struct_external_function_pointer.sol │ │ │ │ │ ├── struct_mapping.sol │ │ │ │ │ ├── struct_nested_constructor.sol │ │ │ │ │ ├── struct_nested_constructor_named_args.sol │ │ │ │ │ ├── struct_nested_temporary.sol │ │ │ │ │ ├── struct_recursive_1.sol │ │ │ │ │ ├── struct_recursive_2.sol │ │ │ │ │ ├── struct_recursive_3.sol │ │ │ │ │ ├── struct_recursive_4.sol │ │ │ │ │ ├── struct_recursive_5.sol │ │ │ │ │ ├── struct_recursive_6.sol │ │ │ │ │ ├── struct_recursive_indirect_1.sol │ │ │ │ │ ├── struct_recursive_indirect_2.sol │ │ │ │ │ ├── struct_return.sol │ │ │ │ │ ├── struct_state_constructor.sol │ │ │ │ │ ├── struct_state_var.sol │ │ │ │ │ ├── struct_state_var_array_pop_1.sol │ │ │ │ │ ├── struct_state_var_array_pop_2.sol │ │ │ │ │ ├── struct_temporary.sol │ │ │ │ │ ├── struct_unary_add.sol │ │ │ │ │ └── struct_unary_sub.sol │ │ │ │ ├── struct_1.sol │ │ │ │ ├── struct_array_branches_1d.sol │ │ │ │ ├── struct_array_branches_2d.sol │ │ │ │ ├── struct_array_branches_3d.sol │ │ │ │ ├── tuple_1_chain_1.sol │ │ │ │ ├── tuple_1_chain_2.sol │ │ │ │ ├── tuple_1_chain_n.sol │ │ │ │ ├── tuple_array_pop_1.sol │ │ │ │ ├── tuple_array_pop_2.sol │ │ │ │ ├── tuple_assignment.sol │ │ │ │ ├── tuple_assignment_array.sol │ │ │ │ ├── tuple_assignment_array_empty.sol │ │ │ │ ├── tuple_assignment_compound.sol │ │ │ │ ├── tuple_assignment_empty.sol │ │ │ │ ├── tuple_assignment_multiple_calls.sol │ │ │ │ ├── tuple_declarations.sol │ │ │ │ ├── tuple_declarations_empty.sol │ │ │ │ ├── tuple_declarations_function.sol │ │ │ │ ├── tuple_declarations_function_2.sol │ │ │ │ ├── tuple_declarations_function_empty.sol │ │ │ │ ├── tuple_different_count_assignment_1.sol │ │ │ │ ├── tuple_different_count_assignment_2.sol │ │ │ │ ├── tuple_extra_parens_1.sol │ │ │ │ ├── tuple_extra_parens_2.sol │ │ │ │ ├── tuple_extra_parens_3.sol │ │ │ │ ├── tuple_extra_parens_4.sol │ │ │ │ ├── tuple_extra_parens_5.sol │ │ │ │ ├── tuple_extra_parens_6.sol │ │ │ │ ├── tuple_extra_parens_7.sol │ │ │ │ ├── tuple_function.sol │ │ │ │ ├── tuple_function_2.sol │ │ │ │ ├── tuple_function_3.sol │ │ │ │ ├── tuple_return_branch.sol │ │ │ │ ├── tuple_single_element_1.sol │ │ │ │ ├── tuple_single_element_2.sol │ │ │ │ ├── tuple_single_non_tuple_element.sol │ │ │ │ ├── tuple_tuple.sol │ │ │ │ ├── type_expression_array_2d.sol │ │ │ │ ├── type_expression_array_3d.sol │ │ │ │ ├── type_expression_tuple_array_2d.sol │ │ │ │ ├── type_expression_tuple_array_3d.sol │ │ │ │ ├── type_interfaceid.sol │ │ │ │ ├── type_meta_unsupported.sol │ │ │ │ ├── type_minmax.sol │ │ │ │ ├── type_simple_range.sol │ │ │ │ └── unused_mapping.sol │ │ │ ├── unchecked/ │ │ │ │ ├── block_inside_unchecked.sol │ │ │ │ ├── check_var_init.sol │ │ │ │ ├── checked_called_by_unchecked.sol │ │ │ │ ├── checked_modifier_called_by_unchecked.sol │ │ │ │ ├── flipping_sign_tests.sol │ │ │ │ ├── inc_dec.sol │ │ │ │ ├── signed_mod.sol │ │ │ │ ├── unchecked_called_by_checked.sol │ │ │ │ ├── unchecked_div_by_zero.sol │ │ │ │ ├── unchecked_double_with_modifier.sol │ │ │ │ └── unchecked_function_call_with_unchecked_block.sol │ │ │ ├── unsupported/ │ │ │ │ ├── assembly_1.sol │ │ │ │ └── transient_storage_state_variable.sol │ │ │ ├── userTypes/ │ │ │ │ ├── constant.sol │ │ │ │ ├── conversion_1.sol │ │ │ │ ├── conversion_2.sol │ │ │ │ ├── conversion_3.sol │ │ │ │ ├── conversion_4.sol │ │ │ │ ├── fixedpoint.sol │ │ │ │ ├── in_parenthesis.sol │ │ │ │ ├── in_parenthesis_2.sol │ │ │ │ ├── mapping_1.sol │ │ │ │ ├── modifier_1.sol │ │ │ │ ├── multisource.sol │ │ │ │ ├── multisource_module.sol │ │ │ │ ├── simple.sol │ │ │ │ ├── user_abi_1.sol │ │ │ │ ├── user_abi_2.sol │ │ │ │ ├── user_type_as_array_elem_1.sol │ │ │ │ ├── user_type_as_array_elem_2.sol │ │ │ │ ├── user_type_as_library_constant_1.sol │ │ │ │ ├── user_type_as_library_constant_2.sol │ │ │ │ ├── user_type_as_mapping_index_1.sol │ │ │ │ ├── user_type_as_mapping_index_2.sol │ │ │ │ ├── user_type_as_struct_member_1.sol │ │ │ │ ├── user_type_over_fixed_bytes_can_be_initialized_from_string_literal.sol │ │ │ │ └── wrap_unwrap_via_contract_name.sol │ │ │ └── verification_target/ │ │ │ ├── constant_condition_1.sol │ │ │ ├── constant_condition_2.sol │ │ │ ├── constant_condition_3.sol │ │ │ ├── no_target_for_abstract_constract.sol │ │ │ ├── no_target_for_constructor_of_abstract_constract.sol │ │ │ ├── simple_assert.sol │ │ │ ├── simple_assert_with_require.sol │ │ │ ├── simple_assert_with_require_message.sol │ │ │ ├── target_in_constructor_of_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol │ │ │ └── target_in_same_source_contract_not_analyzed_when_not_selected_and_not_called_from_selection.sol │ │ ├── syntaxTests/ │ │ │ ├── abiEncoder/ │ │ │ │ ├── abi_encodeCall_error_free_function.sol │ │ │ │ ├── abi_encodeCall_event_free_function.sol │ │ │ │ ├── abi_encodeCall_free_func.sol │ │ │ │ ├── abi_encodeCall_on_lib_func_in_free_func.sol │ │ │ │ ├── abi_encodeCall_tuple_from_assignment_expression.sol │ │ │ │ ├── abi_encodeCall_tuple_from_conditional_ternary_expression.sol │ │ │ │ ├── abi_encodeCall_tuple_from_error_event.sol │ │ │ │ ├── abi_encodeCall_tuple_from_invalid_operator.sol │ │ │ │ ├── abi_encodeCall_tuple_returned_from_function.sol │ │ │ │ ├── abi_encodeCall_unitary_tuple_from_assignment_expression.sol │ │ │ │ ├── abi_encodeCall_unitary_tuple_from_conditional_ternary_expression.sol │ │ │ │ ├── abi_encodeCall_unitary_tuple_returned_from_function.sol │ │ │ │ ├── abi_encode_conversions.sol │ │ │ │ ├── abi_encode_conversions_address.sol │ │ │ │ ├── abi_encode_conversions_function_pointers.sol │ │ │ │ ├── conflicting_settings.sol │ │ │ │ ├── conflicting_settings_reverse.sol │ │ │ │ ├── conflicting_settings_reverse_experimental.sol │ │ │ │ ├── external_functions_taking_internal_types_nested_struct_with_mapping.sol │ │ │ │ ├── external_functions_taking_internal_types_struct_array_with_function_type.sol │ │ │ │ ├── external_functions_taking_internal_types_struct_with_array_of_function_types.sol │ │ │ │ ├── external_functions_taking_internal_types_struct_with_function_type.sol │ │ │ │ ├── external_functions_taking_internal_types_struct_with_mapping.sol │ │ │ │ ├── invalid_pragma_value.sol │ │ │ │ ├── overloaded_external_functions_taking_different_structs.sol │ │ │ │ ├── overloaded_external_functions_taking_identical_structs.sol │ │ │ │ ├── same_setting_twice.sol │ │ │ │ ├── select_v1.sol │ │ │ │ ├── select_v1_quoted_string.sol │ │ │ │ ├── select_v2_quoted_string.sol │ │ │ │ ├── selected_twice.sol │ │ │ │ ├── selected_twice_v2.sol │ │ │ │ ├── tight_packing_literals.sol │ │ │ │ ├── tight_packing_literals_fine.sol │ │ │ │ ├── v1_accessing_public_state_variable_via_v1_type.sol │ │ │ │ ├── v1_accessing_public_state_variable_via_v2_type.sol │ │ │ │ ├── v1_call_to_v1_library_function_accepting_storage_struct.sol │ │ │ │ ├── v1_call_to_v2_constructor_accepting_struct.sol │ │ │ │ ├── v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol │ │ │ │ ├── v1_call_to_v2_contract_function_pointer_accepting_struct.sol │ │ │ │ ├── v1_call_to_v2_contract_function_returning_dynamic_string_array.sol │ │ │ │ ├── v1_call_to_v2_contract_function_returning_struct.sol │ │ │ │ ├── v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol │ │ │ │ ├── v1_call_to_v2_event_accepting_struct.sol │ │ │ │ ├── v1_call_to_v2_library_attached_function_returning_struct.sol │ │ │ │ ├── v1_call_to_v2_library_function_accepting_storage_struct.sol │ │ │ │ ├── v1_call_to_v2_library_function_returning_struct.sol │ │ │ │ ├── v1_call_to_v2_modifier.sol │ │ │ │ ├── v1_constructor_with_v2_modifier.sol │ │ │ │ ├── v1_inheritance_from_contract_calling_v2_function.sol │ │ │ │ ├── v1_inheritance_from_contract_defining_v2_event.sol │ │ │ │ ├── v1_inheritance_from_contract_defining_v2_function_accepting_struct.sol │ │ │ │ ├── v1_inheritance_from_contract_defining_v2_function_returning_struct.sol │ │ │ │ ├── v1_inheritance_from_contract_emitting_v2_event.sol │ │ │ │ ├── v1_modifier_overriding_v2_modifier.sol │ │ │ │ ├── v1_v2_v1_modifier_mix.sol │ │ │ │ ├── v2_accessing_returned_dynamic_array_with_returndata_support.sol │ │ │ │ ├── v2_accessing_returned_dynamic_array_without_returndata_support.sol │ │ │ │ ├── v2_call_to_v2_constructor_accepting_struct.sol │ │ │ │ ├── v2_call_to_v2_contract_function_pointer_accepting_struct.sol │ │ │ │ ├── v2_call_to_v2_contract_function_returning_dynamic_string_array.sol │ │ │ │ ├── v2_call_to_v2_contract_function_returning_struct.sol │ │ │ │ ├── v2_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol │ │ │ │ ├── v2_call_to_v2_event_accepting_struct.sol │ │ │ │ ├── v2_call_to_v2_library_function_pointer_accepting_struct.sol │ │ │ │ ├── v2_call_to_v2_library_function_returning_struct.sol │ │ │ │ ├── v2_v1_v1_modifier_sandwich.sol │ │ │ │ └── v2_v1_v2_modifier_sandwich.sol │ │ │ ├── abstract/ │ │ │ │ ├── abstract_contract_because_of_interface.sol │ │ │ │ ├── abstract_contract_instantiation.sol │ │ │ │ ├── abstract_only.sol │ │ │ │ ├── abstract_without_contract.sol │ │ │ │ ├── contract.sol │ │ │ │ ├── interface.sol │ │ │ │ ├── library.sol │ │ │ │ ├── unimplemented_functions.sol │ │ │ │ └── unimplemented_functions_inherited.sol │ │ │ ├── array/ │ │ │ │ ├── array_pop.sol │ │ │ │ ├── array_pop_arg.sol │ │ │ │ ├── bytes1_array_push_assign_multi.sol │ │ │ │ ├── bytes_assign_multi_fine.sol │ │ │ │ ├── bytes_pop.sol │ │ │ │ ├── bytes_push_assign_multi.sol │ │ │ │ ├── bytes_to_fixed_bytes.sol │ │ │ │ ├── calldata.sol │ │ │ │ ├── calldata_assign.sol │ │ │ │ ├── calldata_dynamic.sol │ │ │ │ ├── calldata_multi.sol │ │ │ │ ├── calldata_multi_dynamic.sol │ │ │ │ ├── calldata_multi_dynamic_V1.sol │ │ │ │ ├── calldata_resize.sol │ │ │ │ ├── concat/ │ │ │ │ │ ├── bytes_concat_empty_invalid.sol │ │ │ │ │ ├── bytes_concat_on_type_info.sol │ │ │ │ │ ├── bytes_concat_on_variable.sol │ │ │ │ │ ├── bytes_concat_valid_type_literal.sol │ │ │ │ │ ├── bytes_concat_wrong_type_bytes_and_strings.sol │ │ │ │ │ ├── bytes_concat_wrong_type_empty_array_literal.sol │ │ │ │ │ ├── bytes_concat_wrong_type_empty_string_literal.sol │ │ │ │ │ ├── bytes_concat_wrong_type_misc.sol │ │ │ │ │ ├── bytes_concat_wrong_type_misc_literals_and_expressions.sol │ │ │ │ │ └── bytes_concat_wrong_type_zero_literal.sol │ │ │ │ ├── contract_array.sol │ │ │ │ ├── contract_index_access.sol │ │ │ │ ├── copy_calldata_struct_array_to_storage_legacy.sol │ │ │ │ ├── copy_from_function_type.sol │ │ │ │ ├── copy_memory_struct_array_to_storage_legacy.sol │ │ │ │ ├── copy_storage_arrays_of_function_type.sol │ │ │ │ ├── dynamic_memory_array_pop.sol │ │ │ │ ├── function_mapping.sol │ │ │ │ ├── function_mapping_library.sol │ │ │ │ ├── invalid/ │ │ │ │ │ ├── bytes_to_fixed_bytes.sol │ │ │ │ │ ├── library_array.sol │ │ │ │ │ └── library_index_access.sol │ │ │ │ ├── invalidCopy/ │ │ │ │ │ ├── calldata_to_memory_different_base.sol │ │ │ │ │ ├── storage_to_memory_different_base.sol │ │ │ │ │ ├── storage_to_storage_different_base.sol │ │ │ │ │ ├── storage_to_storage_different_base_2.sol │ │ │ │ │ ├── storage_to_storage_different_sign.sol │ │ │ │ │ ├── storage_to_storage_dynamic_to_static.sol │ │ │ │ │ └── storage_to_storage_static_longer_to_shorter.sol │ │ │ │ ├── length/ │ │ │ │ │ ├── abi_decode_length_too_large.sol │ │ │ │ │ ├── array_length_cannot_be_constant_function_parameter.sol │ │ │ │ │ ├── builtin_erc7201_comptime.sol │ │ │ │ │ ├── bytes32_too_large.sol │ │ │ │ │ ├── bytes32_too_large_multidim.sol │ │ │ │ │ ├── can_be_constant_in_function.sol │ │ │ │ │ ├── can_be_constant_in_struct.sol │ │ │ │ │ ├── can_be_recursive_constant.sol │ │ │ │ │ ├── cannot_be_assigned.sol │ │ │ │ │ ├── cannot_be_assigned_mapping.sol │ │ │ │ │ ├── cannot_be_assigned_struct.sol │ │ │ │ │ ├── cannot_be_function.sol │ │ │ │ │ ├── cannot_be_function_call.sol │ │ │ │ │ ├── complex_cyclic_constant.sol │ │ │ │ │ ├── const_cannot_be_fractional.sol │ │ │ │ │ ├── constant_var.sol │ │ │ │ │ ├── cyclic_constant.sol │ │ │ │ │ ├── fixed_size_multidim_zero_length.sol │ │ │ │ │ ├── fixed_size_zero_length.sol │ │ │ │ │ ├── inline_array.sol │ │ │ │ │ ├── invalid_expression_1.sol │ │ │ │ │ ├── invalid_expression_2.sol │ │ │ │ │ ├── invalid_expression_3.sol │ │ │ │ │ ├── invalid_expression_4.sol │ │ │ │ │ ├── invalid_expression_5.sol │ │ │ │ │ ├── literal_conversion.sol │ │ │ │ │ ├── local_memory_too_large.sol │ │ │ │ │ ├── non_integer_constant_var.sol │ │ │ │ │ ├── not_convertible_to_integer.sol │ │ │ │ │ ├── parameter_too_large.sol │ │ │ │ │ ├── parameter_too_large_multidim.sol │ │ │ │ │ ├── parameter_too_large_multidim_ABIv2.sol │ │ │ │ │ ├── parentheses.sol │ │ │ │ │ ├── pure_functions.sol │ │ │ │ │ ├── string_as_array_length.sol │ │ │ │ │ ├── too_large.sol │ │ │ │ │ ├── tuples.sol │ │ │ │ │ └── uint_too_large_multidim.sol │ │ │ │ ├── library_array.sol │ │ │ │ ├── nested_calldata_memory.sol │ │ │ │ ├── nested_calldata_memory2.sol │ │ │ │ ├── nested_calldata_memory3.sol │ │ │ │ ├── nested_calldata_storage.sol │ │ │ │ ├── nested_calldata_storage2.sol │ │ │ │ ├── new_no_parentheses.sol │ │ │ │ ├── no_array_pop.sol │ │ │ │ ├── pop/ │ │ │ │ │ ├── calldata_pop.sol │ │ │ │ │ ├── memory_pop.sol │ │ │ │ │ └── storage_with_mapping_pop.sol │ │ │ │ ├── push/ │ │ │ │ │ ├── calldata_push.sol │ │ │ │ │ ├── memory_push.sol │ │ │ │ │ └── storage_with_mapping_push.sol │ │ │ │ ├── slice/ │ │ │ │ │ ├── assign_to_storage.sol │ │ │ │ │ ├── bytes_calldata.sol │ │ │ │ │ ├── bytes_memory.sol │ │ │ │ │ ├── bytes_storage.sol │ │ │ │ │ ├── calldata_dynamic.sol │ │ │ │ │ ├── calldata_dynamic_access.sol │ │ │ │ │ ├── calldata_dynamic_convert_to_memory.sol │ │ │ │ │ ├── calldata_dynamic_encode.sol │ │ │ │ │ ├── calldata_dynamic_forward.sol │ │ │ │ │ ├── calldata_static.sol │ │ │ │ │ ├── member_access.sol │ │ │ │ │ ├── memory_dynamic.sol │ │ │ │ │ ├── memory_static.sol │ │ │ │ │ ├── slice_literal.sol │ │ │ │ │ ├── slice_memory_bytes.sol │ │ │ │ │ ├── slice_memory_string.sol │ │ │ │ │ ├── slice_string.sol │ │ │ │ │ ├── storage_dynamic.sol │ │ │ │ │ └── storage_static.sol │ │ │ │ ├── static_storage_array_pop.sol │ │ │ │ ├── string_pop.sol │ │ │ │ └── uninitialized_storage_var.sol │ │ │ ├── bytecodeReferences/ │ │ │ │ ├── circular_reference_complex.sol │ │ │ │ ├── circular_reference_complex1.sol │ │ │ │ ├── circular_reference_free_function.sol │ │ │ │ ├── circular_reference_function_parameters.sol │ │ │ │ ├── circular_reference_internal_function.sol │ │ │ │ ├── circular_reference_internal_functions.sol │ │ │ │ ├── circular_reference_libraries.sol │ │ │ │ ├── circular_reference_mention_only.sol │ │ │ │ ├── circular_reference_new_in_ctor.sol │ │ │ │ ├── circular_reference_report_first_in_cycle.sol │ │ │ │ ├── circular_reference_type_mention_only.sol │ │ │ │ ├── cyclic_dep_exhaustion.sol │ │ │ │ ├── library_called.sol │ │ │ │ ├── library_function_circular_reference.sol │ │ │ │ ├── library_non_called.sol │ │ │ │ ├── library_public_called.sol │ │ │ │ └── library_public_without_contract.sol │ │ │ ├── comments/ │ │ │ │ ├── multiline_comments.sol │ │ │ │ ├── multiline_unicode_direction_override_1.sol │ │ │ │ ├── multiline_unicode_direction_override_2.sol │ │ │ │ ├── multiline_unicode_direction_override_3.sol │ │ │ │ ├── multiline_unicode_direction_override_4.sol │ │ │ │ ├── multiline_unicode_direction_override_5.sol │ │ │ │ ├── multiline_unicode_direction_override_6.sol │ │ │ │ ├── multiline_unicode_direction_override_7.sol │ │ │ │ ├── singleline_unicode_direction_override_1.sol │ │ │ │ ├── singleline_unicode_direction_override_2.sol │ │ │ │ ├── singleline_unicode_direction_override_3.sol │ │ │ │ ├── singleline_unicode_direction_override_4.sol │ │ │ │ ├── singleline_unicode_direction_override_5.sol │ │ │ │ ├── singleline_unicode_direction_override_6.sol │ │ │ │ ├── unicode_direction_in_source_1.sol │ │ │ │ ├── unicode_direction_in_source_2.sol │ │ │ │ └── unicode_direction_override_1.sol │ │ │ ├── constantEvaluator/ │ │ │ │ ├── erc7201_builtin.sol │ │ │ │ ├── overflow.sol │ │ │ │ ├── type_reference.sol │ │ │ │ ├── type_reference_in_contract.sol │ │ │ │ ├── unary_fine.sol │ │ │ │ ├── underflow.sol │ │ │ │ └── underflow_unary.sol │ │ │ ├── constants/ │ │ │ │ ├── access_via_getter.sol │ │ │ │ ├── constant_cyclic_via_user_operators.sol │ │ │ │ ├── constant_natspec.sol │ │ │ │ ├── constant_natspec_user.sol │ │ │ │ ├── constant_override.sol │ │ │ │ ├── constant_state_variable_named_transient.sol │ │ │ │ ├── constant_transient_state_variable.sol │ │ │ │ ├── constant_unassigned.sol │ │ │ │ ├── constant_variables_as_static_array_length.sol │ │ │ │ ├── constant_virtual.sol │ │ │ │ ├── constant_with_dependencies_as_array_sizes.sol │ │ │ │ ├── constant_with_dependencies_on_constants.sol │ │ │ │ ├── constant_with_dependencies_on_file_level_constants.sol │ │ │ │ ├── constant_with_visibility.sol │ │ │ │ ├── constant_with_visibility_inverted.sol │ │ │ │ ├── constants_with_dependencies_on_library_constants_multi_file.sol │ │ │ │ ├── cross_file_cyclic.sol │ │ │ │ ├── cross_file_cyclic_modules.sol │ │ │ │ ├── file_level_memory.sol │ │ │ │ ├── file_level_memory_inverted.sol │ │ │ │ ├── file_level_multiple_constant_keywords.sol │ │ │ │ ├── immutable_at_file_level.sol │ │ │ │ ├── initialization/ │ │ │ │ │ ├── abi_decode_const_args.sol │ │ │ │ │ ├── abi_decode_non_const_args.sol │ │ │ │ │ ├── abi_encode_call_const_args.sol │ │ │ │ │ ├── abi_encode_call_non_const_args.sol │ │ │ │ │ ├── abi_encoding_builtin_const_args.sol │ │ │ │ │ ├── abi_encoding_builtin_non_const_args.sol │ │ │ │ │ ├── addmod_by_zero.sol │ │ │ │ │ ├── addmod_mulmod_rational_arg.sol │ │ │ │ │ ├── block_tx_msg_property.sol │ │ │ │ │ ├── bytes_concat_const_args.sol │ │ │ │ │ ├── bytes_concat_non_const_args.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_1.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_2.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_3.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_4.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_5.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_file.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_file_and_library.sol │ │ │ │ │ ├── constant_with_cyclic_dependency_library.sol │ │ │ │ │ ├── division_by_zero.sol │ │ │ │ │ ├── function_pointer_call.sol │ │ │ │ │ ├── math_builtin_opcode_based_const_args.sol │ │ │ │ │ ├── math_builtin_opcode_based_non_const_args.sol │ │ │ │ │ ├── math_builtin_precompile_based_const_args.sol │ │ │ │ │ ├── math_builtin_precompile_based_non_const_args.sol │ │ │ │ │ ├── modulo_by_zero.sol │ │ │ │ │ ├── mulmod_by_zero.sol │ │ │ │ │ ├── string_concat_const_args.sol │ │ │ │ │ ├── string_concat_non_const_args.sol │ │ │ │ │ └── type_info.sol │ │ │ │ ├── mapping_constant.sol │ │ │ │ ├── mod_div_rational.sol │ │ │ │ ├── name_clash_via_import.sol │ │ │ │ ├── non_constant.sol │ │ │ │ ├── pure_non_rational.sol │ │ │ │ ├── redefinition_cross_file.sol │ │ │ │ ├── redefinition_public_constant.sol │ │ │ │ └── struct_constant.sol │ │ │ ├── constructor/ │ │ │ │ ├── abstract_creation_forward_reference.sol │ │ │ │ ├── base_constructor_missing_arguments.sol │ │ │ │ ├── base_constructor_missing_arguments_abstract_inheritance_list_empty_parens.sol │ │ │ │ ├── base_constructor_missing_arguments_abstract_lists_omitted.sol │ │ │ │ ├── base_constructor_missing_arguments_abstract_modifier_init.sol │ │ │ │ ├── base_constructor_missing_arguments_abstract_modifier_init_empty_list.sol │ │ │ │ ├── base_constructor_wrong_arg_count_inheritance_and_modifier_lists.sol │ │ │ │ ├── base_constructor_wrong_arg_count_inheritance_list.sol │ │ │ │ ├── base_constructor_wrong_arg_count_inheritance_list_abstract.sol │ │ │ │ ├── base_constructor_wrong_arg_count_inheritance_list_empty_parens_and_modifier_list.sol │ │ │ │ ├── base_constructor_wrong_arg_count_inheritance_list_with_derived_constructor.sol │ │ │ │ ├── base_constructor_wrong_arg_count_modifier_list.sol │ │ │ │ ├── calldata_constructor_args.sol │ │ │ │ ├── constructible_abstract_base.sol │ │ │ │ ├── constructible_internal_constructor.sol │ │ │ │ ├── constructor.sol │ │ │ │ ├── constructor_function_parameter_disallowed_conversion.sol │ │ │ │ ├── constructor_internal_function.sol │ │ │ │ ├── constructor_internal_function_abstract.sol │ │ │ │ ├── constructor_mapping_memory.sol │ │ │ │ ├── constructor_mapping_memory_abstract.sol │ │ │ │ ├── constructor_old.sol │ │ │ │ ├── constructor_override.sol │ │ │ │ ├── constructor_payable.sol │ │ │ │ ├── constructor_state_mutability.sol │ │ │ │ ├── constructor_storage.sol │ │ │ │ ├── constructor_storage_abstract.sol │ │ │ │ ├── constructor_this.sol │ │ │ │ ├── constructor_virtual.sol │ │ │ │ ├── constructor_visibility.sol │ │ │ │ ├── constructor_without_implementation.sol │ │ │ │ ├── external_constructor.sol │ │ │ │ ├── function_named_constructor.sol │ │ │ │ ├── inconstructible_abstract_contract.sol │ │ │ │ ├── inconstructible_abstract_contract_inverted.sol │ │ │ │ ├── inconstructible_internal_constructor.sol │ │ │ │ ├── inconstructible_internal_constructor_inverted.sol │ │ │ │ ├── interface_constructor.sol │ │ │ │ ├── internal_constructor_non_abstract.sol │ │ │ │ ├── library_constructor.sol │ │ │ │ ├── msg_value_non_payable.sol │ │ │ │ ├── nonabiv2_type.sol │ │ │ │ ├── nonabiv2_type_abstract.sol │ │ │ │ ├── nonpayable_new.sol │ │ │ │ ├── not_a_contract.sol │ │ │ │ ├── overriding_constructor.sol │ │ │ │ ├── payable_new.sol │ │ │ │ ├── public_constructor_abstract.sol │ │ │ │ ├── public_constructor_non_abstract.sol │ │ │ │ ├── returns_in_constructor.sol │ │ │ │ └── two_constructors.sol │ │ │ ├── controlFlow/ │ │ │ │ ├── calldataReturn/ │ │ │ │ │ ├── calldata_return_dynamic_array.sol │ │ │ │ │ ├── calldata_return_static_array.sol │ │ │ │ │ └── calldata_return_struct.sol │ │ │ │ ├── free_function_crash.sol │ │ │ │ ├── leave_inside_function.sol │ │ │ │ ├── leave_outside_function.sol │ │ │ │ ├── localCalldataVariables/ │ │ │ │ │ ├── if_declaration_err.sol │ │ │ │ │ ├── if_declaration_fine.sol │ │ │ │ │ └── smoke_declaration.sol │ │ │ │ ├── localStorageVariables/ │ │ │ │ │ ├── assembly/ │ │ │ │ │ │ ├── for_declaration_err.sol │ │ │ │ │ │ ├── for_declaration_fine.sol │ │ │ │ │ │ ├── if_declaration_err.sol │ │ │ │ │ │ ├── returning_function_declaration.sol │ │ │ │ │ │ ├── reverting_function_declaration.sol │ │ │ │ │ │ ├── stub_declaration.sol │ │ │ │ │ │ ├── switch_declaration_err.sol │ │ │ │ │ │ └── switch_declaration_fine.sol │ │ │ │ │ ├── dowhile_declaration_err.sol │ │ │ │ │ ├── dowhile_declaration_fine.sol │ │ │ │ │ ├── for_declaration_err.sol │ │ │ │ │ ├── for_declaration_fine.sol │ │ │ │ │ ├── if_declaration_err.sol │ │ │ │ │ ├── if_declaration_fine.sol │ │ │ │ │ ├── modifier_declaration_fine.sol │ │ │ │ │ ├── revert_declaration_fine.sol │ │ │ │ │ ├── short_circuit_declaration_err.sol │ │ │ │ │ ├── short_circuit_declaration_fine.sol │ │ │ │ │ ├── smoke_declaration.sol │ │ │ │ │ ├── ternary_assignment_err.sol │ │ │ │ │ ├── ternary_assignment_fine.sol │ │ │ │ │ ├── ternary_declaration_err.sol │ │ │ │ │ ├── ternary_declaration_fine.sol │ │ │ │ │ ├── try_declaration_err.sol │ │ │ │ │ ├── try_declaration_fine.sol │ │ │ │ │ ├── tuple_declaration_fine.sol │ │ │ │ │ ├── while_declaration_err.sol │ │ │ │ │ └── while_declaration_fine.sol │ │ │ │ ├── mappingReturn/ │ │ │ │ │ ├── named_err.sol │ │ │ │ │ ├── named_fine.sol │ │ │ │ │ ├── unnamed_err.sol │ │ │ │ │ └── unnamed_fine.sol │ │ │ │ ├── modifiers/ │ │ │ │ │ ├── implemented_without_placeholder.sol │ │ │ │ │ ├── modifier_different_functions.sol │ │ │ │ │ ├── modifier_override.sol │ │ │ │ │ └── non_implemented_modifier.sol │ │ │ │ ├── storageReturn/ │ │ │ │ │ ├── assembly/ │ │ │ │ │ │ ├── for_err.sol │ │ │ │ │ │ ├── for_fine.sol │ │ │ │ │ │ ├── if_err.sol │ │ │ │ │ │ ├── returning_function.sol │ │ │ │ │ │ ├── reverting_function.sol │ │ │ │ │ │ ├── stub.sol │ │ │ │ │ │ ├── switch_err.sol │ │ │ │ │ │ ├── switch_fine.sol │ │ │ │ │ │ └── switch_only_default_warn.sol │ │ │ │ │ ├── assembly_err.sol │ │ │ │ │ ├── default_location.sol │ │ │ │ │ ├── dowhile_err.sol │ │ │ │ │ ├── dowhile_fine.sol │ │ │ │ │ ├── for_err.sol │ │ │ │ │ ├── for_fine.sol │ │ │ │ │ ├── if_err.sol │ │ │ │ │ ├── if_fine.sol │ │ │ │ │ ├── modifier_err.sol │ │ │ │ │ ├── modifier_fine.sol │ │ │ │ │ ├── revert_fine.sol │ │ │ │ │ ├── short_circuit_err.sol │ │ │ │ │ ├── short_circuit_fine.sol │ │ │ │ │ ├── smoke.sol │ │ │ │ │ ├── ternary_err.sol │ │ │ │ │ ├── ternary_fine.sol │ │ │ │ │ ├── try_err.sol │ │ │ │ │ ├── try_fine.sol │ │ │ │ │ ├── tuple_fine.sol │ │ │ │ │ ├── unimplemented_internal.sol │ │ │ │ │ ├── unimplemented_library.sol │ │ │ │ │ ├── while_err.sol │ │ │ │ │ └── while_fine.sol │ │ │ │ ├── uninitializedAccess/ │ │ │ │ │ ├── always_revert.sol │ │ │ │ │ ├── assembly.sol │ │ │ │ │ ├── bug10821-for.sol │ │ │ │ │ ├── bug10821-if.sol │ │ │ │ │ ├── bug10821-modifier.sol │ │ │ │ │ ├── bug10821-require.sol │ │ │ │ │ ├── bug10821-while.sol │ │ │ │ │ ├── functionType.sol │ │ │ │ │ ├── modifier_order_fail.sol │ │ │ │ │ ├── modifier_order_fine.sol │ │ │ │ │ ├── modifier_post_access.sol │ │ │ │ │ ├── modifier_pre_access.sol │ │ │ │ │ ├── reverting_call.sol │ │ │ │ │ ├── reverting_call_free_function.sol │ │ │ │ │ ├── reverting_call_library.sol │ │ │ │ │ ├── reverting_call_nested.sol │ │ │ │ │ ├── reverting_call_nested1.sol │ │ │ │ │ ├── reverting_call_recursive.sol │ │ │ │ │ ├── reverting_call_static.sol │ │ │ │ │ ├── reverting_call_super.sol │ │ │ │ │ ├── reverting_call_virtual.sol │ │ │ │ │ ├── reverting_call_virtual1.sol │ │ │ │ │ ├── reverting_call_virtual2.sol │ │ │ │ │ ├── reverting_call_virtual3.sol │ │ │ │ │ ├── reverting_call_virtual4.sol │ │ │ │ │ ├── smoke.sol │ │ │ │ │ ├── struct.sol │ │ │ │ │ └── unreachable.sol │ │ │ │ ├── unreachableCode/ │ │ │ │ │ ├── assembly/ │ │ │ │ │ │ ├── double_revert.sol │ │ │ │ │ │ ├── for_break.sol │ │ │ │ │ │ ├── for_continue.sol │ │ │ │ │ │ ├── return.sol │ │ │ │ │ │ └── revert.sol │ │ │ │ │ ├── comment_fine.sol │ │ │ │ │ ├── constant_condition.sol │ │ │ │ │ ├── do_while_continue.sol │ │ │ │ │ ├── double_return.sol │ │ │ │ │ ├── double_revert.sol │ │ │ │ │ ├── for_break.sol │ │ │ │ │ ├── if_both_return.sol │ │ │ │ │ ├── library_function_import_bug.sol │ │ │ │ │ ├── library_function_nonimport_bug.sol │ │ │ │ │ ├── revert.sol │ │ │ │ │ ├── revert_empty.sol │ │ │ │ │ ├── while_break.sol │ │ │ │ │ └── while_continue.sol │ │ │ │ └── userDefinedOperators/ │ │ │ │ ├── binary_operator_udvt.sol │ │ │ │ └── unary_operator_udvt.sol │ │ │ ├── conversion/ │ │ │ │ ├── allowed_conversion_to_bytes_array.sol │ │ │ │ ├── allowed_conversion_to_string.sol │ │ │ │ ├── conversion_to_bytes.sol │ │ │ │ ├── convert_to_super_empty.sol │ │ │ │ ├── convert_to_super_nonempty.sol │ │ │ │ ├── explicit_conversion_address_to_payable.sol │ │ │ │ ├── explicit_conversion_error_to_bytes4.sol │ │ │ │ ├── explicit_conversion_event_to_bytes4.sol │ │ │ │ ├── explicit_conversion_from_error.sol │ │ │ │ ├── explicit_conversion_from_event.sol │ │ │ │ ├── explicit_conversion_from_storage_array_ref.sol │ │ │ │ ├── explicit_conversion_sender_to_payable.sol │ │ │ │ ├── explicit_conversion_this_to_payable.sol │ │ │ │ ├── function_cast_value_set.sol │ │ │ │ ├── function_type_array_to_memory.sol │ │ │ │ ├── function_type_nonpayable_payable.sol │ │ │ │ ├── function_type_nonpayable_pure.sol │ │ │ │ ├── function_type_nonpayable_view.sol │ │ │ │ ├── function_type_payable_nonpayable.sol │ │ │ │ ├── function_type_payable_pure.sol │ │ │ │ ├── function_type_payable_view.sol │ │ │ │ ├── function_type_pure_nonpayable.sol │ │ │ │ ├── function_type_pure_payable.sol │ │ │ │ ├── function_type_pure_view.sol │ │ │ │ ├── function_type_same.sol │ │ │ │ ├── function_type_view_nonpayable.sol │ │ │ │ ├── function_type_view_payable.sol │ │ │ │ ├── function_type_view_pure.sol │ │ │ │ ├── implicit_conversion_error_to_bytes4_function_argument.sol │ │ │ │ ├── implicit_conversion_error_to_bytes4_return_value.sol │ │ │ │ ├── implicit_conversion_event_to_bytes4_function_argument.sol │ │ │ │ ├── implicit_conversion_event_to_bytes4_return_value.sol │ │ │ │ ├── implicit_conversion_from_array_of_string_literals_to_calldata_string.sol │ │ │ │ ├── implicit_conversion_from_storage_array_ref.sol │ │ │ │ ├── implicit_conversion_from_string_literal_to_calldata_string.sol │ │ │ │ ├── implicit_conversion_from_string_literal_to_calldata_string_in_function_parameter.sol │ │ │ │ ├── implicit_conversion_of_super_in_comparison.sol │ │ │ │ ├── implicit_conversion_of_super_in_operators.sol │ │ │ │ ├── not_allowed_conversion_from_super.sol │ │ │ │ ├── not_allowed_conversion_to_int_array_pointer1.sol │ │ │ │ └── not_allowed_conversion_to_int_array_pointer2.sol │ │ │ ├── dataLocations/ │ │ │ │ ├── data_location_in_function_type.sol │ │ │ │ ├── data_location_in_function_type_fail.sol │ │ │ │ ├── externalFunction/ │ │ │ │ │ ├── external_function_return_parameters_no_data_location.sol │ │ │ │ │ ├── function_argument_location_specifier_test_external_calldata.sol │ │ │ │ │ ├── function_argument_location_specifier_test_external_memory.sol │ │ │ │ │ ├── function_argument_location_specifier_test_external_storage.sol │ │ │ │ │ └── function_argument_location_specifier_test_external_transient.sol │ │ │ │ ├── function_argument_location_specifier_test_non_reference_type.sol │ │ │ │ ├── function_parameters_with_data_location_fine.sol │ │ │ │ ├── function_return_parameters_with_data_location_fine.sol │ │ │ │ ├── function_type_array_as_reference_type.sol │ │ │ │ ├── internalFunction/ │ │ │ │ │ ├── function_argument_location_specifier_test_internal_calldata.sol │ │ │ │ │ ├── function_argument_location_specifier_test_internal_memory.sol │ │ │ │ │ ├── function_argument_location_specifier_test_internal_storage.sol │ │ │ │ │ ├── function_argument_location_specifier_test_internal_transient.sol │ │ │ │ │ ├── internal_function_parameters_no_data_location.sol │ │ │ │ │ └── internal_function_return_parameters_no_data_location.sol │ │ │ │ ├── libraries/ │ │ │ │ │ ├── library_external_function_params_no_data_location.sol │ │ │ │ │ ├── library_external_function_return_no_data_location.sol │ │ │ │ │ ├── library_function_with_data_location_fine.sol │ │ │ │ │ ├── library_function_with_data_location_transient.sol │ │ │ │ │ ├── library_internal_function_no_data_location.sol │ │ │ │ │ ├── library_private_function_no_data_location.sol │ │ │ │ │ └── library_public_function_no_data_location.sol │ │ │ │ ├── libraryExternalFunction/ │ │ │ │ │ ├── function_argument_location_specifier_test_external_calldata.sol │ │ │ │ │ ├── function_argument_location_specifier_test_external_memory.sol │ │ │ │ │ ├── function_argument_location_specifier_test_external_storage.sol │ │ │ │ │ └── function_argument_location_specifier_test_external_transient.sol │ │ │ │ ├── libraryInternalFunction/ │ │ │ │ │ ├── function_argument_location_specifier_test_internal_calldata.sol │ │ │ │ │ ├── function_argument_location_specifier_test_internal_memory.sol │ │ │ │ │ ├── function_argument_location_specifier_test_internal_storage.sol │ │ │ │ │ └── function_argument_location_specifier_test_internal_transient.sol │ │ │ │ ├── memory_storage_data_location.sol │ │ │ │ ├── multiple_transient_data_location_function_parameter.sol │ │ │ │ ├── privateFunction/ │ │ │ │ │ ├── private_function_parameters_location_transient.sol │ │ │ │ │ ├── private_function_parameters_no_data_location.sol │ │ │ │ │ ├── private_function_return_parameters_location_transient.sol │ │ │ │ │ └── private_function_return_parameters_no_data_location.sol │ │ │ │ ├── publicFunction/ │ │ │ │ │ ├── function_argument_location_specifier_test_public_calldata.sol │ │ │ │ │ ├── function_argument_location_specifier_test_public_memory.sol │ │ │ │ │ ├── function_argument_location_specifier_test_public_storage.sol │ │ │ │ │ ├── function_argument_location_specifier_test_public_transient.sol │ │ │ │ │ ├── public_function_parameters_no_data_location.sol │ │ │ │ │ ├── public_function_return_parameters_location_transient.sol │ │ │ │ │ └── public_function_return_parameters_no_data_location.sol │ │ │ │ ├── state_variable_storage_named_transient.sol │ │ │ │ ├── state_variable_storage_transient.sol │ │ │ │ ├── state_variable_transient_storage.sol │ │ │ │ ├── transient_dynamic_array_state_variable.sol │ │ │ │ ├── transient_fixed_array_state_variable.sol │ │ │ │ ├── transient_function_type.sol │ │ │ │ ├── transient_function_type_parameter.sol │ │ │ │ ├── transient_local_variable.sol │ │ │ │ ├── transient_mapping_state_variable.sol │ │ │ │ ├── transient_state_variable_visibility.sol │ │ │ │ ├── transient_storage_variable_pre_cancun.sol │ │ │ │ ├── transient_struct_state_variable.sol │ │ │ │ ├── transient_value_type_state_variables.sol │ │ │ │ ├── transient_value_type_state_variables_initialization.sol │ │ │ │ ├── unspecified_constructor.sol │ │ │ │ ├── variable_declaration_location_specifier_test_non_reference_type.sol │ │ │ │ └── variable_declaration_location_specifier_test_reference_type.sol │ │ │ ├── denominations/ │ │ │ │ ├── combining_hex_and_denomination.sol │ │ │ │ ├── denominations.sol │ │ │ │ ├── denominations_in_array_sizes.sol │ │ │ │ ├── deprecated_year.sol │ │ │ │ ├── finney_invalid.sol │ │ │ │ ├── fixed_point_division.sol │ │ │ │ ├── gwei_as_identifier.sol │ │ │ │ ├── invalid_denomination_address.sol │ │ │ │ ├── invalid_denomination_no_whitespace.sol │ │ │ │ ├── invalid_denomination_on_bool.sol │ │ │ │ ├── invalid_denomination_on_string.sol │ │ │ │ ├── szabo_finney_identifiers.sol │ │ │ │ ├── szabo_invalid.sol │ │ │ │ └── two_denominations_same_literal.sol │ │ │ ├── duplicateFunctions/ │ │ │ │ ├── fallback_function_twice.sol │ │ │ │ ├── illegal_names_exception.sol │ │ │ │ ├── illegal_names_functions.sol │ │ │ │ └── receive_function_thrice.sol │ │ │ ├── emit/ │ │ │ │ ├── emit_empty.sol │ │ │ │ └── emit_non_event.sol │ │ │ ├── enums/ │ │ │ │ ├── enum_member_shadowing.sol │ │ │ │ ├── enum_with_too_many_members.sol │ │ │ │ ├── global_enum.sol │ │ │ │ ├── global_enum_contract_name_clash.sol │ │ │ │ ├── global_enum_name_clash.sol │ │ │ │ ├── global_enum_shadowing.sol │ │ │ │ ├── illegal_names.sol │ │ │ │ ├── literal_conversion.sol │ │ │ │ └── literal_conversion_error.sol │ │ │ ├── errors/ │ │ │ │ ├── abi_decode_error.sol │ │ │ │ ├── abi_decode_error_constructor.sol │ │ │ │ ├── abi_encode_error.sol │ │ │ │ ├── abi_encode_error_constructor.sol │ │ │ │ ├── abi_encode_error_instance.sol │ │ │ │ ├── all_ones_signature.sol │ │ │ │ ├── anonymous.sol │ │ │ │ ├── assert_with_cond_and_error.sol │ │ │ │ ├── assert_with_error.sol │ │ │ │ ├── basic.sol │ │ │ │ ├── bytes_concat_on_error_type_info.sol │ │ │ │ ├── clash_function_error.sol │ │ │ │ ├── clash_function_error_inheritance.sol │ │ │ │ ├── clash_function_error_inheritance_2.sol │ │ │ │ ├── duplicate.sol │ │ │ │ ├── elementary_non_address_state_mutability_error_argument.sol │ │ │ │ ├── error_abi_decode.sol │ │ │ │ ├── error_address_payable.sol │ │ │ │ ├── error_as_function_param.sol │ │ │ │ ├── error_bytes_concat_wrong_type.sol │ │ │ │ ├── error_encodecall_fail_args.sol │ │ │ │ ├── error_in_interface.sol │ │ │ │ ├── error_in_library.sol │ │ │ │ ├── error_incompatible_binary_ops.sol │ │ │ │ ├── error_incompatible_operator_for_type.sol │ │ │ │ ├── error_incompatible_unary_operator.sol │ │ │ │ ├── error_invalid_function_modifier_type.sol │ │ │ │ ├── error_location_memory.sol │ │ │ │ ├── error_location_specifier.sol │ │ │ │ ├── error_param_type_shadowed_by_builtin_type_used_as_param_name.sol │ │ │ │ ├── error_param_type_shadowed_by_param_name.sol │ │ │ │ ├── error_reserved_name.sol │ │ │ │ ├── error_return_tuple_not_convertible.sol │ │ │ │ ├── error_selector_syntax.sol │ │ │ │ ├── error_ternary_operator.sol │ │ │ │ ├── error_to_function_conversion.sol │ │ │ │ ├── error_variable_declaration_implicit_conversion.sol │ │ │ │ ├── error_wrong_type_base_arg.sol │ │ │ │ ├── file_level.sol │ │ │ │ ├── hash_collision.sol │ │ │ │ ├── hash_collision_external.sol │ │ │ │ ├── indexed_error.sol │ │ │ │ ├── internal_type.sol │ │ │ │ ├── invalid_parameter_indexed.sol │ │ │ │ ├── invalid_parameter_location.sol │ │ │ │ ├── invalid_parameter_mutability.sol │ │ │ │ ├── invalid_parameter_visibility.sol │ │ │ │ ├── no_mappings.sol │ │ │ │ ├── no_overloading.sol │ │ │ │ ├── no_overloading_inheritance.sol │ │ │ │ ├── no_structs_in_abiv1.sol │ │ │ │ ├── panic_reserved_name.sol │ │ │ │ ├── require_custom.sol │ │ │ │ ├── require_nested.sol │ │ │ │ ├── revert_parentheses.sol │ │ │ │ ├── selector.sol │ │ │ │ ├── selector_on_instance.sol │ │ │ │ ├── struct_named_error.sol │ │ │ │ ├── unreachable.sol │ │ │ │ ├── using.sol │ │ │ │ ├── using_2.sol │ │ │ │ ├── using_structs.sol │ │ │ │ ├── weird3.sol │ │ │ │ ├── weird4.sol │ │ │ │ └── zero_signature.sol │ │ │ ├── events/ │ │ │ │ ├── anonymous_event_four_indexed.sol │ │ │ │ ├── anonymous_event_multiple_anonymous_specifiers.sol │ │ │ │ ├── anonymous_event_too_many_indexed.sol │ │ │ │ ├── bytes_concat_on_event_type_info.sol │ │ │ │ ├── double_event_declaration.sol │ │ │ │ ├── double_event_declaration_ignores_anonymous.sol │ │ │ │ ├── double_event_declaration_ignores_indexed.sol │ │ │ │ ├── elementary_non_address_state_mutability_event_argument.sol │ │ │ │ ├── event.sol │ │ │ │ ├── event_abi_decode.sol │ │ │ │ ├── event_array_indexed_v2.sol │ │ │ │ ├── event_array_v2.sol │ │ │ │ ├── event_bytes_concat_wrong_type.sol │ │ │ │ ├── event_call.sol │ │ │ │ ├── event_emit_complex.sol │ │ │ │ ├── event_emit_foreign_class.sol │ │ │ │ ├── event_emit_qualified_file_level.sol │ │ │ │ ├── event_emit_simple.sol │ │ │ │ ├── event_emit_simple_file_level.sol │ │ │ │ ├── event_encodecall_fail_args.sol │ │ │ │ ├── event_function_inheritance_clash.sol │ │ │ │ ├── event_function_type_indexed.sol │ │ │ │ ├── event_incompatible_binary_ops.sol │ │ │ │ ├── event_incompatible_operator_for_type.sol │ │ │ │ ├── event_incompatible_unary_operator.sol │ │ │ │ ├── event_inheritance.sol │ │ │ │ ├── event_invalid_function_modifier_type.sol │ │ │ │ ├── event_library_function.sol │ │ │ │ ├── event_multiple_indexed_of_one_parameter.sol │ │ │ │ ├── event_named_arguments_in_any_order.sol │ │ │ │ ├── event_nested_array.sol │ │ │ │ ├── event_nested_array_2.sol │ │ │ │ ├── event_nested_array_in_struct.sol │ │ │ │ ├── event_nested_array_indexed_v2.sol │ │ │ │ ├── event_nested_array_v2.sol │ │ │ │ ├── event_overload_named_arguments_ambiguous.sol │ │ │ │ ├── event_overload_named_arguments_ambiguous_implicit_conversion.sol │ │ │ │ ├── event_overload_named_arguments_in_any_order.sol │ │ │ │ ├── event_overload_named_arguments_wrong_types.sol │ │ │ │ ├── event_param_type_outside_storage.sol │ │ │ │ ├── event_param_type_shadowed_by_param_name.sol │ │ │ │ ├── event_return_tuple_not_convertible.sol │ │ │ │ ├── event_selector_access_file_level.sol │ │ │ │ ├── event_selector_access_foreign_contract.sol │ │ │ │ ├── event_selector_access_interface.sol │ │ │ │ ├── event_selector_access_library.sol │ │ │ │ ├── event_selector_library_called_inside_function.sol │ │ │ │ ├── event_selector_library_declared_outside_but_called_inside_function.sol │ │ │ │ ├── event_selector_syntax.sol │ │ │ │ ├── event_struct.sol │ │ │ │ ├── event_struct_indexed.sol │ │ │ │ ├── event_struct_indexed_v2.sol │ │ │ │ ├── event_struct_v2.sol │ │ │ │ ├── event_ternary_operator.sol │ │ │ │ ├── event_to_function_conversion.sol │ │ │ │ ├── event_too_many_indexed.sol │ │ │ │ ├── event_variable_declaration_implicit_conversion.sol │ │ │ │ ├── event_without_emit_deprecated.sol │ │ │ │ ├── event_wrong_type_base_arg.sol │ │ │ │ ├── events_with_same_name.sol │ │ │ │ ├── events_with_same_name_different_types.sol │ │ │ │ ├── events_with_same_name_unnamed_arguments.sol │ │ │ │ ├── file_level_event.sol │ │ │ │ ├── file_level_event_duplicate_definition.sol │ │ │ │ ├── file_level_event_duplicate_definition_via_import.sol │ │ │ │ ├── file_level_event_import.sol │ │ │ │ ├── file_level_event_overloading.sol │ │ │ │ ├── file_level_event_overloading_vs_shadowing.sol │ │ │ │ ├── file_level_event_shadowed_inside_contract.sol │ │ │ │ ├── file_level_event_shadowed_inside_contract_adds_anonymous.sol │ │ │ │ ├── file_level_event_shadowing_contract.sol │ │ │ │ ├── file_level_event_shadowing_error.sol │ │ │ │ ├── file_level_event_using.sol │ │ │ │ ├── function_event_in_contract_clash.sol │ │ │ │ ├── function_event_inheritance_clash.sol │ │ │ │ ├── illegal_names_exception.sol │ │ │ │ ├── illegal_names_exception_file_level.sol │ │ │ │ ├── inheritance_adds_anonymous.sol │ │ │ │ ├── inheritance_adds_indexed.sol │ │ │ │ ├── inheritance_adds_parameter.sol │ │ │ │ ├── inheritance_event_repeated.sol │ │ │ │ ├── inheritance_multi_parent.sol │ │ │ │ ├── inheritance_removes_indexed.sol │ │ │ │ ├── internal_type.sol │ │ │ │ ├── invalid_parameter_location.sol │ │ │ │ ├── invalid_parameter_mutability.sol │ │ │ │ ├── invalid_parameter_visibility.sol │ │ │ │ ├── multiple_event_without_emit.sol │ │ │ │ ├── multiple_events_argument_clash.sol │ │ │ │ ├── multiple_inheritance.sol │ │ │ │ ├── overloading_in_contract.sol │ │ │ │ └── transient_indexed_parameter.sol │ │ │ ├── experimental/ │ │ │ │ ├── builtin/ │ │ │ │ │ ├── builtin_type_definition.sol │ │ │ │ │ ├── builtin_type_definition_duplicate.sol │ │ │ │ │ └── builtin_type_definition_unknown.sol │ │ │ │ ├── forall/ │ │ │ │ │ ├── undeclared_type_variable_in_function.sol │ │ │ │ │ ├── undeclared_type_variable_in_quantified_function.sol │ │ │ │ │ └── undeclared_type_variable_in_type_class.sol │ │ │ │ ├── import/ │ │ │ │ │ ├── experimental_solidity.sol │ │ │ │ │ ├── experimental_solidity_multisource_not_all_enable.sol │ │ │ │ │ ├── experimental_solidity_out_of_order_1.sol │ │ │ │ │ ├── experimental_solidity_out_of_order_2.sol │ │ │ │ │ ├── experimental_solidity_wrong_evm_version.sol │ │ │ │ │ ├── parsing_stdlib_import_1.sol │ │ │ │ │ ├── parsing_stdlib_import_2.sol │ │ │ │ │ ├── parsing_stdlib_import_3.sol │ │ │ │ │ ├── parsing_stdlib_import_4.sol │ │ │ │ │ ├── parsing_stdlib_import_without_pragma_1.sol │ │ │ │ │ └── parsing_stdlib_import_without_pragma_2.sol │ │ │ │ ├── inference/ │ │ │ │ │ ├── experimental_keywords.sol │ │ │ │ │ ├── import_and_call_stdlib_function.sol │ │ │ │ │ ├── instantiation_invalid_type_constructor.sol │ │ │ │ │ ├── instantiation_member_type_does_not_match_declaration.sol │ │ │ │ │ ├── instantiation_not_for_class.sol │ │ │ │ │ ├── invalid_type_referenced.sol │ │ │ │ │ ├── monomorphic_function_call_type_mismatch.sol │ │ │ │ │ ├── polymorphic_function_call.sol │ │ │ │ │ ├── polymorphic_function_call_let_polymorphism.sol │ │ │ │ │ ├── polymorphic_function_call_type_mismatch.sol │ │ │ │ │ ├── polymorphic_type.sol │ │ │ │ │ ├── polymorphic_type_abs_and_rep.sol │ │ │ │ │ ├── polymorphic_type_instantiation_and_operators.sol │ │ │ │ │ ├── type_variable_multi_use_function_parameter_and_return.sol │ │ │ │ │ └── type_variable_multi_use_function_parameters.sol │ │ │ │ └── parsing/ │ │ │ │ ├── forall_free_function.sol │ │ │ │ ├── forall_free_function_no_type_var.sol │ │ │ │ ├── forall_free_function_with_sorts.sol │ │ │ │ ├── forall_type_class.sol │ │ │ │ └── forall_type_class_instantiation.sol │ │ │ ├── fallback/ │ │ │ │ ├── arguments.sol │ │ │ │ ├── default_visibility.sol │ │ │ │ ├── fallback_as_function_name.sol │ │ │ │ ├── fallback_duplicate_returns.sol │ │ │ │ ├── fallback_duplicate_returns_inheritance.sol │ │ │ │ ├── fallback_duplicate_returns_override.sol │ │ │ │ ├── fallback_wrong_data_location.sol │ │ │ │ ├── inheritance_multi_base.sol │ │ │ │ ├── no_input_no_output.sol │ │ │ │ ├── old_syntax.sol │ │ │ │ ├── payable_fallback_with_inherited_receive.sol │ │ │ │ ├── payable_fallback_without_receive_empty.sol │ │ │ │ ├── payable_fallback_without_receive_nonempty.sol │ │ │ │ ├── payable_fallback_without_receive_nonempty_by_inheritance.sol │ │ │ │ ├── payable_fallback_without_receive_only_internal.sol │ │ │ │ ├── pure_modifier.sol │ │ │ │ ├── return_value_number.sol │ │ │ │ ├── return_value_type.sol │ │ │ │ ├── return_value_unsupported.sol │ │ │ │ ├── returns.sol │ │ │ │ └── view_modifier.sol │ │ │ ├── freeFunctions/ │ │ │ │ ├── circular_reference1functions_first.sol │ │ │ │ ├── circular_referencecontracts_first.sol │ │ │ │ ├── free_call_via_contract_type.sol │ │ │ │ ├── free_constructor.sol │ │ │ │ ├── free_different_integer_types.sol │ │ │ │ ├── free_fallback.sol │ │ │ │ ├── free_function_modifier.sol │ │ │ │ ├── free_function_namesake_different_parameter_types.sol │ │ │ │ ├── free_function_qualified_modifier.sol │ │ │ │ ├── free_function_shadowing.sol │ │ │ │ ├── free_function_visibility.sol │ │ │ │ ├── free_function_without_body.sol │ │ │ │ ├── free_functions.sol │ │ │ │ ├── free_identical.sol │ │ │ │ ├── free_identical_multiple.sol │ │ │ │ ├── free_mutability.sol │ │ │ │ ├── free_namesake_contract_function.sol │ │ │ │ ├── free_overload.sol │ │ │ │ ├── free_override.sol │ │ │ │ ├── free_payable.sol │ │ │ │ ├── free_receive.sol │ │ │ │ ├── free_redefinition.sol │ │ │ │ ├── free_storage.sol │ │ │ │ ├── free_virtual.sol │ │ │ │ ├── function_same_name_as_contract.sol │ │ │ │ ├── function_using_struct_after_contract.sol │ │ │ │ ├── gas_value.sol │ │ │ │ ├── illegal_names.sol │ │ │ │ ├── invalid_function_named_unicode.sol │ │ │ │ ├── named_fallback_warning.sol │ │ │ │ ├── named_receive_warning.sol │ │ │ │ ├── qualified_struct_access.sol │ │ │ │ ├── struct_after_function.sol │ │ │ │ ├── super_in_free_function.sol │ │ │ │ └── this_in_free_function.sol │ │ │ ├── functionCalls/ │ │ │ │ ├── arbitrary_parameters_but_restricted_first_type.sol │ │ │ │ ├── call_unimplemented_base.sol │ │ │ │ ├── call_unimplemented_base_via_super.sol │ │ │ │ ├── calldata_struct_argument_with_internal_data_type_inside.sol │ │ │ │ ├── calldata_struct_array_argument_with_internal_data_type_inside.sol │ │ │ │ ├── calldata_struct_array_argument_with_internal_data_type_inside_as_constructor_parameter.sol │ │ │ │ ├── calloptions_duplicated.sol │ │ │ │ ├── calloptions_on_delegatecall.sol │ │ │ │ ├── calloptions_on_internal_function.sol │ │ │ │ ├── calloptions_on_staticcall.sol │ │ │ │ ├── calloptions_repeated.sol │ │ │ │ ├── empty_call_options.sol │ │ │ │ ├── enum_value_not_callable.sol │ │ │ │ ├── eof/ │ │ │ │ │ ├── calloptions_on_delegatecall.sol │ │ │ │ │ ├── calloptions_on_staticcall.sol │ │ │ │ │ ├── external_call_with_gas_option.sol │ │ │ │ │ └── lowlevel_call_options.sol │ │ │ │ ├── int_not_callable.sol │ │ │ │ ├── invalid_expressions_with_calloptions1.sol │ │ │ │ ├── invalid_expressions_with_calloptions2.sol │ │ │ │ ├── invalid_expressions_with_calloptions3.sol │ │ │ │ ├── invalid_named_arguments_conditional.sol │ │ │ │ ├── lowlevel_call_options.sol │ │ │ │ ├── magic_not_callable.sol │ │ │ │ ├── mapping_not_callable.sol │ │ │ │ ├── modifier_not_callable.sol │ │ │ │ ├── module_not_callable.sol │ │ │ │ ├── msg_value_non_payable.sol │ │ │ │ ├── named_arguments_duplicate_parameter.sol │ │ │ │ ├── named_arguments_empty.sol │ │ │ │ ├── named_arguments_for_functions_that_take_arbitrary_parameters.sol │ │ │ │ ├── named_arguments_in_any_order.sol │ │ │ │ ├── named_arguments_invalid_name.sol │ │ │ │ ├── named_arguments_overload.sol │ │ │ │ ├── named_arguments_overload_failing1.sol │ │ │ │ ├── named_arguments_overload_failing2.sol │ │ │ │ ├── named_arguments_overload_failing3.sol │ │ │ │ ├── named_arguments_overload_failing_ambiguous.sol │ │ │ │ ├── named_arguments_overload_failing_ambiguous_implicit_conversion.sol │ │ │ │ ├── named_arguments_overload_failing_right_names_wrong_order.sol │ │ │ │ ├── named_arguments_overload_failing_wrong_names.sol │ │ │ │ ├── named_arguments_overload_in_any_order.sol │ │ │ │ ├── named_arguments_wrong_count.sol │ │ │ │ ├── new_library.sol │ │ │ │ ├── new_with_calloptions.sol │ │ │ │ ├── new_with_calloptions_unsupported.sol │ │ │ │ ├── new_with_invalid_calloptions.sol │ │ │ │ ├── staticcall_on_homestead.sol │ │ │ │ └── this_not_callable.sol │ │ │ ├── functionTypes/ │ │ │ │ ├── assign_attached_library_function.sol │ │ │ │ ├── assign_attached_library_function_storage_arg.sol │ │ │ │ ├── assign_builtin.sol │ │ │ │ ├── call_gas_on_function.sol │ │ │ │ ├── call_value_library_function.sol │ │ │ │ ├── call_value_on_non_constructor.sol │ │ │ │ ├── call_value_on_non_payable_function_type.sol │ │ │ │ ├── call_value_on_payable_function_type.sol │ │ │ │ ├── call_value_options_on_non_payable_function_type.sol │ │ │ │ ├── comparison_of_function_types_external_eq.sol │ │ │ │ ├── comparison_of_function_types_gt_1.sol │ │ │ │ ├── comparison_of_function_types_gt_2.sol │ │ │ │ ├── comparison_of_function_types_internal_eq_1.sol │ │ │ │ ├── comparison_of_function_types_internal_eq_2.sol │ │ │ │ ├── comparison_of_function_types_lt_1.sol │ │ │ │ ├── comparison_of_function_types_lt_2.sol │ │ │ │ ├── comparison_operator_for_external_functions_with_call_options.sol │ │ │ │ ├── comparison_operators_between_internal_and_external_function_pointers.sol │ │ │ │ ├── comparison_operators_external_functions_with_different_parameters.sol │ │ │ │ ├── conversion_to_address.sol │ │ │ │ ├── declaration_type_conversion.sol │ │ │ │ ├── declaration_type_conversion_internal_base.sol │ │ │ │ ├── delete_external_function_type_invalid.sol │ │ │ │ ├── delete_function_type.sol │ │ │ │ ├── delete_function_type_invalid.sol │ │ │ │ ├── eof/ │ │ │ │ │ └── call_gas_on_function.sol │ │ │ │ ├── error_deprecate_gas_function.sol │ │ │ │ ├── error_deprecate_value_constructor.sol │ │ │ │ ├── error_deprecate_value_constructor_nonpayable.sol │ │ │ │ ├── error_deprecate_value_function.sol │ │ │ │ ├── external_function_to_function_type_calldata_parameter.sol │ │ │ │ ├── external_function_type_public_variable.sol │ │ │ │ ├── external_function_type_returning_internal.sol │ │ │ │ ├── external_function_type_taking_internal.sol │ │ │ │ ├── external_function_type_to_address.sol │ │ │ │ ├── external_function_type_to_address_payable.sol │ │ │ │ ├── external_function_type_to_uint.sol │ │ │ │ ├── external_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol │ │ │ │ ├── external_functions_with_calldata_args_assigned_to_function_pointers_with_memory_type.sol │ │ │ │ ├── external_functions_with_variable_number_of_stack_slots.sol │ │ │ │ ├── external_library_function_to_external_function_type.sol │ │ │ │ ├── from_ternary_expression.sol │ │ │ │ ├── function_parameter_allowed_conversions.sol │ │ │ │ ├── function_type.sol │ │ │ │ ├── function_type_arrays.sol │ │ │ │ ├── function_type_constructor.sol │ │ │ │ ├── function_type_constructor_local.sol │ │ │ │ ├── function_type_internal_public_variable.sol │ │ │ │ ├── function_type_named_call.sol │ │ │ │ ├── function_type_parameter.sol │ │ │ │ ├── function_type_return_parameters_with_names.sol │ │ │ │ ├── function_type_returned.sol │ │ │ │ ├── function_type_struct.sol │ │ │ │ ├── function_type_struct_undefined_member.sol │ │ │ │ ├── function_type_variable_external_internal.sol │ │ │ │ ├── function_type_with_transient_param.sol │ │ │ │ ├── function_types_internal_visibility_error.sol │ │ │ │ ├── function_types_variable_visibility.sol │ │ │ │ ├── inline_array_with_attached_function.sol │ │ │ │ ├── inline_array_with_attached_function_mixed.sol │ │ │ │ ├── inline_array_with_payable_function.sol │ │ │ │ ├── internal_function_array_memory_as_external_parameter_in_library_external.sol │ │ │ │ ├── internal_function_array_storage_as_external_parameter_in_library_external.sol │ │ │ │ ├── internal_function_as_external_parameter.sol │ │ │ │ ├── internal_function_as_external_parameter_in_library_external.sol │ │ │ │ ├── internal_function_as_external_parameter_in_library_internal.sol │ │ │ │ ├── internal_function_returned_from_public_function.sol │ │ │ │ ├── internal_function_struct_as_external_parameter_in_library_external.sol │ │ │ │ ├── internal_function_type_to_address.sol │ │ │ │ ├── internal_functions_with_calldata_args_assigned_to_function_pointers_of_same_type.sol │ │ │ │ ├── payable_internal_function_type.sol │ │ │ │ ├── payable_internal_function_type_is_not_fatal.sol │ │ │ │ ├── private_function_type.sol │ │ │ │ ├── public_function_type.sol │ │ │ │ ├── selector_ternary_contract_external_function.sol │ │ │ │ ├── selector_ternary_different_contract_public_function.sol │ │ │ │ ├── selector_ternary_different_contracts_external_function.sol │ │ │ │ ├── selector_ternary_different_interface_external_function.sol │ │ │ │ ├── selectors.sol │ │ │ │ ├── ternary_contract_delegate_function.sol │ │ │ │ ├── ternary_with_attached_functions.sol │ │ │ │ ├── transient_function_type_with_param_named_transient.sol │ │ │ │ ├── transient_function_type_with_transient_param.sol │ │ │ │ ├── valid_function_type_variables.sol │ │ │ │ └── warn_function_type_parameters_with_names.sol │ │ │ ├── getter/ │ │ │ │ ├── complex_struct.sol │ │ │ │ ├── nested_structs.sol │ │ │ │ ├── recursive_struct.sol │ │ │ │ └── simple_struct.sol │ │ │ ├── globalFunctions/ │ │ │ │ ├── blobhash_function_pre_cancun.sol │ │ │ │ ├── blobhash_function_shadow_warning.sol │ │ │ │ ├── blobhash_no_call.sol │ │ │ │ ├── blobhash_not_declared_pre_cancun.sol │ │ │ │ ├── blobhash_var_pre_cancun.sol │ │ │ │ ├── blobhash_var_shadow_warning.sol │ │ │ │ ├── call_with_wrong_arg_count.sol │ │ │ │ ├── callcode_with_wrong_arg_count.sol │ │ │ │ ├── delegatecall_with_wrong_arg_count.sol │ │ │ │ ├── deprecated_functions.sol │ │ │ │ ├── erc7201_builtin_abi_encode_comptime.sol │ │ │ │ ├── erc7201_builtin_function_pointer_assignment.sol │ │ │ │ ├── erc7201_builtin_function_shadow_warning.sol │ │ │ │ ├── erc7201_builtin_invalid_gas_function_option.sol │ │ │ │ ├── erc7201_builtin_no_call.sol │ │ │ │ ├── erc7201_builtin_overflow_expression_comptime.sol │ │ │ │ ├── erc7201_builtin_param_bytes_converted_to_string.sol │ │ │ │ ├── erc7201_builtin_param_constant_string_unitary_tuple.sol │ │ │ │ ├── erc7201_builtin_param_invalid_bytes.sol │ │ │ │ ├── erc7201_builtin_param_invalid_hex_literal.sol │ │ │ │ ├── erc7201_builtin_param_invalid_number_literal.sol │ │ │ │ ├── erc7201_builtin_param_named.sol │ │ │ │ ├── erc7201_builtin_param_string_unitary_tuple_comptime.sol │ │ │ │ ├── erc7201_builtin_param_string_var_with_escaped_chars_comptime.sol │ │ │ │ ├── erc7201_builtin_param_string_variable.sol │ │ │ │ ├── erc7201_builtin_param_string_variable_comptime.sol │ │ │ │ ├── erc7201_builtin_param_string_with_whitespaces_comptime.sol │ │ │ │ ├── erc7201_builtin_param_unicode_literal.sol │ │ │ │ ├── erc7201_builtin_param_wrong_count.sol │ │ │ │ ├── erc7201_builtin_variable_name_shadow_warning.sol │ │ │ │ ├── keccak256_with_wrong_arg_count.sol │ │ │ │ ├── log_deprecate.sol │ │ │ │ ├── now_deprecate.sol │ │ │ │ ├── now_override.sol │ │ │ │ ├── ripemd160_with_wrong_arg_count.sol │ │ │ │ ├── selfdestruct_no_call.sol │ │ │ │ ├── sha256_with_wrong_arg_count.sol │ │ │ │ ├── sha3_no_call.sol │ │ │ │ ├── sha3_override.sol │ │ │ │ ├── sha3_var.sol │ │ │ │ ├── suicide_no_call.sol │ │ │ │ ├── suicide_override.sol │ │ │ │ └── suicide_var.sol │ │ │ ├── iceRegressionTests/ │ │ │ │ ├── calling_external_function_via_local_variable_with_invalid_type.sol │ │ │ │ ├── calling_external_function_via_parameter_with_invalid_type.sol │ │ │ │ ├── const_struct_with_mapping.sol │ │ │ │ ├── cycle_checker_function_type.sol │ │ │ │ ├── declarationUnaryTuple/ │ │ │ │ │ ├── declaration_bitnot_tuple.sol │ │ │ │ │ ├── declaration_dec_tuple.sol │ │ │ │ │ ├── declaration_delete_tuple.sol │ │ │ │ │ ├── declaration_inc_tuple.sol │ │ │ │ │ ├── declaration_unary_plus_tuple.sol │ │ │ │ │ ├── declaration_unary_plus_tuple_compound_assign.sol │ │ │ │ │ └── declaration_unary_tuple.sol │ │ │ │ ├── identifier_collision_return_declare.sol │ │ │ │ ├── large_array_in_memory_struct.sol │ │ │ │ ├── large_array_in_memory_struct_2.sol │ │ │ │ ├── large_struct_array.sol │ │ │ │ ├── memory_mapping_array.sol │ │ │ │ ├── missing_functions_duplicate_bug.sol │ │ │ │ ├── oversized_var.sol │ │ │ │ └── recursive_struct_memory.sol │ │ │ ├── immutable/ │ │ │ │ ├── access_via_getter.sol │ │ │ │ ├── as_function_param.sol │ │ │ │ ├── assembly.sol │ │ │ │ ├── base_ctor_return_no_immutables.sol │ │ │ │ ├── complex.sol │ │ │ │ ├── conditional_return_uninitialized.sol │ │ │ │ ├── conditionally_initialized.sol │ │ │ │ ├── creationCode.sol │ │ │ │ ├── ctor_indirect_initialization.sol │ │ │ │ ├── ctor_initialization_indirect_reading.sol │ │ │ │ ├── ctor_initialization_reading.sol │ │ │ │ ├── ctor_initialization_tuple.sol │ │ │ │ ├── ctor_modifier_args.sol │ │ │ │ ├── ctor_modifier_initialization.sol │ │ │ │ ├── ctor_modifier_reading.sol │ │ │ │ ├── decrement.sol │ │ │ │ ├── double_specifier.sol │ │ │ │ ├── external_function_pointer.sol │ │ │ │ ├── function_initialization.sol │ │ │ │ ├── function_initialization_reading.sol │ │ │ │ ├── function_pointer_initializing.sol │ │ │ │ ├── function_pointer_reading.sol │ │ │ │ ├── illegal_names.sol │ │ │ │ ├── immutable_basic.sol │ │ │ │ ├── immutable_state_var_named_transient.sol │ │ │ │ ├── increment.sol │ │ │ │ ├── indirect_reading_during_statevar_init.sol │ │ │ │ ├── inheritance_ctor.sol │ │ │ │ ├── inheritance_ctor_argument.sol │ │ │ │ ├── inheritance_ctor_inherit_specifier_argument_init.sol │ │ │ │ ├── inheritance_ctor_inherit_specifier_argument_reading.sol │ │ │ │ ├── inheritance_virtual_functions.sol │ │ │ │ ├── inheritance_virtual_functions_direct_call.sol │ │ │ │ ├── inheritance_virtual_functions_super.sol │ │ │ │ ├── inheritance_virtual_modifiers.sol │ │ │ │ ├── inheritance_wrong_ctor.sol │ │ │ │ ├── init_in_constructor_modifier_param.sol │ │ │ │ ├── init_in_ctor_param.sol │ │ │ │ ├── init_in_function_modifier_param.sol │ │ │ │ ├── init_in_function_via_contract_name.sol │ │ │ │ ├── init_in_function_via_super.sol │ │ │ │ ├── init_in_inheritance_specifier_param.sol │ │ │ │ ├── initialized_after_ctor.sol │ │ │ │ ├── long_name.sol │ │ │ │ ├── loop_initialized.sol │ │ │ │ ├── multiple_inheritance_virtual_functions.sol │ │ │ │ ├── multiple_inheritance_virtual_functions_with_super.sol │ │ │ │ ├── multiple_initializations.sol │ │ │ │ ├── no_assignments.sol │ │ │ │ ├── non-value_type.sol │ │ │ │ ├── non-value_type_struct.sol │ │ │ │ ├── non-value_type_struct_with_mapping.sol │ │ │ │ ├── private_state_var.sol │ │ │ │ ├── read_in_function_before_init.sol │ │ │ │ ├── read_in_function_before_init2.sol │ │ │ │ ├── reading_after_initialization.sol │ │ │ │ ├── reading_after_initialization_function.sol │ │ │ │ ├── reading_after_initialization_modifier.sol │ │ │ │ ├── reading_during_statevar_init.sol │ │ │ │ ├── return_uninitialized.sol │ │ │ │ ├── runtimeCode.sol │ │ │ │ ├── runtimeCodeInheritance.sol │ │ │ │ ├── selector.sol │ │ │ │ ├── selector_function_name.sol │ │ │ │ ├── selector_function_pointer.sol │ │ │ │ ├── state_var_external_access_read.sol │ │ │ │ ├── state_var_external_access_write.sol │ │ │ │ ├── state_var_transient_data_location.sol │ │ │ │ ├── try_catch_initialized.sol │ │ │ │ ├── unary.sol │ │ │ │ ├── uninitialized.sol │ │ │ │ ├── uninitialized_private_state_var.sol │ │ │ │ ├── unrelated_reading.sol │ │ │ │ ├── variable_declaration_already.sol │ │ │ │ ├── variable_declaration_value.sol │ │ │ │ ├── writing_after_initialization.sol │ │ │ │ └── writing_after_initialization_modifier.sol │ │ │ ├── imports/ │ │ │ │ ├── alias_import_not_forwarded.sol │ │ │ │ ├── circular_import.sol │ │ │ │ ├── complex_import.sol │ │ │ │ ├── declaration_not_found.sol │ │ │ │ ├── filename_with_period.sol │ │ │ │ ├── import_access_struct.sol │ │ │ │ ├── import_does_not_clutter_importee.sol │ │ │ │ ├── import_is_transitive.sol │ │ │ │ ├── importing_free_functions.sol │ │ │ │ ├── inheritance_abi_encoder_match.sol │ │ │ │ ├── inheritance_abi_encoder_mismatch_1.sol │ │ │ │ ├── inheritance_abi_encoder_mismatch_2.sol │ │ │ │ ├── library_name_clash.sol │ │ │ │ ├── library_name_clash_with_contract.sol │ │ │ │ ├── module_function_from_ternary_expression.sol │ │ │ │ ├── multiple_non_existent_file_names.sol │ │ │ │ ├── name_clash_in_import_1.sol │ │ │ │ ├── name_clash_in_import_2.sol │ │ │ │ ├── name_clash_in_import_3.sol │ │ │ │ ├── name_clash_in_import_4.sol │ │ │ │ ├── name_clash_in_import_5.sol │ │ │ │ ├── name_clash_in_import_contract_struct_1.sol │ │ │ │ ├── name_clash_in_import_contract_struct_2.sol │ │ │ │ ├── name_clash_in_import_contract_struct_3.sol │ │ │ │ ├── name_clash_in_import_contract_struct_4.sol │ │ │ │ ├── name_clash_in_import_contract_struct_5.sol │ │ │ │ ├── name_clash_in_import_enum.sol │ │ │ │ ├── name_clash_in_import_enum_contract.sol │ │ │ │ ├── name_clash_in_import_enum_struct.sol │ │ │ │ ├── name_clash_in_import_struct_1.sol │ │ │ │ ├── name_clash_in_import_struct_2.sol │ │ │ │ ├── name_clash_in_import_struct_3.sol │ │ │ │ ├── name_clash_in_import_struct_4.sol │ │ │ │ ├── name_clash_in_import_struct_5.sol │ │ │ │ ├── name_clash_in_import_struct_contract_1.sol │ │ │ │ ├── name_clash_in_import_struct_contract_2.sol │ │ │ │ ├── name_clash_in_import_struct_contract_3.sol │ │ │ │ ├── name_clash_in_import_struct_contract_4.sol │ │ │ │ ├── name_clash_in_import_struct_contract_5.sol │ │ │ │ ├── regular_import.sol │ │ │ │ ├── relative_import.sol │ │ │ │ ├── relative_import_multiplex.sol │ │ │ │ ├── shadowing_builtins_with_alias.sol │ │ │ │ ├── shadowing_builtins_with_imports.sol │ │ │ │ ├── shadowing_builtins_with_multiple_imports.sol │ │ │ │ ├── shadowing_via_import.sol │ │ │ │ ├── simple_alias.sol │ │ │ │ ├── smoke_test.sol │ │ │ │ └── transitive.sol │ │ │ ├── indexing/ │ │ │ │ ├── array_multidim_rational.sol │ │ │ │ ├── array_multim_overflow_index.sol │ │ │ │ ├── array_negative_index.sol │ │ │ │ ├── array_noninteger_index.sol │ │ │ │ ├── array_out_of_bounds_index.sol │ │ │ │ ├── array_without_index.sol │ │ │ │ ├── error_type_without_index.sol │ │ │ │ ├── event_type_without_index.sol │ │ │ │ ├── fixedbytes_negative_index.sol │ │ │ │ ├── fixedbytes_noninteger_index.sol │ │ │ │ ├── fixedbytes_out_of_bounds_index.sol │ │ │ │ ├── fixedbytes_without_index.sol │ │ │ │ ├── function_type.sol │ │ │ │ ├── function_type_without_index.sol │ │ │ │ ├── index_range_access_assert.sol │ │ │ │ └── struct_array_noninteger_index.sol │ │ │ ├── inheritance/ │ │ │ │ ├── allow_empty_duplicated_super_constructor_call.sol │ │ │ │ ├── base_arguments_empty_parentheses.sol │ │ │ │ ├── base_arguments_multiple_inheritance.sol │ │ │ │ ├── base_arguments_no_parentheses.sol │ │ │ │ ├── base_not_contract.sol │ │ │ │ ├── dataLocation/ │ │ │ │ │ ├── external_overriding_external.sol │ │ │ │ │ ├── modifier_parameter_data_location_change_illegal_internal.sol │ │ │ │ │ ├── parameter_data_location_change_calldata_memory_illegal_public.sol │ │ │ │ │ ├── parameter_data_location_change_illegal_internal.sol │ │ │ │ │ ├── parameter_data_location_change_illegal_public.sol │ │ │ │ │ ├── return_type_data_location.sol │ │ │ │ │ └── return_type_data_location_change_illegal.sol │ │ │ │ ├── disallow_modifier_style_without_parentheses.sol │ │ │ │ ├── duplicatedConstructorCall/ │ │ │ │ │ ├── ancestor.sol │ │ │ │ │ ├── base.sol │ │ │ │ │ ├── base_multi.sol │ │ │ │ │ ├── base_multi_no_constructor.sol │ │ │ │ │ └── base_multi_no_constructor_modifier_style.sol │ │ │ │ ├── duplicated_inheritance_definition.sol │ │ │ │ ├── fallbackReceive/ │ │ │ │ │ ├── fallback_overrides_receive.sol │ │ │ │ │ ├── fallback_with_override.sol │ │ │ │ │ ├── fallback_with_override_intermediate.sol │ │ │ │ │ ├── fallback_without_override.sol │ │ │ │ │ ├── fallback_without_override_intermediate.sol │ │ │ │ │ ├── receive_overrides_fallback.sol │ │ │ │ │ ├── receive_parameter.sol │ │ │ │ │ ├── receive_return_parameter.sol │ │ │ │ │ ├── receive_unimplemented.sol │ │ │ │ │ ├── receive_with_override.sol │ │ │ │ │ ├── receive_with_override_intermediate.sol │ │ │ │ │ ├── receive_without_override.sol │ │ │ │ │ └── receive_without_override_intermediate.sol │ │ │ │ ├── interface/ │ │ │ │ │ ├── contract_base.sol │ │ │ │ │ ├── diamond/ │ │ │ │ │ │ ├── diamond_no_relist.sol │ │ │ │ │ │ └── diamond_with_relist.sol │ │ │ │ │ ├── implementation/ │ │ │ │ │ │ ├── complete.sol │ │ │ │ │ │ └── partial.sol │ │ │ │ │ ├── linearization/ │ │ │ │ │ │ ├── invalid/ │ │ │ │ │ │ │ ├── lists_a.sol │ │ │ │ │ │ │ ├── lists_b.sol │ │ │ │ │ │ │ └── lists_both.sol │ │ │ │ │ │ └── valid.sol │ │ │ │ │ ├── multiple_parents.sol │ │ │ │ │ ├── overrides_multiple.sol │ │ │ │ │ ├── overrides_single.sol │ │ │ │ │ └── single_parent.sol │ │ │ │ ├── interface_virtual_warning.sol │ │ │ │ ├── modifiers_in_constructor_context.sol │ │ │ │ ├── override/ │ │ │ │ │ ├── add_view.sol │ │ │ │ │ ├── ambiguous_base_and_unique_implementation.sol │ │ │ │ │ ├── ambiguous_base_and_unique_mention.sol │ │ │ │ │ ├── ambiguous_base_functions_overridden_in_intermediate_base.sol │ │ │ │ │ ├── ambiguous_base_functions_overridden_in_intermediate_base_unimplemented.sol │ │ │ │ │ ├── calldata_memory.sol │ │ │ │ │ ├── calldata_memory_conflict.sol │ │ │ │ │ ├── calldata_memory_interface.sol │ │ │ │ │ ├── calldata_memory_interface_instantiate.sol │ │ │ │ │ ├── calldata_memory_interface_struct.sol │ │ │ │ │ ├── calldata_memory_struct.sol │ │ │ │ │ ├── change_return_types_in_interface.sol │ │ │ │ │ ├── common_base_and_unique_implementation.sol │ │ │ │ │ ├── common_base_and_unique_mention.sol │ │ │ │ │ ├── correct_choice_for_base_function.sol │ │ │ │ │ ├── correct_choice_for_base_function_abstract_contract.sol │ │ │ │ │ ├── detect_double_override.sol │ │ │ │ │ ├── diamond_interface_empty_intermediate_public_state_variable_and_function.sol │ │ │ │ │ ├── diamond_interface_intermediate_public_state_variable.sol │ │ │ │ │ ├── diamond_interface_intermediate_public_state_variable_and_function.sol │ │ │ │ │ ├── diamond_interface_intermediate_public_state_variable_and_function_implemented.sol │ │ │ │ │ ├── diamond_top_implemented_intermediate_empty_bottom_public_state_variable.sol │ │ │ │ │ ├── diamond_top_implemented_intermediate_implemented_public_state_variable.sol │ │ │ │ │ ├── diamond_top_implemented_intermediate_public_state_variable.sol │ │ │ │ │ ├── external_turns_public_no_params.sol │ │ │ │ │ ├── function_pointer.sol │ │ │ │ │ ├── function_state_variable.sol │ │ │ │ │ ├── implement_interface_by_public_variable.sol │ │ │ │ │ ├── implement_internal_function_by_public_variable.sol │ │ │ │ │ ├── implement_private_function_by_public_variable.sol │ │ │ │ │ ├── implement_public_function_by_public_variable.sol │ │ │ │ │ ├── interfaceException/ │ │ │ │ │ │ ├── abstract_needed.sol │ │ │ │ │ │ ├── diamond_needed.sol │ │ │ │ │ │ └── regular_optional.sol │ │ │ │ │ ├── interface_and_base_override_err.sol │ │ │ │ │ ├── interface_and_base_override_fine.sol │ │ │ │ │ ├── internal_external.sol │ │ │ │ │ ├── internal_external_inheritance.sol │ │ │ │ │ ├── modifier_ambiguous.sol │ │ │ │ │ ├── modifier_ambiguous_fail.sol │ │ │ │ │ ├── modifier_inherited_different_signature.sol │ │ │ │ │ ├── modifier_inherited_different_signature_override.sol │ │ │ │ │ ├── no_common_base_and_unique_implementation.sol │ │ │ │ │ ├── no_matching_resolution.sol │ │ │ │ │ ├── nonintermediate_common_base_and_unique_implementation.sol │ │ │ │ │ ├── nonintermediate_common_base_and_unique_implementation_modifier.sol │ │ │ │ │ ├── nonintermediate_common_base_and_unique_implementation_unimplemented.sol │ │ │ │ │ ├── override.sol │ │ │ │ │ ├── override_ambiguous.sol │ │ │ │ │ ├── override_base_base.sol │ │ │ │ │ ├── override_empty_list.sol │ │ │ │ │ ├── override_implemented_and_unimplemented_with_implemented_call_via_contract.sol │ │ │ │ │ ├── override_implemented_and_unimplemented_with_implemented_call_via_super.sol │ │ │ │ │ ├── override_implemented_and_unimplemented_with_implemented_no_call.sol │ │ │ │ │ ├── override_implemented_and_unimplemented_with_implemented_virtual_call_into_base_contract.sol │ │ │ │ │ ├── override_implemented_with_unimplemented_then_implemented.sol │ │ │ │ │ ├── override_interface.sol │ │ │ │ │ ├── override_interface_multiple.sol │ │ │ │ │ ├── override_less_strict_mutability.sol │ │ │ │ │ ├── override_library.sol │ │ │ │ │ ├── override_missing_virtual.sol │ │ │ │ │ ├── override_modifier_no_override.sol │ │ │ │ │ ├── override_multi_layered_error.sol │ │ │ │ │ ├── override_multi_layered_fine.sol │ │ │ │ │ ├── override_multi_layered_fine_abstract.sol │ │ │ │ │ ├── override_multiple.sol │ │ │ │ │ ├── override_multiple2.sol │ │ │ │ │ ├── override_multiple_duplicated.sol │ │ │ │ │ ├── override_multiple_fail1.sol │ │ │ │ │ ├── override_multiple_fail2.sol │ │ │ │ │ ├── override_multiple_fail3.sol │ │ │ │ │ ├── override_multiple_fail4.sol │ │ │ │ │ ├── override_multiple_missing.sol │ │ │ │ │ ├── override_multiple_no_virtual.sol │ │ │ │ │ ├── override_multiple_no_virtual2.sol │ │ │ │ │ ├── override_multiple_unresolved.sol │ │ │ │ │ ├── override_public_vars.sol │ │ │ │ │ ├── override_return_mismatch.sol │ │ │ │ │ ├── override_shared_base.sol │ │ │ │ │ ├── override_shared_base_partial.sol │ │ │ │ │ ├── override_shared_base_simple.sol │ │ │ │ │ ├── override_stricter_mutability.sol │ │ │ │ │ ├── override_stricter_mutability1.sol │ │ │ │ │ ├── override_stricter_mutability2.sol │ │ │ │ │ ├── override_stricter_mutability3.sol │ │ │ │ │ ├── override_stricter_mutability4.sol │ │ │ │ │ ├── override_stricter_mutability5.sol │ │ │ │ │ ├── override_stricter_mutability6.sol │ │ │ │ │ ├── override_stricter_mutability7.sol │ │ │ │ │ ├── override_type_mismatch.sol │ │ │ │ │ ├── override_type_mismatch2.sol │ │ │ │ │ ├── override_unimplemented_and_implemented_with_unimplemented.sol │ │ │ │ │ ├── override_unimplemented_and_unimplemented_with_unimplemented.sol │ │ │ │ │ ├── private_state_variable.sol │ │ │ │ │ ├── public_constant_var_overrides_pure.sol │ │ │ │ │ ├── public_immutable_var_overrides_pure.sol │ │ │ │ │ ├── public_var_implements_parallel_interface.sol │ │ │ │ │ ├── public_var_missing_override.sol │ │ │ │ │ ├── public_var_no_override_but_function.sol │ │ │ │ │ ├── public_var_override_mapping_to_dynamic_struct.sol │ │ │ │ │ ├── public_var_override_struct_with_memory_element.sol │ │ │ │ │ ├── public_var_overrides_public_var.sol │ │ │ │ │ ├── public_var_overrides_pure.sol │ │ │ │ │ ├── public_var_overriding_multiple.sol │ │ │ │ │ ├── public_var_overriding_multiple_derived.sol │ │ │ │ │ ├── public_var_parallel_function.sol │ │ │ │ │ ├── public_var_same_name_but_different_args.sol │ │ │ │ │ ├── public_var_surplus_override.sol │ │ │ │ │ ├── public_vars_multiple.sol │ │ │ │ │ ├── public_vars_multiple1.sol │ │ │ │ │ ├── public_vars_multiple2.sol │ │ │ │ │ ├── public_vars_multiple3.sol │ │ │ │ │ ├── public_vars_multiple4.sol │ │ │ │ │ ├── public_vars_multiple5.sol │ │ │ │ │ ├── public_vars_multiple_diamond.sol │ │ │ │ │ ├── public_vars_multiple_diamond1.sol │ │ │ │ │ ├── public_vars_multiple_diamond2.sol │ │ │ │ │ ├── public_vars_multiple_explicit_override.sol │ │ │ │ │ ├── public_vars_wrong_override.sol │ │ │ │ │ ├── remove_view.sol │ │ │ │ │ ├── restrict_mutability_for_override_only.sol │ │ │ │ │ ├── state_variable_function.sol │ │ │ │ │ ├── triangle_impl.sol │ │ │ │ │ ├── triangle_no_impl.sol │ │ │ │ │ └── virtual_private.sol │ │ │ │ ├── reference_non_base_ctor.sol │ │ │ │ ├── repeated_inheritance_definition.sol │ │ │ │ ├── shadowing_base_state_vars.sol │ │ │ │ ├── shadowing_private_base_state_vars.sol │ │ │ │ ├── super_on_external.sol │ │ │ │ ├── too_few_base_arguments.sol │ │ │ │ ├── unimplemented_without_virtual.sol │ │ │ │ ├── virtual/ │ │ │ │ │ ├── duplicate.sol │ │ │ │ │ ├── library_err.sol │ │ │ │ │ ├── modifier_virtual_err.sol │ │ │ │ │ └── simple.sol │ │ │ │ └── wrong_type_base_arguments.sol │ │ │ ├── inlineArrays/ │ │ │ │ ├── dynamic_inline_array.sol │ │ │ │ ├── inline_array_declaration_and_passing_implicit_conversion.sol │ │ │ │ ├── inline_array_declaration_and_passing_implicit_conversion_strings.sol │ │ │ │ ├── inline_array_declaration_const_int_conversion.sol │ │ │ │ ├── inline_array_declaration_const_string_conversion.sol │ │ │ │ ├── inline_array_declaration_no_type.sol │ │ │ │ ├── inline_array_declaration_no_type_strings.sol │ │ │ │ ├── inline_array_fixed_types.sol │ │ │ │ ├── inline_array_of_mapping_type.sol │ │ │ │ ├── inline_array_rationals.sol │ │ │ │ ├── invalid_types_in_inline_array.sol │ │ │ │ ├── lvalues_as_inline_array.sol │ │ │ │ ├── unnamed_type_tuple_in_inline_array.sol │ │ │ │ ├── unnamed_types_in_inline_array_1.sol │ │ │ │ ├── unnamed_types_in_inline_array_2.sol │ │ │ │ └── unnamed_types_in_inline_array_3.sol │ │ │ ├── inlineAssembly/ │ │ │ │ ├── assembly_dialect_duplicate_option.sol │ │ │ │ ├── assembly_dialect_invalid_options.sol │ │ │ │ ├── assembly_dialect_leading_space.sol │ │ │ │ ├── assembly_duplicate_option.sol │ │ │ │ ├── assembly_empty_option_list.sol │ │ │ │ ├── assembly_empty_option_list_dialect.sol │ │ │ │ ├── assembly_flags_delimiter.sol │ │ │ │ ├── assembly_invalid_options.sol │ │ │ │ ├── assignment_from_contract.sol │ │ │ │ ├── assignment_from_functiontype.sol │ │ │ │ ├── assignment_from_functiontype2.sol │ │ │ │ ├── assignment_from_functiontype3.sol │ │ │ │ ├── assignment_from_library.sol │ │ │ │ ├── assignment_from_opcode_like.sol │ │ │ │ ├── assignment_from_super.sol │ │ │ │ ├── assignment_location.sol │ │ │ │ ├── assignment_to_function_pointer.sol │ │ │ │ ├── assignment_to_opcode_like.sol │ │ │ │ ├── assignment_to_special.sol │ │ │ │ ├── basefee_reserved_london.sol │ │ │ │ ├── blobbasefee_reserved_cancun.sol │ │ │ │ ├── blobhash.sol │ │ │ │ ├── blobhash_pre_cancun_not_declared.sol │ │ │ │ ├── blobhash_pre_cancun_not_reserved.sol │ │ │ │ ├── blobhash_reserved_cancun.sol │ │ │ │ ├── circular_constant_access_err.sol │ │ │ │ ├── circular_constant_access_module_err.sol │ │ │ │ ├── circular_module_access_err.sol │ │ │ │ ├── clash_with_non_reserved_pure_yul_builtin.sol │ │ │ │ ├── clash_with_reserved_builtin.sol │ │ │ │ ├── clash_with_reserved_non_builtin.sol │ │ │ │ ├── clash_with_reserved_pure_yul_builtin.sol │ │ │ │ ├── clz.sol │ │ │ │ ├── clz_pre_osaka.sol │ │ │ │ ├── clz_reserved_osaka.sol │ │ │ │ ├── const_forward_reference.sol │ │ │ │ ├── const_from_non_const.sol │ │ │ │ ├── const_from_this.sol │ │ │ │ ├── constant_access.sol │ │ │ │ ├── constant_access_non_initialized.sol │ │ │ │ ├── constant_array.sol │ │ │ │ ├── constant_bytes_ref.sol │ │ │ │ ├── constant_computation.sol │ │ │ │ ├── constant_ref.sol │ │ │ │ ├── create2_as_variable_post_istanbul.sol │ │ │ │ ├── create2_as_variable_pre_istanbul.sol │ │ │ │ ├── difficulty_builtin_pre_paris.sol │ │ │ │ ├── difficulty_disallowed_function_pre_paris.sol │ │ │ │ ├── difficulty_magic_block_warn_post_paris.sol │ │ │ │ ├── difficulty_nobuiltin_post_paris.sol │ │ │ │ ├── difficulty_reserved_post_paris.sol │ │ │ │ ├── evm_byzantium.sol │ │ │ │ ├── evm_byzantium_on_homestead.sol │ │ │ │ ├── evm_constantinople.sol │ │ │ │ ├── evm_constantinople_on_byzantium.sol │ │ │ │ ├── evm_istanbul.sol │ │ │ │ ├── evm_istanbul_on_petersburg.sol │ │ │ │ ├── extcodehash_as_variable_post_constantinople.sol │ │ │ │ ├── extcodehash_as_variable_pre_constantinople.sol │ │ │ │ ├── external_identifier_access_shadowing.sol │ │ │ │ ├── function_call_invalid_argument_count.sol │ │ │ │ ├── function_call_not_found.sol │ │ │ │ ├── function_call_to_variable.sol │ │ │ │ ├── function_definition.sol │ │ │ │ ├── function_definition_whitespace.sol │ │ │ │ ├── function_without_call.sol │ │ │ │ ├── hex_assignment.sol │ │ │ │ ├── hex_expression.sol │ │ │ │ ├── hex_switch_case.sol │ │ │ │ ├── immutables.sol │ │ │ │ ├── in_modifier.sol │ │ │ │ ├── invalid/ │ │ │ │ │ ├── assign_to_instruction.sol │ │ │ │ │ ├── assignment_to_function.sol │ │ │ │ │ ├── bare_instructions_disallowed.sol │ │ │ │ │ ├── calldata_array.sol │ │ │ │ │ ├── calldata_array_offset.sol │ │ │ │ │ ├── calldata_slot.sol │ │ │ │ │ ├── calldata_variables.sol │ │ │ │ │ ├── const_forward_reference.sol │ │ │ │ │ ├── constant_access.sol │ │ │ │ │ ├── constant_assignment.sol │ │ │ │ │ ├── constant_length_access.sol │ │ │ │ │ ├── constant_variable_via_offset.sol │ │ │ │ │ ├── dot_in_fun_param.sol │ │ │ │ │ ├── dot_in_fundecl.sol │ │ │ │ │ ├── dot_in_multi_vardecl.sol │ │ │ │ │ ├── dot_in_vardecl.sol │ │ │ │ │ ├── dup_disallowed.sol │ │ │ │ │ ├── empty_fun_arg_beginning.sol │ │ │ │ │ ├── empty_fun_arg_end.sol │ │ │ │ │ ├── empty_fun_arg_middle.sol │ │ │ │ │ ├── empty_function_name.sol │ │ │ │ │ ├── eof/ │ │ │ │ │ │ ├── eof_builtins_disallowed.sol │ │ │ │ │ │ └── eof_builtins_disallowed_in_inline_assembly.sol │ │ │ │ │ ├── external_function_pointer_offset.sol │ │ │ │ │ ├── identifier_starting_with_dot.sol │ │ │ │ │ ├── illegal_names.sol │ │ │ │ │ ├── internal_function_pointer_address.sol │ │ │ │ │ ├── internal_function_pointer_selector.sol │ │ │ │ │ ├── invalid_number.sol │ │ │ │ │ ├── jump_disallowed.sol │ │ │ │ │ ├── jumpdest_disallowed.sol │ │ │ │ │ ├── jumpi_disallowed.sol │ │ │ │ │ ├── label_disallowed.sol │ │ │ │ │ ├── leave_items_on_stack.sol │ │ │ │ │ ├── literals_on_stack_disallowed.sol │ │ │ │ │ ├── local_variable_access_out_of_functions.sol │ │ │ │ │ ├── local_variable_access_out_of_functions_storage_ptr.sol │ │ │ │ │ ├── missing_variable.sol │ │ │ │ │ ├── missing_variable_in_assign.sol │ │ │ │ │ ├── multiple_assign_to_instruction.sol │ │ │ │ │ ├── nested_function_local_access.sol │ │ │ │ │ ├── pc_disallowed.sol │ │ │ │ │ ├── push_disallowed.sol │ │ │ │ │ ├── storage_assignment.sol │ │ │ │ │ ├── storage_assignment_in_modifier.sol │ │ │ │ │ ├── storage_nonslot.sol │ │ │ │ │ ├── storage_variable_access_out_of_functions.sol │ │ │ │ │ ├── swap_disallowed.sol │ │ │ │ │ ├── transient_storage_assignment.sol │ │ │ │ │ ├── unbalanced_negative_stack.sol │ │ │ │ │ ├── unbalanced_positive_stack.sol │ │ │ │ │ ├── unbalanced_two_stack_load.sol │ │ │ │ │ ├── variable_declaration_suffix_offset.sol │ │ │ │ │ ├── whitespace_in_assignment.sol │ │ │ │ │ └── whitespace_in_multiple_assignment.sol │ │ │ │ ├── invalid_natspec.sol │ │ │ │ ├── leave.sol │ │ │ │ ├── leave_invalid.sol │ │ │ │ ├── linkersymbol_builtin.sol │ │ │ │ ├── linkersymbol_function.sol │ │ │ │ ├── mcopy.sol │ │ │ │ ├── mcopy_pre_cancun.sol │ │ │ │ ├── mcopy_reserved_cancun.sol │ │ │ │ ├── memory_safe_dialect_string_and_comment.sol │ │ │ │ ├── memory_safe_in_dialect_string.sol │ │ │ │ ├── natspec_memory_safe.sol │ │ │ │ ├── natspec_multi.sol │ │ │ │ ├── natspec_multi_swallowed.sol │ │ │ │ ├── no_unused_variable_warning.sol │ │ │ │ ├── overloaded_reference.sol │ │ │ │ ├── period_in_identifer.sol │ │ │ │ ├── prevrandao_allowed_function_pre_paris.sol │ │ │ │ ├── prevrandao_builtin_post_paris.sol │ │ │ │ ├── prevrandao_disallowed_function_post_paris.sol │ │ │ │ ├── prevrandao_magic_block_warn_pre_paris.sol │ │ │ │ ├── prevrandao_nobuitin_pre_paris.sol │ │ │ │ ├── push0_disallowed.sol │ │ │ │ ├── reserved_identifiers.sol │ │ │ │ ├── reserved_identifiers_byzantium.sol │ │ │ │ ├── reserved_identifiers_constantinople.sol │ │ │ │ ├── returndatasize_as_variable_call_post_byzantium.sol.sol │ │ │ │ ├── returndatasize_as_variable_post_byzantium.sol │ │ │ │ ├── returndatasize_as_variable_pre_byzantium.sol │ │ │ │ ├── returndatasize_as_variable_read_post_byzantium.sol.sol │ │ │ │ ├── shadowing/ │ │ │ │ │ ├── argument.sol │ │ │ │ │ ├── constant.sol │ │ │ │ │ ├── contract.sol │ │ │ │ │ ├── function.sol │ │ │ │ │ ├── global_function_by_opcode.sol │ │ │ │ │ ├── local_function_by_opcode.sol │ │ │ │ │ ├── local_variable.sol │ │ │ │ │ ├── name_clash_in_import.sol │ │ │ │ │ ├── no_name_clash_in_import.sol │ │ │ │ │ ├── qualified_names.sol │ │ │ │ │ ├── state_variable_by_opcode.sol │ │ │ │ │ └── variable_by_opcode.sol │ │ │ │ ├── solidity_keywords.sol │ │ │ │ ├── storage_reference.sol │ │ │ │ ├── storage_reference_assignment.sol │ │ │ │ ├── storage_reference_assignment_statevar.sol │ │ │ │ ├── storage_reference_empty_offset.sol │ │ │ │ ├── storage_reference_empty_slot.sol │ │ │ │ ├── storage_reference_fine.sol │ │ │ │ ├── storage_reference_old.sol │ │ │ │ ├── storage_reference_old_shadow.sol │ │ │ │ ├── storage_reference_on_function.sol │ │ │ │ ├── storage_reference_on_memory.sol │ │ │ │ ├── storage_slot_assign.sol │ │ │ │ ├── string_literal_switch_case.sol │ │ │ │ ├── tload_reserved_cancun.sol │ │ │ │ ├── transient_storage_invalid_pre_cancun.sol │ │ │ │ ├── transient_storage_opcodes.sol │ │ │ │ ├── transient_storage_value_assignment_statevar.sol │ │ │ │ ├── tstore_reserved_cancun.sol │ │ │ │ ├── tstore_warning_only_once_multiple_contracts.sol │ │ │ │ ├── tstore_warning_only_once_multiple_sources.sol │ │ │ │ ├── two_stack_slot_access.sol │ │ │ │ ├── two_stack_slots.sol │ │ │ │ ├── use_msize_with_optimizer.sol │ │ │ │ ├── use_msize_without_optimizer.sol │ │ │ │ └── verbatim_disallowed.sol │ │ │ ├── isoltestTesting/ │ │ │ │ ├── stopAfterAnalysisError.sol │ │ │ │ ├── stopAfterParsingAnalysisErrorNotShowing.sol │ │ │ │ └── stopAfterParsingError.sol │ │ │ ├── largeTypes/ │ │ │ │ ├── large_storage_array_fine.sol │ │ │ │ ├── large_storage_array_mapping.sol │ │ │ │ ├── large_storage_array_simple.sol │ │ │ │ ├── large_storage_arrays_combined.sol │ │ │ │ ├── large_storage_arrays_struct.sol │ │ │ │ ├── large_storage_structs.sol │ │ │ │ ├── max_size_array_with_transient_state_variables.sol │ │ │ │ ├── oversized_array_1d.sol │ │ │ │ ├── oversized_array_2d.sol │ │ │ │ ├── oversized_contract.sol │ │ │ │ ├── oversized_contract_inheritance.sol │ │ │ │ ├── oversized_struct.sol │ │ │ │ └── storage_parameter.sol │ │ │ ├── license/ │ │ │ │ ├── license_AND.sol │ │ │ │ ├── license_OR.sol │ │ │ │ ├── license_bidi_marks.sol │ │ │ │ ├── license_bottom.sol │ │ │ │ ├── license_cr_endings.sol │ │ │ │ ├── license_crlf_endings.sol │ │ │ │ ├── license_double.sol │ │ │ │ ├── license_double2.sol │ │ │ │ ├── license_double3.sol │ │ │ │ ├── license_double4.sol │ │ │ │ ├── license_double5.sol │ │ │ │ ├── license_hidden_unicode.sol │ │ │ │ ├── license_in_contract.sol │ │ │ │ ├── license_in_import.sol │ │ │ │ ├── license_in_string.sol │ │ │ │ ├── license_missing.sol │ │ │ │ ├── license_missing_colon.sol │ │ │ │ ├── license_multiline.sol │ │ │ │ ├── license_natspec.sol │ │ │ │ ├── license_natspec_multiline.sol │ │ │ │ ├── license_no_whitespace.sol │ │ │ │ ├── license_no_whitespace_multiline.sol │ │ │ │ ├── license_nonempty_line.sol │ │ │ │ ├── license_unicode.sol │ │ │ │ ├── license_whitespace_after_colon.sol │ │ │ │ ├── license_whitespace_before_spdx.sol │ │ │ │ └── license_whitespace_trailing.sol │ │ │ ├── literalOperations/ │ │ │ │ ├── division_by_zero.sol │ │ │ │ ├── division_by_zero_complex.sol │ │ │ │ ├── division_by_zero_complex_compound.sol │ │ │ │ ├── division_by_zero_compound.sol │ │ │ │ ├── division_by_zero_nonliteral.sol │ │ │ │ ├── exponent.sol │ │ │ │ ├── exponent_fine.sol │ │ │ │ ├── literal_comparisons.sol │ │ │ │ ├── mod_zero.sol │ │ │ │ ├── mod_zero_complex.sol │ │ │ │ ├── mod_zero_complex_compound.sol │ │ │ │ ├── mod_zero_compound.sol │ │ │ │ └── mod_zero_nonliteral.sol │ │ │ ├── literals/ │ │ │ │ ├── hex_string_duplicate_underscore.sol │ │ │ │ ├── hex_string_duplicate_underscore_yul.sol │ │ │ │ ├── hex_string_invalid_characters_yul.sol │ │ │ │ ├── hex_string_leading_underscore.sol │ │ │ │ ├── hex_string_misaligned_underscore.sol │ │ │ │ ├── hex_string_trailing_underscore.sol │ │ │ │ ├── hex_string_underscores_valid.sol │ │ │ │ ├── invalid_hex_number.sol │ │ │ │ ├── invalid_octal_denomination_no_whitespace.sol │ │ │ │ ├── invalid_octal_digits.sol │ │ │ │ ├── invalid_octal_number.sol │ │ │ │ ├── ternary_operator_return_type_with_literal_arguments.sol │ │ │ │ ├── unicode_string_direction_override_1.sol │ │ │ │ ├── unicode_string_direction_override_2.sol │ │ │ │ ├── unicode_string_direction_override_3.sol │ │ │ │ ├── unicode_string_direction_override_4.sol │ │ │ │ ├── unicode_string_direction_override_5.sol │ │ │ │ ├── unicode_string_direction_override_6.sol │ │ │ │ ├── unicode_string_direction_override_7.sol │ │ │ │ └── upper_case_hex_literals.sol │ │ │ ├── lvalues/ │ │ │ │ ├── calldata_index_access.sol │ │ │ │ ├── calldata_member_access.sol │ │ │ │ ├── external_reference_argument.sol │ │ │ │ ├── functions.sol │ │ │ │ ├── library_mapping.sol │ │ │ │ ├── lvalue_not_set.sol │ │ │ │ └── valid_lvalues.sol │ │ │ ├── memberLookup/ │ │ │ │ ├── constructor_as_potential_library_member.sol │ │ │ │ ├── contract_not_payable_send.sol │ │ │ │ ├── contract_not_payable_transfer.sol │ │ │ │ ├── failed_function_lookup.sol │ │ │ │ ├── failed_function_lookup_in_library.sol │ │ │ │ ├── internal_function_type.sol │ │ │ │ ├── member_not_unique.sol │ │ │ │ ├── member_value_not_unique.sol │ │ │ │ ├── memory_structs_with_mapping_array_struct_array.sol │ │ │ │ ├── memory_structs_with_mappings.sol │ │ │ │ ├── msg_sender_non_payable_send.sol │ │ │ │ ├── msg_sender_non_payable_transfer.sol │ │ │ │ ├── msg_value_modifier_payable.sol │ │ │ │ ├── msg_value_modifier_pure.sol │ │ │ │ ├── msg_value_modifier_view.sol │ │ │ │ ├── push_on_memory_types.sol │ │ │ │ ├── tx_origin_non_payable_send.sol │ │ │ │ ├── tx_origin_non_payable_transfer.sol │ │ │ │ └── unused_module_member_reference.sol │ │ │ ├── metaTypes/ │ │ │ │ ├── array_type_from_ternary.sol │ │ │ │ ├── codeAccess.sol │ │ │ │ ├── codeAccessAbstractCreation.sol │ │ │ │ ├── codeAccessAbstractRuntime.sol │ │ │ │ ├── codeAccessBase.sol │ │ │ │ ├── codeAccessCyclic.sol │ │ │ │ ├── codeAccessIsConstant.sol │ │ │ │ ├── codeAccessLibrary.sol │ │ │ │ ├── codeAccess_super.sol │ │ │ │ ├── codeIsNoLValue.sol │ │ │ │ ├── contract_from_ternary.sol │ │ │ │ ├── contract_min.sol │ │ │ │ ├── explicit_type_conversion.sol │ │ │ │ ├── int_name.sol │ │ │ │ ├── integer.sol │ │ │ │ ├── integer_err.sol │ │ │ │ ├── integer_pure.sol │ │ │ │ ├── interfaceid_super.sol │ │ │ │ ├── library_from_ternary.sol │ │ │ │ ├── max_keyword_from_ternary_with_type_expression.sol │ │ │ │ ├── name.sol │ │ │ │ ├── name_constant.sol │ │ │ │ ├── name_other_contract.sol │ │ │ │ ├── noArgForType.sol │ │ │ │ ├── runtimeCodeWarningAssembly.sol │ │ │ │ ├── runtimeCode_from_ternary_with_type_expression.sol │ │ │ │ ├── struct_from_ternary.sol │ │ │ │ ├── super_name.sol │ │ │ │ ├── tooManyArgsForType.sol │ │ │ │ ├── typeNotRegularIdentifierContractName.sol │ │ │ │ ├── typeNotRegularIdentifierFunction.sol │ │ │ │ ├── typeNotRegularIdentifierParameter.sol │ │ │ │ ├── typeNotRegularIdentifierStateVariable.sol │ │ │ │ ├── typeNotRegularIdentifierVariable.sol │ │ │ │ ├── typeOfContract.sol │ │ │ │ ├── typeRecursive.sol │ │ │ │ ├── type_expression_nested_ternary_max_keyword.sol │ │ │ │ ├── type_expression_tuple_max.sol │ │ │ │ ├── type_from_ternary_condition.sol │ │ │ │ ├── type_max.sol │ │ │ │ ├── type_max_from_ternary_expression.sol │ │ │ │ ├── type_runtimecode.sol │ │ │ │ ├── type_runtimecode_from_ternary_expression_.sol │ │ │ │ └── unsupported_arg_for_type.sol │ │ │ ├── modifiers/ │ │ │ │ ├── access_in_library.sol │ │ │ │ ├── base_constructor_double_invocation.sol │ │ │ │ ├── constructor_as_modifier.sol │ │ │ │ ├── constructor_call_invalid_arg_count.sol │ │ │ │ ├── cross_contract_access.sol │ │ │ │ ├── cross_contract_base.sol │ │ │ │ ├── cross_contract_super.sol │ │ │ │ ├── cross_contract_unrelated.sol │ │ │ │ ├── definition_in_contract.sol │ │ │ │ ├── definition_in_contract_unimplemented.sol │ │ │ │ ├── definition_in_interface.sol │ │ │ │ ├── definition_in_library.sol │ │ │ │ ├── definition_in_library_unimplemented.sol │ │ │ │ ├── definition_in_library_virtual.sol │ │ │ │ ├── elementary_non_address_state_mutability_modifier_argument.sol │ │ │ │ ├── empty_modifier_body.sol │ │ │ │ ├── empty_modifier_err.sol │ │ │ │ ├── function_modifier_double_invocation.sol │ │ │ │ ├── function_modifier_invocation.sol │ │ │ │ ├── function_modifier_invocation_local_variables.sol │ │ │ │ ├── function_modifier_invocation_parameters.sol │ │ │ │ ├── function_overrides_modifier.sol │ │ │ │ ├── illegal_modifier_override.sol │ │ │ │ ├── illegal_name.sol │ │ │ │ ├── invalid_function_modifier_type.sol │ │ │ │ ├── invalid_parameter_indexed.sol │ │ │ │ ├── invalid_parameter_mutability.sol │ │ │ │ ├── invalid_parameter_visibility.sol │ │ │ │ ├── legal_modifier_override.sol │ │ │ │ ├── library_via_using.sol │ │ │ │ ├── modifier_abstract_override.sol │ │ │ │ ├── modifier_overrides_function.sol │ │ │ │ ├── modifier_overrides_variable.sol │ │ │ │ ├── modifier_returns_value.sol │ │ │ │ ├── modifier_without_underscore.sol │ │ │ │ ├── modifiers_on_abstract_functions_no_parser_error.sol │ │ │ │ ├── multiple_inheritance_unimplemented_override.sol │ │ │ │ ├── multiple_parameter_location.sol │ │ │ │ ├── non-virtual_modifier_override.sol │ │ │ │ ├── transient_parameter.sol │ │ │ │ ├── unimplemented_function_and_modifier.sol │ │ │ │ ├── unimplemented_override_unimplemented.sol │ │ │ │ ├── use_in_invalid_context.sol │ │ │ │ ├── use_on_interface_function.sol │ │ │ │ ├── use_unimplemented_from_base.sol │ │ │ │ ├── use_unimplemented_on_overridden_func.sol │ │ │ │ └── use_unimplemented_static.sol │ │ │ ├── multiSource/ │ │ │ │ ├── alias_shadows_another_alias.sol │ │ │ │ ├── alias_shadows_function.sol │ │ │ │ ├── circular_import.sol │ │ │ │ ├── circular_import_2.sol │ │ │ │ ├── circular_import_3.sol │ │ │ │ ├── circular_import_4.sol │ │ │ │ ├── circular_import_5.sol │ │ │ │ ├── duplicate_import_statement.sol │ │ │ │ ├── error_in_first.sol │ │ │ │ ├── free_different_interger_types.sol │ │ │ │ ├── free_function_alias_different_parameter_types.sol │ │ │ │ ├── free_function_control_flow_analysis.sol │ │ │ │ ├── free_function_redefinition_base_derived.sol │ │ │ │ ├── free_function_redefinition_transitive.sol │ │ │ │ ├── free_function_resolution_override_virtual.sol │ │ │ │ ├── import.sol │ │ │ │ ├── import_alias.sol │ │ │ │ ├── import_alias_mismatch.sol │ │ │ │ ├── import_contract_function_error.sol │ │ │ │ ├── import_not_found.sol │ │ │ │ ├── imported_free_function.sol │ │ │ │ ├── libraries_control_flow_analysis.sol │ │ │ │ ├── multiple_imports_same_function.sol │ │ │ │ ├── no_import.sol │ │ │ │ ├── one_source.sol │ │ │ │ ├── reimport_imported_function.sol │ │ │ │ ├── split_contract_hierarchy_control_flow_analysis.sol │ │ │ │ ├── split_contract_hierarchy_control_flow_analysis_complex.sol │ │ │ │ ├── two_imports_same_function.sol │ │ │ │ └── warning_in_both.sol │ │ │ ├── multiVariableDeclaration/ │ │ │ │ ├── differentNumberOfComponents.sol │ │ │ │ ├── differentNumberOfComponentsFromReturn.sol │ │ │ │ ├── disallowWildcards.sol │ │ │ │ ├── disallowWildcardsFromReturn.sol │ │ │ │ ├── multiSingleVariableDeclaration.sol │ │ │ │ ├── multiVariableDeclarationComplex.sol │ │ │ │ ├── multiVariableDeclarationEmpty.sol │ │ │ │ ├── multiVariableDeclarationInvalidType.sol │ │ │ │ ├── multiVariableDeclarationScoping.sol │ │ │ │ ├── multiVariableDeclarationScoping2.sol │ │ │ │ ├── multiVariableDeclarationSimple.sol │ │ │ │ ├── multiVariableDeclarationThatIsExpression.sol │ │ │ │ ├── oneElementTuple.sol │ │ │ │ └── sameNumberOfComponents.sol │ │ │ ├── nameAndTypeResolution/ │ │ │ │ ├── 001_name_references.sol │ │ │ │ ├── 002_undeclared_name.sol │ │ │ │ ├── 003_undeclared_name_is_not_fatal.sol │ │ │ │ ├── 004_reference_to_later_declaration.sol │ │ │ │ ├── 010_type_conversion_for_comparison.sol │ │ │ │ ├── 011_type_conversion_for_comparison_invalid.sol │ │ │ │ ├── 013_large_string_literal.sol │ │ │ │ ├── 014_balance.sol │ │ │ │ ├── 015_balance_invalid.sol │ │ │ │ ├── 017_assignment_to_struct.sol │ │ │ │ ├── 018_forward_function_reference.sol │ │ │ │ ├── 019_comparison_bitop_precedence.sol │ │ │ │ ├── 025_comparison_of_mapping_types.sol │ │ │ │ ├── 029_create_abstract_contract.sol │ │ │ │ ├── 030_redeclare_implemented_abstract_function_as_abstract.sol │ │ │ │ ├── 044_returning_multi_dimensional_arrays_new_abi.sol │ │ │ │ ├── 045_returning_multi_dimensional_arrays.sol │ │ │ │ ├── 046_returning_multi_dimensional_static_arrays.sol │ │ │ │ ├── 047_returning_arrays_in_structs_new_abi.sol │ │ │ │ ├── 048_returning_arrays_in_structs_arrays.sol │ │ │ │ ├── 049_function_external_call_allowed_conversion.sol │ │ │ │ ├── 050_function_external_call_not_allowed_conversion.sol │ │ │ │ ├── 051_function_internal_allowed_conversion.sol │ │ │ │ ├── 052_function_internal_not_allowed_conversion.sol │ │ │ │ ├── 053_hash_collision_in_interface.sol │ │ │ │ ├── 054_inheritance_basic.sol │ │ │ │ ├── 055_inheritance_diamond_basic.sol │ │ │ │ ├── 056_cyclic_inheritance.sol │ │ │ │ ├── 057_legal_override_direct.sol │ │ │ │ ├── 058_legal_override_indirect.sol │ │ │ │ ├── 059_illegal_override_visibility.sol │ │ │ │ ├── 060_complex_inheritance.sol │ │ │ │ ├── 061_missing_base_constructor_arguments.sol │ │ │ │ ├── 062_base_constructor_arguments_override.sol │ │ │ │ ├── 063_implicit_derived_to_base_conversion.sol │ │ │ │ ├── 064_implicit_base_to_derived_conversion.sol │ │ │ │ ├── 065_super_excludes_current_contract.sol │ │ │ │ ├── 067_function_clash_with_state_variable_accessor.sol │ │ │ │ ├── 069_base_class_state_variable_accessor.sol │ │ │ │ ├── 070_struct_accessor_one_array_only.sol │ │ │ │ ├── 071_base_class_state_variable_internal_member.sol │ │ │ │ ├── 072_state_variable_member_of_wrong_class1.sol │ │ │ │ ├── 073_state_variable_member_of_wrong_class2.sol │ │ │ │ ├── 074_fallback_function.sol │ │ │ │ ├── 075_fallback_function_with_arguments.sol │ │ │ │ ├── 076_fallback_function_in_library.sol │ │ │ │ ├── 076_receive_function_in_library.sol │ │ │ │ ├── 077_fallback_function_with_return_parameters.sol │ │ │ │ ├── 079_fallback_function_inheritance.sol │ │ │ │ ├── 096_access_to_default_function_visibility.sol │ │ │ │ ├── 097_access_to_internal_function.sol │ │ │ │ ├── 098_access_to_default_state_variable_visibility.sol │ │ │ │ ├── 099_access_to_internal_state_variable.sol │ │ │ │ ├── 104_empty_name_input_parameter.sol │ │ │ │ ├── 105_constant_input_parameter.sol │ │ │ │ ├── 106_empty_name_return_parameter.sol │ │ │ │ ├── 107_empty_name_input_parameter_with_named_one.sol │ │ │ │ ├── 108_empty_name_return_parameter_with_named_one.sol │ │ │ │ ├── 110_no_overflow_with_large_literal.sol │ │ │ │ ├── 111_overflow_caused_by_ether_units.sol │ │ │ │ ├── 112_exp_operator_exponent_too_big.sol │ │ │ │ ├── 113_exp_warn_literal_base_1.sol │ │ │ │ ├── 114_exp_warn_literal_base_2.sol │ │ │ │ ├── 115_exp_warn_literal_base_3.sol │ │ │ │ ├── 116_shift_warn_literal_base_1.sol │ │ │ │ ├── 117_shift_warn_literal_base_2.sol │ │ │ │ ├── 118_shift_warn_literal_base_3.sol │ │ │ │ ├── 119_shift_warn_literal_base_4.sol │ │ │ │ ├── 124_enum_member_access.sol │ │ │ │ ├── 125_enum_member_access_accross_contracts.sol │ │ │ │ ├── 126_enum_invalid_member_access.sol │ │ │ │ ├── 127_enum_invalid_direct_member_access.sol │ │ │ │ ├── 128_enum_explicit_conversion_is_okay.sol │ │ │ │ ├── 129_int_to_enum_explicit_conversion_is_okay.sol │ │ │ │ ├── 130_enum_implicit_conversion_is_not_okay_256.sol │ │ │ │ ├── 131_enum_implicit_conversion_is_not_okay_64.sol │ │ │ │ ├── 132_enum_to_enum_conversion_is_not_okay.sol │ │ │ │ ├── 133_enum_duplicate_values.sol │ │ │ │ ├── 134_enum_name_resolution_under_current_contract_name.sol │ │ │ │ ├── 135_private_visibility.sol │ │ │ │ ├── 136_private_visibility_via_explicit_base_access.sol │ │ │ │ ├── 137_external_visibility.sol │ │ │ │ ├── 138_similar_name_suggestions_expected.sol │ │ │ │ ├── 139_no_name_suggestion.sol │ │ │ │ ├── 140_multiple_similar_suggestions.sol │ │ │ │ ├── 141_multiple_scopes_suggestions.sol │ │ │ │ ├── 142_inheritence_suggestions.sol │ │ │ │ ├── 143_no_spurious_identifier_suggestions_with_submatch.sol │ │ │ │ ├── 144_no_spurious_identifier_suggestions.sol │ │ │ │ ├── 145_external_base_visibility.sol │ │ │ │ ├── 146_external_argument_assign.sol │ │ │ │ ├── 147_external_argument_increment.sol │ │ │ │ ├── 148_external_argument_delete.sol │ │ │ │ ├── 149_test_for_bug_override_function_with_bytearray_type.sol │ │ │ │ ├── 150_array_with_nonconstant_length.sol │ │ │ │ ├── 151_array_with_negative_length.sol │ │ │ │ ├── 152_array_copy_with_different_types1.sol │ │ │ │ ├── 153_array_copy_with_different_types2.sol │ │ │ │ ├── 154_array_copy_with_different_types_conversion_possible.sol │ │ │ │ ├── 155_array_copy_with_different_types_static_dynamic.sol │ │ │ │ ├── 156_array_copy_with_different_types_dynamic_static.sol │ │ │ │ ├── 157_array_of_undeclared_type.sol │ │ │ │ ├── 158_storage_variable_initialization_with_incorrect_type_int.sol │ │ │ │ ├── 159_storage_variable_initialization_with_incorrect_type_string.sol │ │ │ │ ├── 160_test_byte_is_alias_of_byte1.sol │ │ │ │ ├── 164_assigning_value_to_const_variable.sol │ │ │ │ ├── 165_assigning_state_to_const_variable.sol │ │ │ │ ├── 167_constant_string_literal_disallows_assignment.sol │ │ │ │ ├── 168_assignment_to_const_var_involving_conversion.sol │ │ │ │ ├── 169_assignment_to_const_var_involving_expression.sol │ │ │ │ ├── 170_assignment_to_const_var_involving_keccak.sol │ │ │ │ ├── 171_assignment_to_const_array_vars.sol │ │ │ │ ├── 172_assignment_to_const_string_bytes.sol │ │ │ │ ├── 173_constant_struct.sol │ │ │ │ ├── 174_address_is_constant.sol │ │ │ │ ├── 175_uninitialized_const_variable.sol │ │ │ │ ├── 176_overloaded_function_cannot_resolve.sol │ │ │ │ ├── 177_ambiguous_overloaded_function.sol │ │ │ │ ├── 178_assignment_of_nonoverloaded_function.sol │ │ │ │ ├── 179_assignment_of_overloaded_function.sol │ │ │ │ ├── 180_external_types_clash.sol │ │ │ │ ├── 181_override_changes_return_types.sol │ │ │ │ ├── 182_equal_overload.sol │ │ │ │ ├── 188_string_index.sol │ │ │ │ ├── 189_string_length.sol │ │ │ │ ├── 190_negative_integers_to_signed_out_of_bound.sol │ │ │ │ ├── 191_negative_integers_to_signed_min.sol │ │ │ │ ├── 192_positive_integers_to_signed_out_of_bound.sol │ │ │ │ ├── 193_positive_integers_to_signed_out_of_bound_max.sol │ │ │ │ ├── 194_negative_integers_to_unsigned.sol │ │ │ │ ├── 195_positive_integers_to_unsigned_out_of_bound.sol │ │ │ │ ├── 196_integer_boolean_or.sol │ │ │ │ ├── 197_integer_boolean_and.sol │ │ │ │ ├── 198_integer_boolean_not.sol │ │ │ │ ├── 199_integer_unsigned_exp_signed.sol │ │ │ │ ├── 200_integer_signed_exp_unsigned.sol │ │ │ │ ├── 201_integer_signed_exp_signed.sol │ │ │ │ ├── 202_bytes_reference_compare_operators.sol │ │ │ │ ├── 203_struct_reference_compare_operators.sol │ │ │ │ ├── 204_overwrite_memory_location_external.sol │ │ │ │ ├── 205_overwrite_storage_location_external.sol │ │ │ │ ├── 206_storage_location_local_variables.sol │ │ │ │ ├── 207_no_mappings_in_memory_array.sol │ │ │ │ ├── 208_assignment_mem_to_local_storage_variable.sol │ │ │ │ ├── 209_storage_assign_to_different_local_variable.sol │ │ │ │ ├── 210_uninitialized_mapping_variable.sol │ │ │ │ ├── 211_uninitialized_mapping_array_variable.sol │ │ │ │ ├── 213_no_delete_on_storage_pointers.sol │ │ │ │ ├── 214_assignment_mem_storage_variable_directly.sol │ │ │ │ ├── 215_function_argument_mem_to_storage.sol │ │ │ │ ├── 216_function_argument_storage_to_mem.sol │ │ │ │ ├── 217_mem_array_assignment_changes_base_type.sol │ │ │ │ ├── 219_memory_arrays_not_resizeable.sol │ │ │ │ ├── 220_struct_constructor.sol │ │ │ │ ├── 221_struct_constructor_nested.sol │ │ │ │ ├── 222_struct_named_constructor.sol │ │ │ │ ├── 223_literal_strings.sol │ │ │ │ ├── 224_string_bytes_conversion.sol │ │ │ │ ├── 225_inheriting_from_library.sol │ │ │ │ ├── 226_inheriting_library.sol │ │ │ │ ├── 227_library_having_variables.sol │ │ │ │ ├── 228_valid_library.sol │ │ │ │ ├── 229_call_to_library_function.sol │ │ │ │ ├── 230_creating_contract_within_the_contract.sol │ │ │ │ ├── 231_array_out_of_bound_access.sol │ │ │ │ ├── 232_literal_string_to_storage_pointer.sol │ │ │ │ ├── 233_non_initialized_references.sol │ │ │ │ ├── 235_abi_encode_with_large_integer_constant.sol │ │ │ │ ├── 236_cyclic_binary_dependency.sol │ │ │ │ ├── 237_cyclic_binary_dependency_via_inheritance.sol │ │ │ │ ├── 244_tuples.sol │ │ │ │ ├── 245_tuples_empty_components.sol │ │ │ │ ├── 250_member_access_parser_ambiguity.sol │ │ │ │ ├── 251_using_for_library.sol │ │ │ │ ├── 252_using_for_not_library.sol │ │ │ │ ├── 253_using_for_function_exists.sol │ │ │ │ ├── 254_using_for_function_on_int.sol │ │ │ │ ├── 255_using_for_function_on_struct.sol │ │ │ │ ├── 256_using_for_overload.sol │ │ │ │ ├── 257_using_for_by_name.sol │ │ │ │ ├── 258_using_for_mismatch.sol │ │ │ │ ├── 259_using_for_not_used.sol │ │ │ │ ├── 260_library_memory_struct.sol │ │ │ │ ├── 261_using_for_arbitrary_mismatch.sol │ │ │ │ ├── 263_create_memory_arrays.sol │ │ │ │ ├── 264_mapping_in_memory_array.sol │ │ │ │ ├── 265_new_for_non_array.sol │ │ │ │ ├── 268_function_overload_array_type.sol │ │ │ │ ├── 275_inline_struct_declaration_arrays.sol │ │ │ │ ├── 279_break_not_in_loop.sol │ │ │ │ ├── 280_continue_not_in_loop.sol │ │ │ │ ├── 281_continue_not_in_loop_2.sol │ │ │ │ ├── 282_invalid_different_types_for_conditional_expression.sol │ │ │ │ ├── 283_left_value_in_conditional_expression_not_supported_yet.sol │ │ │ │ ├── 284_conditional_expression_with_different_struct.sol │ │ │ │ ├── 285_conditional_expression_with_different_function_type.sol │ │ │ │ ├── 286_conditional_expression_with_different_enum.sol │ │ │ │ ├── 287_conditional_expression_with_different_mapping.sol │ │ │ │ ├── 288_conditional_with_all_types.sol │ │ │ │ ├── 289_uint7_and_uintM_as_identifier.sol │ │ │ │ ├── 290_varM_disqualified_as_keyword_1.sol │ │ │ │ ├── 290_varM_disqualified_as_keyword_2.sol │ │ │ │ ├── 290_varM_disqualified_as_keyword_3.sol │ │ │ │ ├── 291_modifier_is_not_a_valid_typename.sol │ │ │ │ ├── 292_modifier_is_not_a_valid_typename_is_not_fatal.sol │ │ │ │ ├── 293_function_is_not_a_valid_typename.sol │ │ │ │ ├── 294_long_uint_variable_fails.sol │ │ │ │ ├── 295_bytes10abc_is_identifier.sol │ │ │ │ ├── 296_int10abc_is_identifier.sol │ │ │ │ ├── 297_library_functions_do_not_have_value.sol │ │ │ │ ├── 298_invalid_fixed_types_0x7_mxn.sol │ │ │ │ ├── 299_invalid_fixed_types_long_invalid_identifier.sol │ │ │ │ ├── 300_invalid_fixed_types_7x8_mxn.sol │ │ │ │ ├── 301_library_instances_cannot_be_used.sol │ │ │ │ ├── 302_invalid_fixed_type_long.sol │ │ │ │ ├── 303_fixed_type_int_conversion.sol │ │ │ │ ├── 304_fixed_type_rational_int_conversion.sol │ │ │ │ ├── 305_fixed_type_rational_fraction_conversion.sol │ │ │ │ ├── 306_invalid_int_implicit_conversion_from_fixed.sol │ │ │ │ ├── 307_rational_unary_minus_operation.sol │ │ │ │ ├── 308_rational_unary_plus_operation.sol │ │ │ │ ├── 312_leading_zero_rationals_convert.sol │ │ │ │ ├── 313_fixed_type_size_capabilities.sol │ │ │ │ ├── 314_fixed_type_zero_handling.sol │ │ │ │ ├── 315_fixed_type_invalid_implicit_conversion_size.sol │ │ │ │ ├── 316_fixed_type_invalid_implicit_conversion_lost_data.sol │ │ │ │ ├── 317_fixed_type_valid_explicit_conversions.sol │ │ │ │ ├── 318_invalid_array_declaration_with_rational.sol │ │ │ │ ├── 319_invalid_array_declaration_with_signed_fixed_type.sol │ │ │ │ ├── 320_invalid_array_declaration_with_unsigned_fixed_type.sol │ │ │ │ ├── 321_rational_to_bytes_implicit_conversion.sol │ │ │ │ ├── 322_fixed_to_bytes_implicit_conversion.sol │ │ │ │ ├── 323_mapping_with_fixed_literal.sol │ │ │ │ ├── 324_fixed_points_inside_structs.sol │ │ │ │ ├── 327_rational_index_access.sol │ │ │ │ ├── 328_rational_to_fixed_literal_expression.sol │ │ │ │ ├── 329_rational_as_exponent_value_signed.sol │ │ │ │ ├── 330_rational_as_exponent_value_unsigned.sol │ │ │ │ ├── 331_rational_as_exponent_half.sol │ │ │ │ ├── 332_rational_as_exponent_value_neg_quarter.sol │ │ │ │ ├── 333_fixed_point_casting_exponents_15.sol │ │ │ │ ├── 334_fixed_point_casting_exponents_neg.sol │ │ │ │ ├── 338_rational_bitnot_unary_operation.sol │ │ │ │ ├── 339_rational_bitor_binary_operation.sol │ │ │ │ ├── 340_rational_bitxor_binary_operation.sol │ │ │ │ ├── 341_rational_bitand_binary_operation.sol │ │ │ │ ├── 342_missing_bool_conversion.sol │ │ │ │ ├── 343_integer_and_fixed_interaction.sol │ │ │ │ ├── 344_one_divided_by_three_integer_conversion.sol │ │ │ │ ├── 345_unused_return_value.sol │ │ │ │ ├── 346_unused_return_value_send.sol │ │ │ │ ├── 347_unused_return_value_call.sol │ │ │ │ ├── 348_unused_return_value_call_value.sol │ │ │ │ ├── 350_unused_return_value_delegatecall.sol │ │ │ │ ├── 351_callcode_deprecated.sol │ │ │ │ ├── 353_callcode_not_deprecated_as_function.sol │ │ │ │ ├── 354_payable_in_library.sol │ │ │ │ ├── 355_payable_external.sol │ │ │ │ ├── 356_payable_internal.sol │ │ │ │ ├── 357_payable_private.sol │ │ │ │ ├── 358_illegal_override_payable.sol │ │ │ │ ├── 359_illegal_override_payable_nonpayable.sol │ │ │ │ ├── 360_function_variable_mixin.sol │ │ │ │ ├── 361_calling_payable.sol │ │ │ │ ├── 362_calling_nonpayable.sol │ │ │ │ ├── 363_non_payable_constructor.sol │ │ │ │ ├── 366_invalid_array_as_statement.sol │ │ │ │ ├── 367_using_directive_for_missing_selftype.sol │ │ │ │ ├── 368_shift_constant_left_negative_rvalue.sol │ │ │ │ ├── 369_shift_constant_right_negative_rvalue.sol │ │ │ │ ├── 370_shift_constant_left_excessive_rvalue.sol │ │ │ │ ├── 371_shift_constant_right_excessive_rvalue.sol │ │ │ │ ├── 372_shift_constant_right_fractional.sol │ │ │ │ ├── 396_invalid_mobile_type.sol │ │ │ │ ├── 397_warns_msg_value_in_non_payable_public_function.sol │ │ │ │ ├── 398_does_not_warn_msg_value_in_payable_function.sol │ │ │ │ ├── 399_does_not_warn_msg_value_in_internal_function.sol │ │ │ │ ├── 400_does_not_warn_msg_value_in_library.sol │ │ │ │ ├── 401_does_not_warn_msg_value_in_modifier_following_non_payable_public_function.sol │ │ │ │ ├── 402_assignment_to_constant.sol │ │ │ │ ├── 403_return_structs.sol │ │ │ │ ├── 404_read_returned_struct.sol │ │ │ │ ├── 405_address_checksum_type_deduction.sol │ │ │ │ ├── 406_invalid_address_checksum.sol │ │ │ │ ├── 407_invalid_address_no_checksum.sol │ │ │ │ ├── 408_invalid_address_length_short.sol │ │ │ │ ├── 409_invalid_address_length_long.sol │ │ │ │ ├── 410_string_literal_not_convertible_to_address_as_assignment.sol │ │ │ │ ├── 411_string_literal_not_convertible_to_address_as_return_value.sol │ │ │ │ ├── 412_early_exit_on_fatal_errors.sol │ │ │ │ ├── 413_address_methods.sol │ │ │ │ ├── 414_interface.sol │ │ │ │ ├── 415_interface_functions.sol │ │ │ │ ├── 416_interface_function_bodies.sol │ │ │ │ ├── 417_interface_events.sol │ │ │ │ ├── 418_interface_inheritance.sol │ │ │ │ ├── 419_interface_structs.sol │ │ │ │ ├── 420_interface_variables.sol │ │ │ │ ├── 421_interface_function_parameters.sol │ │ │ │ ├── 422_interface_enums.sol │ │ │ │ ├── 423_using_interface.sol │ │ │ │ ├── 424_using_interface_complex.sol │ │ │ │ ├── 425_interface_implement_public_contract.sol │ │ │ │ ├── 426_throw_is_deprecated.sol │ │ │ │ ├── 428_bare_revert.sol │ │ │ │ ├── 429_revert_with_reason.sol │ │ │ │ ├── 431_bare_assert.sol │ │ │ │ ├── 432_bare_require.sol │ │ │ │ ├── 433_pure_statement_in_for_loop.sol │ │ │ │ ├── 434_pure_statement_check_for_regular_for_loop.sol │ │ │ │ ├── 438_unused_unnamed_function_parameter.sol │ │ │ │ ├── 441_unused_unnamed_return_parameter.sol │ │ │ │ ├── 442_named_return_parameter.sol │ │ │ │ ├── 443_named_return_parameter_with_explicit_return.sol │ │ │ │ ├── 444_unnamed_return_parameter_with_explicit_return.sol │ │ │ │ ├── 445_no_unused_warning_interface_arguments.sol │ │ │ │ ├── 446_no_unused_warning_abstract_arguments.sol │ │ │ │ ├── 447_no_unused_warnings.sol │ │ │ │ ├── 459_function_overload_is_not_shadowing.sol │ │ │ │ ├── 460_function_override_is_not_shadowing.sol │ │ │ │ ├── 461_event_parameter_cannot_shadow_state_variable.sol │ │ │ │ ├── 462_callable_crash.sol │ │ │ │ ├── 466_does_not_error_transfer_payable_fallback.sol │ │ │ │ ├── 467_does_not_error_transfer_regular_function.sol │ │ │ │ ├── 470_specified_storage_no_warn.sol │ │ │ │ ├── 471_unspecified_storage_fail.sol │ │ │ │ ├── 473_storage_location_non_array_or_struct_disallowed.sol │ │ │ │ ├── 474_storage_location_non_array_or_struct_disallowed_is_not_fatal.sol │ │ │ │ ├── 475_implicit_conversion_disallowed.sol │ │ │ │ ├── 476_too_large_arrays_for_calldata_external.sol │ │ │ │ ├── 477_too_large_arrays_for_calldata_internal.sol │ │ │ │ ├── 478_too_large_arrays_for_calldata_public.sol │ │ │ │ ├── 479_explicit_literal_to_memory_string_assignment.sol │ │ │ │ ├── 480_explicit_literal_to_storage_string_assignment.sol │ │ │ │ ├── 481_explicit_literal_to_unspecified_string_assignment.sol │ │ │ │ ├── 482_explicit_literal_to_unspecified_string.sol │ │ │ │ ├── 483_modifiers_access_storage_pointer.sol │ │ │ │ ├── 484_function_types_selector_1.sol │ │ │ │ ├── 485_function_types_selector_2.sol │ │ │ │ ├── 486_function_types_selector_3.sol │ │ │ │ ├── 487_function_types_selector_4.sol │ │ │ │ ├── 488_function_types_selector_5.sol │ │ │ │ ├── 489_function_types_selector_6.sol │ │ │ │ ├── 490_function_types_selector_7.sol │ │ │ │ ├── 491_using_this_in_constructor.sol │ │ │ │ ├── 492_do_not_crash_on_not_lvalue.sol │ │ │ │ ├── 493_builtin_keccak256_reject_gas.sol │ │ │ │ ├── 494_builtin_sha256_reject_gas.sol │ │ │ │ ├── 495_builtin_ripemd160_reject_gas.sol │ │ │ │ ├── 496_builtin_ecrecover_reject_gas.sol │ │ │ │ ├── 497_gasleft.sol │ │ │ │ ├── 498_msg_gas_deprecated.sol │ │ │ │ ├── 500_gasleft_shadowing_1.sol │ │ │ │ ├── 501_gasleft_shadowing_2.sol │ │ │ │ ├── 502_builtin_keccak256_reject_value.sol │ │ │ │ ├── 503_builtin_sha256_reject_value.sol │ │ │ │ ├── 504_builtin_ripemd160_reject_value.sol │ │ │ │ ├── 505_builtin_ecrecover_reject_value.sol │ │ │ │ ├── 511_library_function_without_implementation_public.sol │ │ │ │ ├── 512_library_function_without_implementation_internal.sol │ │ │ │ ├── 513_library_function_without_implementation_private.sol │ │ │ │ ├── 514_using_for_with_non_library.sol │ │ │ │ ├── 523_reject_interface_creation.sol │ │ │ │ ├── 525_reject_interface_constructors.sol │ │ │ │ ├── 526_fallback_marked_external.sol │ │ │ │ ├── 527_fallback_marked_internal.sol │ │ │ │ ├── 528_fallback_marked_private.sol │ │ │ │ ├── 529_fallback_marked_public.sol │ │ │ │ ├── 530_tuple_invalid_literal_too_large_for_uint.sol │ │ │ │ ├── 531_tuple_invalid_literal_too_large_unassigned.sol │ │ │ │ ├── 532_tuple_invalid_literal_too_large_for_uint_multi.sol │ │ │ │ ├── 533_tuple_invalid_literal_too_large_exp.sol │ │ │ │ ├── 534_tuple_invalid_literal_too_large_expression.sol │ │ │ │ ├── 535_address_overload_resolution.sol │ │ │ │ ├── 536_array_length_invalid_expression_negative_bool.sol │ │ │ │ ├── 537_array_length_invalid_expression_int_divides_bool.sol │ │ │ │ ├── 538_array_length_invalid_expression_bool_divides_int.sol │ │ │ │ ├── 539_array_length_invalid_expression_scientific_literal.sol │ │ │ │ ├── 540_array_length_invalid_expression_division_by_zero.sol │ │ │ │ ├── 541_warn_about_address_members_on_contract_balance.sol │ │ │ │ ├── 542_warn_about_address_members_on_contract_transfer.sol │ │ │ │ ├── 543_warn_about_address_members_on_contract_send.sol │ │ │ │ ├── 544_warn_about_address_members_on_contract_call.sol │ │ │ │ ├── 545_warn_about_address_members_on_contract_callcode.sol │ │ │ │ ├── 546_warn_about_address_members_on_contract_delegatecall.sol │ │ │ │ ├── 547_warn_about_address_members_on_non_this_contract_balance.sol │ │ │ │ ├── 548_warn_about_address_members_on_non_this_contract_transfer.sol │ │ │ │ ├── 549_warn_about_address_members_on_non_this_contract_send.sol │ │ │ │ ├── 550_warn_about_address_members_on_non_this_contract_call.sol │ │ │ │ ├── 551_warn_about_address_members_on_non_this_contract_callcode.sol │ │ │ │ ├── 552_warn_about_address_members_on_non_this_contract_delegatecall.sol │ │ │ │ ├── 559_no_warning_for_using_members_that_look_like_address_members.sol │ │ │ │ ├── 568_blockhash.sol │ │ │ │ ├── 569_block_blockhash_deprecated.sol │ │ │ │ ├── 570_function_type_undeclared_type.sol │ │ │ │ ├── 571_function_type_undeclared_type_external.sol │ │ │ │ ├── 572_function_type_undeclared_type_multi_nested.sol │ │ │ │ ├── 573_similar_name_longer_than_80_not_suggested.sol │ │ │ │ ├── 574_similar_name_shorter_than_80_suggested.sol │ │ │ │ ├── 575_member_member_getter_call_without_parentheses.sol │ │ │ │ ├── 576_member_getter_call_without_parentheses.sol │ │ │ │ ├── 577_member_getter_call_without_parentheses_missing_function.sol │ │ │ │ ├── 578_private_member_getter_call_without_parentheses.sol │ │ │ │ ├── 579_member_getter_call_without_parentheses_private_function.sol │ │ │ │ ├── 580_improve_name_suggestion_one_and_two_letters.sol │ │ │ │ ├── 581_improve_name_suggestion_three_letters.sol │ │ │ │ ├── 582_improve_name_suggestion_four_letters.sol │ │ │ │ ├── 583_abi_encode_packed_with_rational_number_constant.sol │ │ │ │ ├── 584_abi_decode_with_tuple_of_other_than_types.sol │ │ │ │ ├── 585_abi_decode_with_unsupported_types.sol │ │ │ │ ├── 589_error_index_access.sol │ │ │ │ ├── 590_event_index_access.sol │ │ │ │ ├── 591_access_to_internal_variable.sol │ │ │ │ ├── array_length_fractional_computed.sol │ │ │ │ ├── call_option_value_on_library_function.sol │ │ │ │ ├── compoundAssignment/ │ │ │ │ │ ├── incomp_types.sol │ │ │ │ │ ├── tuple.sol │ │ │ │ │ └── tuple_invalid_inline_array_type.sol │ │ │ │ ├── constant_forward_reference_struct.sol │ │ │ │ ├── constant_mapping.sol │ │ │ │ ├── constant_nested_mapping.sol │ │ │ │ ├── erc7201_builtin_const_var_assignment.sol │ │ │ │ ├── erc7201_builtin_invalid_member_gas.sol │ │ │ │ ├── erc7201_builtin_invalid_member_value.sol │ │ │ │ ├── free_and_constant.sol │ │ │ │ ├── hash_collision_in_abstract_contract.sol │ │ │ │ ├── invalidArgs/ │ │ │ │ │ ├── creating_memory_array.sol │ │ │ │ │ ├── creating_struct.sol │ │ │ │ │ ├── creating_struct_members_skipped.sol │ │ │ │ │ └── explicit_conversions.sol │ │ │ │ ├── invalidTypes/ │ │ │ │ │ ├── conditional_expression.sol │ │ │ │ │ └── constructor_call.sol │ │ │ │ ├── no_effect_statements.sol │ │ │ │ ├── shadowsBuiltin/ │ │ │ │ │ ├── events.sol │ │ │ │ │ ├── functions.sol │ │ │ │ │ ├── global_scope.sol │ │ │ │ │ ├── ignores_constructor.sol │ │ │ │ │ ├── ignores_struct.sol │ │ │ │ │ ├── illegal_names_assembly_functions.sol │ │ │ │ │ ├── illegal_names_assembly_identifier.sol │ │ │ │ │ ├── illegal_names_function_parameters.sol │ │ │ │ │ ├── illegal_names_library_using_for.sol │ │ │ │ │ ├── illegal_names_using_for.sol │ │ │ │ │ ├── parameters.sol │ │ │ │ │ ├── return_parameters.sol │ │ │ │ │ ├── storage_variables.sol │ │ │ │ │ ├── this_super.sol │ │ │ │ │ └── variables.sol │ │ │ │ ├── shift_warn_literal_large_shift_amount.sol │ │ │ │ ├── typeChecking/ │ │ │ │ │ ├── function_call.sol │ │ │ │ │ ├── library_instances.sol │ │ │ │ │ ├── return.sol │ │ │ │ │ ├── return_tuple_not_convertible.sol │ │ │ │ │ ├── return_wrong_number.sol │ │ │ │ │ └── return_wrong_type.sol │ │ │ │ └── warnUnused/ │ │ │ │ ├── function_parameter.sol │ │ │ │ ├── local.sol │ │ │ │ ├── local_assignment.sol │ │ │ │ └── return_parameter.sol │ │ │ ├── operators/ │ │ │ │ ├── calling_operator_binary_user_defined_not_available.sol │ │ │ │ ├── calling_operator_unary_user_defined_not_available.sol │ │ │ │ ├── negation.sol │ │ │ │ ├── signed_rational_modulus.sol │ │ │ │ ├── transient_value_type.sol │ │ │ │ └── userDefined/ │ │ │ │ ├── calling_operator.sol │ │ │ │ ├── calling_operator_as_attached_function_via_function_name.sol │ │ │ │ ├── calling_operator_as_attached_function_via_operator_name.sol │ │ │ │ ├── calling_operator_defined_separately_from_type.sol │ │ │ │ ├── calling_operator_defined_separately_from_type_and_binding.sol │ │ │ │ ├── calling_operator_imported.sol │ │ │ │ ├── calling_operator_imported_non_global.sol │ │ │ │ ├── calling_operator_imported_transitively.sol │ │ │ │ ├── calling_operator_imported_transitively_non_global.sol │ │ │ │ ├── calling_operator_in_constant_initialization.sol │ │ │ │ ├── calling_operator_non_global.sol │ │ │ │ ├── calling_operator_that_deploys_contract.sol │ │ │ │ ├── calling_operator_that_makes_external_call.sol │ │ │ │ ├── calling_operator_that_makes_pure_external_call.sol │ │ │ │ ├── calling_operator_that_makes_view_external_call.sol │ │ │ │ ├── calling_operator_with_implicit_conversion.sol │ │ │ │ ├── defining_operator_for_builtin_types.sol │ │ │ │ ├── defining_operator_for_contract.sol │ │ │ │ ├── defining_operator_for_enum.sol │ │ │ │ ├── defining_operator_for_error.sol │ │ │ │ ├── defining_operator_for_event.sol │ │ │ │ ├── defining_operator_for_interface.sol │ │ │ │ ├── defining_operator_for_library.sol │ │ │ │ ├── defining_operator_for_struct.sol │ │ │ │ ├── defining_operator_for_wildcard_type_at_contract_level.sol │ │ │ │ ├── defining_operator_for_wildcard_type_at_file_level.sol │ │ │ │ ├── implementing_operator_with_attached_free_function.sol │ │ │ │ ├── implementing_operator_with_builtin_abi_encode.sol │ │ │ │ ├── implementing_operator_with_builtin_keccak256.sol │ │ │ │ ├── implementing_operator_with_builtin_revert.sol │ │ │ │ ├── implementing_operator_with_contract_function_at_contract_level.sol │ │ │ │ ├── implementing_operator_with_contract_function_at_file_level.sol │ │ │ │ ├── implementing_operator_with_error.sol │ │ │ │ ├── implementing_operator_with_event.sol │ │ │ │ ├── implementing_operator_with_function_pointer.sol │ │ │ │ ├── implementing_operator_with_function_shadowing_builtin_keccak256.sol │ │ │ │ ├── implementing_operator_with_library.sol │ │ │ │ ├── implementing_operator_with_library_function_at_contract_level.sol │ │ │ │ ├── implementing_operator_with_library_function_at_file_level.sol │ │ │ │ ├── implementing_operator_with_library_function_private_outside_of_library.sol │ │ │ │ ├── implementing_operator_with_non_pure_function.sol │ │ │ │ ├── implementing_operator_with_non_pure_function_on_built_in_type_non_global.sol │ │ │ │ ├── implementing_operator_with_overloaded_function.sol │ │ │ │ ├── implementing_operator_with_privately_overloaded_function.sol │ │ │ │ ├── implementing_operator_with_unqualified_library_function_at_file_level.sol │ │ │ │ ├── implementing_operator_with_unqualified_library_function_in_library.sol │ │ │ │ ├── multiple_operator_definitions_different_functions_global_and_non_global_different_files.sol │ │ │ │ ├── multiple_operator_definitions_different_functions_global_non_global.sol │ │ │ │ ├── multiple_operator_definitions_different_functions_non_global_and_global_different_files.sol │ │ │ │ ├── multiple_operator_definitions_different_functions_same_directive.sol │ │ │ │ ├── multiple_operator_definitions_different_functions_same_directive_operator_not_used.sol │ │ │ │ ├── multiple_operator_definitions_on_file_and_contract_level.sol │ │ │ │ ├── multiple_operator_definitions_same_function_different_levels_free_function.sol │ │ │ │ ├── multiple_operator_definitions_same_function_different_levels_library_function.sol │ │ │ │ ├── multiple_operator_definitions_same_function_same_directive.sol │ │ │ │ ├── multiple_operator_definitions_same_function_separate_directives.sol │ │ │ │ ├── operator_overloading.sol │ │ │ │ ├── operator_parsing_function_name_missing.sol │ │ │ │ ├── operator_parsing_no_brace.sol │ │ │ │ ├── operator_parsing_non_user_definable.sol │ │ │ │ ├── operator_parsing_not_an_operator.sol │ │ │ │ ├── operator_parsing_operator_name_empty_string.sol │ │ │ │ ├── operator_parsing_operator_name_missing.sol │ │ │ │ ├── operator_parsing_operator_named_as.sol │ │ │ │ ├── operator_returning_wrong_types.sol │ │ │ │ ├── operator_taking_and_returning_types_not_matching_using_for.sol │ │ │ │ ├── operator_taking_no_parameters_binary.sol │ │ │ │ ├── operator_taking_no_parameters_unary.sol │ │ │ │ ├── operator_taking_or_returning_different_types.sol │ │ │ │ ├── operator_taking_two_parameters_unary.sol │ │ │ │ ├── using_for_attaching_functions_and_defining_operators_same_directive.sol │ │ │ │ ├── using_for_with_operator_at_contract_level_for_contract_level_type.sol │ │ │ │ ├── using_for_with_operator_at_contract_level_global.sol │ │ │ │ ├── using_for_with_operator_at_contract_level_global_different_file.sol │ │ │ │ ├── using_for_with_operator_at_contract_level_in_base_contract.sol │ │ │ │ ├── using_for_with_operator_at_contract_level_in_interface.sol │ │ │ │ ├── using_for_with_operator_at_file_level_for_contract_level_type.sol │ │ │ │ ├── using_for_with_operator_at_file_level_for_contract_level_type_non_global.sol │ │ │ │ ├── using_for_with_operator_at_file_level_global_and_non_global.sol │ │ │ │ ├── using_for_with_operator_at_file_level_global_different_file.sol │ │ │ │ └── using_for_with_operator_at_file_level_global_unary_and_non_global_binary_same_file.sol │ │ │ ├── parsing/ │ │ │ │ ├── address_constant_payable.sol │ │ │ │ ├── address_function_arguments_and_returns.sol │ │ │ │ ├── address_in_struct.sol │ │ │ │ ├── address_invalid_state_mutability.sol │ │ │ │ ├── address_nonpayable.sol │ │ │ │ ├── address_payable.sol │ │ │ │ ├── address_payable_constant.sol │ │ │ │ ├── address_payable_conversion.sol │ │ │ │ ├── address_payable_function_type.sol │ │ │ │ ├── address_payable_library.sol │ │ │ │ ├── address_payable_local.sol │ │ │ │ ├── address_payable_state_variable.sol │ │ │ │ ├── address_payable_struct.sol │ │ │ │ ├── address_payable_type_expression.sol │ │ │ │ ├── address_public_payable_error.sol │ │ │ │ ├── array_range_and_ternary.sol │ │ │ │ ├── array_range_conversion.sol │ │ │ │ ├── array_range_nested.sol │ │ │ │ ├── array_range_nested_invalid.sol │ │ │ │ ├── array_range_no_start.sol │ │ │ │ ├── array_type_range.sol │ │ │ │ ├── arrays_in_events.sol │ │ │ │ ├── arrays_in_expressions.sol │ │ │ │ ├── arrays_in_storage.sol │ │ │ │ ├── assembly_evmasm_type.sol │ │ │ │ ├── assembly_invalid_type.sol │ │ │ │ ├── calling_function.sol │ │ │ │ ├── comment_end_with_double_star.sol │ │ │ │ ├── conditional_multiple.sol │ │ │ │ ├── conditional_true_false_literal.sol │ │ │ │ ├── conditional_with_assignment.sol │ │ │ │ ├── conditional_with_constants.sol │ │ │ │ ├── conditional_with_variables.sol │ │ │ │ ├── constant_is_keyword.sol │ │ │ │ ├── constant_state_modifier.sol │ │ │ │ ├── constructor_allowed_this.sol │ │ │ │ ├── constructor_internal_internal.sol │ │ │ │ ├── constructor_internal_public.sol │ │ │ │ ├── constructor_payable_payable.sol │ │ │ │ ├── constructor_public_internal.sol │ │ │ │ ├── constructor_public_public.sol │ │ │ │ ├── constructor_super.sol │ │ │ │ ├── contract_named_transient.sol │ │ │ │ ├── declaring_fixed_and_ufixed_variables.sol │ │ │ │ ├── declaring_fixed_literal_variables.sol │ │ │ │ ├── elementary_non_address_state_mutability_argument.sol │ │ │ │ ├── elementary_non_address_state_mutability_file_var.sol │ │ │ │ ├── elementary_non_address_state_mutability_local.sol │ │ │ │ ├── elementary_non_address_state_mutability_return.sol │ │ │ │ ├── elementary_non_address_state_mutability_state_variable.sol │ │ │ │ ├── else_if_statement.sol │ │ │ │ ├── emit_without_event.sol │ │ │ │ ├── empty_comment.sol │ │ │ │ ├── empty_enum.sol │ │ │ │ ├── empty_function.sol │ │ │ │ ├── enum_from_interface.sol │ │ │ │ ├── enum_from_interface_in_library.sol │ │ │ │ ├── enum_from_library.sol │ │ │ │ ├── enum_inheritance_contract.sol │ │ │ │ ├── enum_inheritance_interface.sol │ │ │ │ ├── enum_valid_declaration.sol │ │ │ │ ├── event.sol │ │ │ │ ├── event_arguments.sol │ │ │ │ ├── event_arguments_indexed.sol │ │ │ │ ├── event_with_no_argument_list.sol │ │ │ │ ├── exp_expression.sol │ │ │ │ ├── external_function.sol │ │ │ │ ├── external_variable.sol │ │ │ │ ├── fallback_function.sol │ │ │ │ ├── fixed_literal_with_double_radix.sol │ │ │ │ ├── for_loop_simple_initexpr.sol │ │ │ │ ├── for_loop_simple_noexpr.sol │ │ │ │ ├── for_loop_single_stmt_body.sol │ │ │ │ ├── for_loop_vardef_initexpr.sol │ │ │ │ ├── from_is_not_keyword.sol │ │ │ │ ├── function_no_body.sol │ │ │ │ ├── function_normal_comments.sol │ │ │ │ ├── function_type_as_parameter.sol │ │ │ │ ├── function_type_as_storage_variable.sol │ │ │ │ ├── function_type_as_storage_variable_with_assignment.sol │ │ │ │ ├── function_type_as_storage_variable_with_modifiers.sol │ │ │ │ ├── function_type_in_expression.sol │ │ │ │ ├── function_type_in_struct.sol │ │ │ │ ├── function_type_multiple_mutability.sol │ │ │ │ ├── function_type_multiple_visibility.sol │ │ │ │ ├── function_type_state_variable.sol │ │ │ │ ├── if_statement.sol │ │ │ │ ├── import_complex.sol │ │ │ │ ├── import_complex_invalid_from.sol │ │ │ │ ├── import_complex_without_from.sol │ │ │ │ ├── import_empty.sol │ │ │ │ ├── import_invalid_token.sol │ │ │ │ ├── import_simple.sol │ │ │ │ ├── inline_array_declaration.sol │ │ │ │ ├── inline_array_empty_cells_check_lvalue.sol │ │ │ │ ├── inline_array_empty_cells_check_without_lvalue.sol │ │ │ │ ├── interface_basic.sol │ │ │ │ ├── invalid_fixed_conversion_leading_zeroes_check.sol │ │ │ │ ├── invalid_function_parameter_and_return_var_indexed.sol │ │ │ │ ├── invalid_function_parameter_and_return_var_mutability.sol │ │ │ │ ├── invalid_state_variable_location.sol │ │ │ │ ├── invalid_variable_indexed.sol │ │ │ │ ├── invalid_variable_mutability.sol │ │ │ │ ├── invalid_variable_named_unicode.sol │ │ │ │ ├── lexer_numbers_with_underscores_decimal.sol │ │ │ │ ├── lexer_numbers_with_underscores_decimal_fail.sol │ │ │ │ ├── lexer_numbers_with_underscores_fixed.sol │ │ │ │ ├── lexer_numbers_with_underscores_fixed_fail.sol │ │ │ │ ├── lexer_numbers_with_underscores_hex.sol │ │ │ │ ├── lexer_numbers_with_underscores_hex_fail.sol │ │ │ │ ├── library_simple.sol │ │ │ │ ├── literal_constants_with_ether_subdenominations.sol │ │ │ │ ├── literal_constants_with_ether_subdenominations_in_expressions.sol │ │ │ │ ├── local_const_variable.sol │ │ │ │ ├── location_specifiers_for_file_level_var.sol │ │ │ │ ├── location_specifiers_for_fn_returns_multi.sol │ │ │ │ ├── location_specifiers_for_locals.sol │ │ │ │ ├── location_specifiers_for_locals_multi.sol │ │ │ │ ├── location_specifiers_for_params.sol │ │ │ │ ├── location_specifiers_for_params_multi.sol │ │ │ │ ├── location_specifiers_for_state_variables.sol │ │ │ │ ├── location_specifiers_for_state_variables_multi.sol │ │ │ │ ├── location_specifiers_with_var.sol │ │ │ │ ├── malformed_enum_declaration.sol │ │ │ │ ├── mapping.sol │ │ │ │ ├── mapping_and_array_of_functions.sol │ │ │ │ ├── mapping_from_address_payable.sol │ │ │ │ ├── mapping_in_struct.sol │ │ │ │ ├── mapping_nonelementary_key_1.sol │ │ │ │ ├── mapping_nonelementary_key_2.sol │ │ │ │ ├── mapping_nonelementary_key_3.sol │ │ │ │ ├── mapping_nonelementary_key_4.sol │ │ │ │ ├── mapping_to_mapping_in_struct.sol │ │ │ │ ├── mapping_with_names_1.sol │ │ │ │ ├── mapping_with_names_2.sol │ │ │ │ ├── mapping_with_names_3.sol │ │ │ │ ├── mapping_with_names_5.sol │ │ │ │ ├── mapping_with_names_6.sol │ │ │ │ ├── mapping_with_names_7.sol │ │ │ │ ├── mapping_with_names_8.sol │ │ │ │ ├── mapping_with_names_conflict_1.sol │ │ │ │ ├── mapping_with_names_conflict_2.sol │ │ │ │ ├── mapping_with_names_conflict_3.sol │ │ │ │ ├── mapping_with_names_conflict_4.sol │ │ │ │ ├── mapping_with_names_conflict_5.sol │ │ │ │ ├── mapping_with_names_conflict_6.sol │ │ │ │ ├── mapping_with_names_func_param_1.sol │ │ │ │ ├── mapping_with_names_func_param_2.sol │ │ │ │ ├── mapping_with_names_func_param_3.sol │ │ │ │ ├── mapping_with_names_func_param_4.sol │ │ │ │ ├── mapping_with_names_func_param_5.sol │ │ │ │ ├── mapping_with_names_func_param_6.sol │ │ │ │ ├── mapping_with_names_func_param_7.sol │ │ │ │ ├── mapping_with_names_func_type_param_1.sol │ │ │ │ ├── mapping_with_names_func_type_param_2.sol │ │ │ │ ├── mapping_with_names_func_type_param_3.sol │ │ │ │ ├── mapping_with_names_func_type_param_4.sol │ │ │ │ ├── mapping_with_names_func_type_param_5.sol │ │ │ │ ├── mapping_with_names_func_type_param_6.sol │ │ │ │ ├── mapping_with_names_func_type_param_7.sol │ │ │ │ ├── mapping_with_names_local_1.sol │ │ │ │ ├── mapping_with_names_local_2.sol │ │ │ │ ├── mapping_with_names_local_3.sol │ │ │ │ ├── mapping_with_names_local_4.sol │ │ │ │ ├── mapping_with_names_local_5.sol │ │ │ │ ├── mapping_with_names_local_6.sol │ │ │ │ ├── mapping_with_names_local_7.sol │ │ │ │ ├── mapping_with_names_local_8.sol │ │ │ │ ├── mapping_with_names_nested_1.sol │ │ │ │ ├── mapping_with_names_nested_2.sol │ │ │ │ ├── mapping_with_names_nested_3.sol │ │ │ │ ├── mapping_with_names_nested_4.sol │ │ │ │ ├── mapping_with_names_nested_5.sol │ │ │ │ ├── mapping_with_names_nested_6.sol │ │ │ │ ├── mapping_with_names_nested_7.sol │ │ │ │ ├── mapping_with_names_nested_8.sol │ │ │ │ ├── mapping_with_names_struct_member_1.sol │ │ │ │ ├── mapping_with_names_struct_member_2.sol │ │ │ │ ├── mapping_with_names_struct_member_3.sol │ │ │ │ ├── mapping_with_names_struct_member_4.sol │ │ │ │ ├── mapping_with_names_struct_member_5.sol │ │ │ │ ├── mapping_with_names_struct_member_6.sol │ │ │ │ ├── mapping_with_names_struct_member_7.sol │ │ │ │ ├── max_depth_reached_1.sol │ │ │ │ ├── max_depth_reached_2.sol │ │ │ │ ├── max_depth_reached_3.sol │ │ │ │ ├── max_depth_reached_4.sol │ │ │ │ ├── missing_argument_in_named_args.sol │ │ │ │ ├── missing_parameter_name_in_named_args.sol │ │ │ │ ├── missing_variable_name_in_declaration.sol │ │ │ │ ├── modifier.sol │ │ │ │ ├── modifier_arguments.sol │ │ │ │ ├── modifier_invocation.sol │ │ │ │ ├── modifier_without_semicolon.sol │ │ │ │ ├── multi_arrays.sol │ │ │ │ ├── multi_variable_declarations.sol │ │ │ │ ├── multiple_event_arg_trailing_comma.sol │ │ │ │ ├── multiple_function_param_trailing_comma.sol │ │ │ │ ├── multiple_functions_natspec_documentation.sol │ │ │ │ ├── multiple_modifier_arg_trailing_comma.sol │ │ │ │ ├── multiple_modifier_overrides.sol │ │ │ │ ├── multiple_mutability_specifiers.sol │ │ │ │ ├── multiple_return_param_trailing_comma.sol │ │ │ │ ├── multiple_state_mutability_specifiers.sol │ │ │ │ ├── new_address_payable.sol │ │ │ │ ├── new_invalid_type_name.sol │ │ │ │ ├── no_function_params.sol │ │ │ │ ├── overloaded_functions.sol │ │ │ │ ├── payable_without_arguments.sol │ │ │ │ ├── placeholder_in_function_context.sol │ │ │ │ ├── pragma_illegal.sol │ │ │ │ ├── scientific_notation.sol │ │ │ │ ├── single_event_arg_trailing_comma.sol │ │ │ │ ├── single_function_param.sol │ │ │ │ ├── single_function_param_trailing_comma.sol │ │ │ │ ├── single_modifier_arg_trailing_comma.sol │ │ │ │ ├── single_return_param_trailing_comma.sol │ │ │ │ ├── smoke_test.sol │ │ │ │ ├── struct_definition.sol │ │ │ │ ├── trailing_comma_in_named_args.sol │ │ │ │ ├── trailing_dot1.sol │ │ │ │ ├── trailing_dot2.sol │ │ │ │ ├── trailing_dot3.sol │ │ │ │ ├── tuples.sol │ │ │ │ ├── tuples_decl_without_rhs.sol │ │ │ │ ├── tuples_without_commas.sol │ │ │ │ ├── two_exact_functions.sol │ │ │ │ ├── unary_plus_expression.sol │ │ │ │ ├── unexpected.sol │ │ │ │ ├── user_defined_value_type.sol │ │ │ │ ├── user_defined_value_type_err.sol │ │ │ │ ├── user_defined_value_type_in_function_err.sol │ │ │ │ ├── var_array.sol │ │ │ │ ├── var_storage_var.sol │ │ │ │ ├── variable_definition_in_mapping.sol │ │ │ │ ├── visibility_specifiers.sol │ │ │ │ ├── while_loop.sol │ │ │ │ ├── wrong_compiler_1.sol │ │ │ │ ├── wrong_compiler_2.sol │ │ │ │ ├── wrong_compiler_3.sol │ │ │ │ └── wrong_compiler_4.sol │ │ │ ├── pragma/ │ │ │ │ ├── blank_space_version.sol │ │ │ │ ├── broken_version_1.sol │ │ │ │ ├── broken_version_2.sol │ │ │ │ ├── broken_version_3.sol │ │ │ │ ├── broken_version_4.sol │ │ │ │ ├── broken_version_5.sol │ │ │ │ ├── broken_version_6.sol │ │ │ │ ├── broken_version_7.sol │ │ │ │ ├── empty_version.sol │ │ │ │ ├── experimental_empty_string_literal.sol │ │ │ │ ├── experimental_multiple_experimental.sol │ │ │ │ ├── experimental_multiple_same_line.sol │ │ │ │ ├── experimental_pragma_duplicate.sol │ │ │ │ ├── experimental_pragma_empty.sol │ │ │ │ ├── experimental_pragma_unknown_string_literal.sol │ │ │ │ ├── experimental_pragma_without_experimental_mode.sol │ │ │ │ ├── experimental_test_warning.sol │ │ │ │ ├── experimental_unknown_number_literal.sol │ │ │ │ ├── experimental_unknown_quoted_string_literal.sol │ │ │ │ ├── invalid_pragma.sol │ │ │ │ ├── invalid_range_conjunction_range_first.sol │ │ │ │ ├── invalid_range_conjunction_range_second.sol │ │ │ │ ├── invalid_range_conjunction_two_ranges.sol │ │ │ │ ├── unknown_pragma.sol │ │ │ │ ├── unterminated_pragma.sol │ │ │ │ ├── unterminated_version.sol │ │ │ │ ├── valid_range_disjunction_range_second.sol │ │ │ │ ├── valid_range_disjunction_two_ranges.sol │ │ │ │ ├── version_check.sol │ │ │ │ ├── version_number_too_large.sol │ │ │ │ └── version_range.sol │ │ │ ├── receiveEther/ │ │ │ │ ├── arguments.sol │ │ │ │ ├── default_visibility.sol │ │ │ │ ├── msg_data_in_receive.sol │ │ │ │ ├── old_syntax.sol │ │ │ │ ├── pure_modifier.sol │ │ │ │ ├── receive_as_function_name.sol │ │ │ │ ├── return_value.sol │ │ │ │ └── view_modifier.sol │ │ │ ├── returnExpressions/ │ │ │ │ ├── single_return_mismatching_number.sol │ │ │ │ ├── single_return_mismatching_number_named.sol │ │ │ │ ├── single_return_mismatching_type.sol │ │ │ │ ├── tuple_return_mismatching_number.sol │ │ │ │ ├── tuple_return_mismatching_number_named.sol │ │ │ │ └── valid_returns.sol │ │ │ ├── revertStatement/ │ │ │ │ ├── at_file_level.sol │ │ │ │ ├── error_used_elsewhere.sol │ │ │ │ ├── in_global_function.sol │ │ │ │ ├── non_called.sol │ │ │ │ ├── non_error.sol │ │ │ │ ├── regular.sol │ │ │ │ ├── require_nested.sol │ │ │ │ ├── revert_event.sol │ │ │ │ ├── revert_revert.sol │ │ │ │ ├── scoped.sol │ │ │ │ ├── using_function.sol │ │ │ │ └── using_struct.sol │ │ │ ├── scoping/ │ │ │ │ ├── access_in_assignment_dynamic_array.sol │ │ │ │ ├── access_in_assignment_struct.sol │ │ │ │ ├── double_function_declaration.sol │ │ │ │ ├── double_stateVariable_declaration.sol │ │ │ │ ├── double_variable_declaration.sol │ │ │ │ ├── double_variable_declaration_disjoint_scope.sol │ │ │ │ ├── double_variable_declaration_disjoint_scope_activation.sol │ │ │ │ ├── double_variable_declaration_same_and_disjoint_scope.sol │ │ │ │ ├── double_variable_declaration_same_scope.sol │ │ │ │ ├── duplicate_contract.sol │ │ │ │ ├── external_library_function_inside_scope.sol │ │ │ │ ├── function_state_variable_conflict.sol │ │ │ │ ├── library_inherited.sol │ │ │ │ ├── library_inherited2.sol │ │ │ │ ├── missing_state_variable.sol │ │ │ │ ├── name_pseudo_shadowing.sol │ │ │ │ ├── name_pseudo_shadowing2.sol │ │ │ │ ├── name_shadowing_function_parameter_name_vs_contract.sol │ │ │ │ ├── name_shadowing_function_parameter_vs_its_function.sol │ │ │ │ ├── name_shadowing_function_parameter_vs_struct_enum.sol │ │ │ │ ├── name_shadowing_function_parameters_parameter_vs_struct_enum.sol │ │ │ │ ├── name_shadowing_function_return_parameter_vs_struct_enum.sol │ │ │ │ ├── name_shadowing_function_type_parameter.sol │ │ │ │ ├── name_shadowing_function_type_return_parameter.sol │ │ │ │ ├── name_shadowing_local_variable_vs_free_function.sol │ │ │ │ ├── name_shadowing_local_variable_vs_functions.sol │ │ │ │ ├── name_shadowing_local_variable_vs_state_variable.sol │ │ │ │ ├── poly_variable_declaration_same_scope.sol │ │ │ │ ├── scoping.sol │ │ │ │ ├── scoping_activation.sol │ │ │ │ ├── scoping_activation_old.sol │ │ │ │ ├── scoping_for.sol │ │ │ │ ├── scoping_for2.sol │ │ │ │ ├── scoping_for3.sol │ │ │ │ ├── scoping_for_decl_in_body.sol │ │ │ │ ├── scoping_old.sol │ │ │ │ ├── scoping_self_use.sol │ │ │ │ ├── state_variable_function_conflict.sol │ │ │ │ └── state_variable_function_conflict_former_crash.sol │ │ │ ├── shifts/ │ │ │ │ └── shift_signed_rvalue.sol │ │ │ ├── sizeLimits/ │ │ │ │ ├── bytecode_too_large.sol │ │ │ │ ├── bytecode_too_large_abiencoder_v1.sol │ │ │ │ ├── bytecode_too_large_byzantium.sol │ │ │ │ ├── bytecode_too_large_homestead.sol │ │ │ │ ├── combined_too_large_paris.sol │ │ │ │ ├── combined_too_large_shanghai.sol │ │ │ │ ├── eof/ │ │ │ │ │ └── bytecode_too_large.sol │ │ │ │ ├── initcode_too_large_paris.sol │ │ │ │ ├── initcode_too_large_shanghai.sol │ │ │ │ ├── more_than_256_declarationerrors.sol │ │ │ │ ├── more_than_256_importerrors.sol │ │ │ │ └── more_than_256_syntaxerrors.sol │ │ │ ├── smoke/ │ │ │ │ └── smoke_test.sol │ │ │ ├── specialFunctions/ │ │ │ │ ├── abi_encodePacked_nested_dynamic_array.sol │ │ │ │ ├── abi_encodePacked_nested_dynamic_array_v2.sol │ │ │ │ ├── abi_encodePacked_structs_v2.sol │ │ │ │ ├── abi_encodePacked_tuple_returned_from_function.sol │ │ │ │ ├── abi_encodePacked_unitary_tuple_returned_from_function.sol │ │ │ │ ├── abi_encodeWithSelector_tuple_returned_from_function.sol │ │ │ │ ├── abi_encodeWithSelector_unitary_tuple_returned_from_function.sol │ │ │ │ ├── abi_encodeWithSignature_tuple_returned_from_function.sol │ │ │ │ ├── abi_encodeWithSignature_unitary_tuple_from_function.sol │ │ │ │ ├── abi_encode_nested_dynamic_array.sol │ │ │ │ ├── abi_encode_nested_dynamic_array_v2.sol │ │ │ │ ├── abi_encode_structs.sol │ │ │ │ ├── abi_encode_structs_abiv2.sol │ │ │ │ ├── abi_encode_tuple_returned_from_function.sol │ │ │ │ ├── abi_encode_unitary_tuple_returned_from_function.sol │ │ │ │ ├── abi_functions_member_access.sol │ │ │ │ ├── abidecode/ │ │ │ │ │ ├── abi_decode_array_of_unitary_tuples.sol │ │ │ │ │ ├── abi_decode_calldata.sol │ │ │ │ │ ├── abi_decode_empty.sol │ │ │ │ │ ├── abi_decode_enum.sol │ │ │ │ │ ├── abi_decode_invalid_arg_count.sol │ │ │ │ │ ├── abi_decode_invalid_arg_type.sol │ │ │ │ │ ├── abi_decode_invalid_argument_array_length_ternary_with_max_keyword.sol │ │ │ │ │ ├── abi_decode_invalid_argument_array_of_tuples.sol │ │ │ │ │ ├── abi_decode_invalid_argument_indexed_array_literal.sol │ │ │ │ │ ├── abi_decode_invalid_argument_indexed_ternary_expression.sol │ │ │ │ │ ├── abi_decode_invalid_argument_ternary_condition_expression.sol │ │ │ │ │ ├── abi_decode_invalid_argument_ternary_expression_inside_parentheses.sol │ │ │ │ │ ├── abi_decode_invalid_argument_ternary_with_side_effect.sol │ │ │ │ │ ├── abi_decode_invalid_argument_tuple_type.sol │ │ │ │ │ ├── abi_decode_invalid_argument_type_expression.sol │ │ │ │ │ ├── abi_decode_member_acess.sol │ │ │ │ │ ├── abi_decode_memory.sol │ │ │ │ │ ├── abi_decode_memory_v2.sol │ │ │ │ │ ├── abi_decode_nested_dynamic_array.sol │ │ │ │ │ ├── abi_decode_nested_dynamic_array_v2.sol │ │ │ │ │ ├── abi_decode_nontuple.sol │ │ │ │ │ ├── abi_decode_simple.sol │ │ │ │ │ ├── abi_decode_single_return.sol │ │ │ │ │ ├── abi_decode_singletontuple.sol │ │ │ │ │ ├── abi_decode_storage.sol │ │ │ │ │ ├── abi_decode_struct.sol │ │ │ │ │ ├── abi_decode_struct_v2.sol │ │ │ │ │ ├── abi_decode_unitary_nested_tuple.sol │ │ │ │ │ └── contract_array.sol │ │ │ │ ├── encodeCall.sol │ │ │ │ ├── encodeCall_fail_args.sol │ │ │ │ ├── encodeCall_fail_args_internal_function_pointer_for_uint.sol │ │ │ │ ├── encodeCall_fail_funType.sol │ │ │ │ ├── encodeCall_nested_tuple.sol │ │ │ │ ├── encodeCall_tuple_incomplete.sol │ │ │ │ ├── encodePacked_array_of_structs.sol │ │ │ │ ├── encodePacked_dynamic_string_array_v2.sol │ │ │ │ ├── encode_array_of_struct.sol │ │ │ │ ├── encodecall_fail_args_internal_struct_for_uint.sol │ │ │ │ ├── functionCallOptions_err.sol │ │ │ │ ├── single_non_bytes_arg.sol │ │ │ │ ├── types_with_unspecified_encoding_internal_functions.sol │ │ │ │ ├── types_with_unspecified_encoding_special_types.sol │ │ │ │ ├── types_with_unspecified_encoding_structs.sol │ │ │ │ ├── types_with_unspecified_encoding_types.sol │ │ │ │ └── types_without_encoding_problems.sol │ │ │ ├── storageLayoutSpecifier/ │ │ │ │ ├── abi_decode.sol │ │ │ │ ├── abstract_contract.sol │ │ │ │ ├── abstract_contract_inheriting_from_non_abstract.sol │ │ │ │ ├── address.sol │ │ │ │ ├── address_constant.sol │ │ │ │ ├── address_non_constant.sol │ │ │ │ ├── array_literal.sol │ │ │ │ ├── assignment.sol │ │ │ │ ├── at_before_layout.sol │ │ │ │ ├── bitwise_negation_after_cast.sol │ │ │ │ ├── bool_constant.sol │ │ │ │ ├── boolean.sol │ │ │ │ ├── builtin_functions.sol │ │ │ │ ├── bytes_constant.sol │ │ │ │ ├── bytes_length_member.sol │ │ │ │ ├── constant_divided_by_its_negation.sol │ │ │ │ ├── constant_divided_by_zero.sol │ │ │ │ ├── constant_from_base_contract.sol │ │ │ │ ├── constant_from_module.sol │ │ │ │ ├── constant_initialized_from_builtin.sol │ │ │ │ ├── constant_initialized_from_cast.sol │ │ │ │ ├── constant_initialized_from_other_constant.sol │ │ │ │ ├── constant_initialized_with_literal_expression.sol │ │ │ │ ├── constant_initialized_with_unlimited_arithmetic_expression.sol │ │ │ │ ├── contract_at_storage_end.sol │ │ │ │ ├── contract_at_storage_end_with_transient_state_variables.sol │ │ │ │ ├── contract_extends_past_storage_end.sol │ │ │ │ ├── contract_named_at.sol │ │ │ │ ├── contract_named_layout.sol │ │ │ │ ├── contract_too_large_for_storage.sol │ │ │ │ ├── contract_with_members_named_layout_and_at.sol │ │ │ │ ├── delete.sol │ │ │ │ ├── division_by_zero.sol │ │ │ │ ├── duplicated_layout_definition.sol │ │ │ │ ├── duplicated_layout_keyword.sol │ │ │ │ ├── enum.sol │ │ │ │ ├── erc7201_builtin_param_constant_variable_comptime.sol │ │ │ │ ├── erc7201_builtin_param_imported_constant_variable_comptime.sol │ │ │ │ ├── erc7201_builtin_param_string_literal_comptime.sol │ │ │ │ ├── function_address.sol │ │ │ │ ├── function_declaration_layout_specified.sol │ │ │ │ ├── function_declaration_layout_with_no_expression.sol │ │ │ │ ├── function_defined_in_other_contract.sol │ │ │ │ ├── function_selector.sol │ │ │ │ ├── hex_address.sol │ │ │ │ ├── hex_string.sol │ │ │ │ ├── hex_string_cast.sol │ │ │ │ ├── immutables.sol │ │ │ │ ├── increment_operator.sol │ │ │ │ ├── inheriting_from_abstract_contract.sol │ │ │ │ ├── inheriting_from_interface.sol │ │ │ │ ├── inheriting_from_itself.sol │ │ │ │ ├── int_constant.sol │ │ │ │ ├── interface.sol │ │ │ │ ├── intermediate_operation_out_of_range.sol │ │ │ │ ├── layout_already_specified_in_ancestor_contract.sol │ │ │ │ ├── layout_bitwise_negation_literal.sol │ │ │ │ ├── layout_fractional_number.sol │ │ │ │ ├── layout_specification_binary_expression.sol │ │ │ │ ├── layout_specification_by_function.sol │ │ │ │ ├── layout_specification_bytes.sol │ │ │ │ ├── layout_specification_constant_in_expression.sol │ │ │ │ ├── layout_specification_max_value.sol │ │ │ │ ├── layout_specification_no_expression.sol │ │ │ │ ├── layout_specification_overflow_value.sol │ │ │ │ ├── layout_specification_underflow_value.sol │ │ │ │ ├── layout_specified_by_ancestor_contract_module.sol │ │ │ │ ├── layout_specified_by_ancestor_contract_multiple_inheritance.sol │ │ │ │ ├── layout_specified_by_attached_library_function.sol │ │ │ │ ├── layout_specified_by_bytes_concat.sol │ │ │ │ ├── layout_specified_by_empty_braces.sol │ │ │ │ ├── layout_specified_by_error.sol │ │ │ │ ├── layout_specified_by_event.sol │ │ │ │ ├── layout_specified_by_expression_not_pure.sol │ │ │ │ ├── layout_specified_by_first_ancestor_contract.sol │ │ │ │ ├── layout_specified_by_function_empty_call_options.sol │ │ │ │ ├── layout_specified_by_function_with_call_options.sol │ │ │ │ ├── layout_specified_by_interface_id.sol │ │ │ │ ├── layout_specified_by_kecak256.sol │ │ │ │ ├── layout_specified_by_last_ancestor_contract.sol │ │ │ │ ├── layout_specified_by_module.sol │ │ │ │ ├── layout_specified_by_other_contract.sol │ │ │ │ ├── layout_specified_by_type.sol │ │ │ │ ├── layout_statement_without_at.sol │ │ │ │ ├── layout_with_inheritance.sol │ │ │ │ ├── library.sol │ │ │ │ ├── literal_cast.sol │ │ │ │ ├── literal_with_underscore.sol │ │ │ │ ├── magic_variables.sol │ │ │ │ ├── multi_token_expression.sol │ │ │ │ ├── natspec.sol │ │ │ │ ├── negative_number.sol │ │ │ │ ├── precompiles.sol │ │ │ │ ├── rational_number_without_fractional_part.sol │ │ │ │ ├── repeated_layout_definition.sol │ │ │ │ ├── same_ancestor_two_contracts.sol │ │ │ │ ├── simple_layout.sol │ │ │ │ ├── state_variable_from_base_contract.sol │ │ │ │ ├── state_variable_getter_from_base_contract.sol │ │ │ │ ├── state_variable_layout_specifier.sol │ │ │ │ ├── string.sol │ │ │ │ ├── struct_defined_in_other_contract.sol │ │ │ │ ├── struct_with_layout_specifier.sol │ │ │ │ ├── ternary_operator.sol │ │ │ │ ├── tuple.sol │ │ │ │ ├── type_uint_max.sol │ │ │ │ ├── user_defined_operators.sol │ │ │ │ ├── user_defined_value_type.sol │ │ │ │ ├── user_defined_value_type_unwrap.sol │ │ │ │ ├── user_defined_value_type_wrap.sol │ │ │ │ ├── value_from_array_literal.sol │ │ │ │ ├── value_from_bytes.sol │ │ │ │ └── warning_near_the_storage_end.sol │ │ │ ├── string/ │ │ │ │ ├── concat/ │ │ │ │ │ ├── string_concat_empty_invalid.sol │ │ │ │ │ ├── string_concat_with_different_parameters.sol │ │ │ │ │ ├── string_concat_wrong_type_bytes_and_strings.sol │ │ │ │ │ ├── string_concat_wrong_type_empty_array_literal.sol │ │ │ │ │ ├── string_concat_wrong_type_misc.sol │ │ │ │ │ ├── string_concat_wrong_type_misc_literals_and_expressions.sol │ │ │ │ │ └── string_concat_wrong_type_zero_literal.sol │ │ │ │ ├── control_character_returned_in_string.sol │ │ │ │ ├── hex_as_identifier.sol │ │ │ │ ├── invalid_legacy_escape.sol │ │ │ │ ├── invalid_utf8_explicit_string.sol │ │ │ │ ├── invalid_utf8_hex_string.sol │ │ │ │ ├── invalid_utf8_implicit_string.sol │ │ │ │ ├── invalid_utf8_in_bytes.sol │ │ │ │ ├── invalid_utf8_sequence.sol │ │ │ │ ├── large_utf8_codepoint.sol │ │ │ │ ├── string_ascii.sol │ │ │ │ ├── string_escapes.sol │ │ │ │ ├── string_multipart_hex_valid_parts.sol │ │ │ │ ├── string_multipart_newline_with_hex_prefix.sol │ │ │ │ ├── string_multipart_newline_without_hex_prefix.sol │ │ │ │ ├── string_multipart_only_hex.sol │ │ │ │ ├── string_multipart_only_regular.sol │ │ │ │ ├── string_multipart_single_line.sol │ │ │ │ ├── string_multipart_unicode.sol │ │ │ │ ├── string_multipart_unicode_mixed.sol │ │ │ │ ├── string_new_line.sol │ │ │ │ ├── string_terminated_by_backslash.sol │ │ │ │ ├── string_unicode.sol │ │ │ │ ├── string_unicode_without_prefix.sol │ │ │ │ ├── string_unterminated.sol │ │ │ │ ├── string_unterminated_no_new_line.sol │ │ │ │ ├── unicode_escape_literals.sol │ │ │ │ ├── unicode_escape_literals_invalid_codepoint.sol │ │ │ │ └── unicode_escape_literals_invalid_format.sol │ │ │ ├── structs/ │ │ │ │ ├── address_member_access.sol │ │ │ │ ├── address_member_declaration.sol │ │ │ │ ├── array_calldata.sol │ │ │ │ ├── calldata.sol │ │ │ │ ├── calldata_array_assign.sol │ │ │ │ ├── calldata_assign.sol │ │ │ │ ├── calldata_dynamic.sol │ │ │ │ ├── calldata_struct_function_type.sol │ │ │ │ ├── calldata_struct_mapping_function.sol │ │ │ │ ├── contract_global_struct_name_clash.sol │ │ │ │ ├── empty_struct.sol │ │ │ │ ├── global_struct.sol │ │ │ │ ├── global_struct_contract_name_clash.sol │ │ │ │ ├── global_struct_shadowing.sol │ │ │ │ ├── global_structs_name_clash.sol │ │ │ │ ├── illegal_names.sol │ │ │ │ ├── member_type_eq_name.sol │ │ │ │ ├── member_type_eq_name_2.sol │ │ │ │ ├── member_type_eq_name_3.sol │ │ │ │ ├── member_type_func.sol │ │ │ │ ├── memory_to_calldata.sol │ │ │ │ ├── recursion/ │ │ │ │ │ ├── multi_struct_composition.sol │ │ │ │ │ ├── parallel_structs.sol │ │ │ │ │ ├── recursive_struct_as_contract_function_parameter.sol │ │ │ │ │ ├── recursive_struct_as_library_function_parameter.sol │ │ │ │ │ ├── recursive_struct_as_memory_library_function_parameter.sol │ │ │ │ │ ├── recursive_struct_forward_reference.sol │ │ │ │ │ ├── recursive_struct_function_pointer.sol │ │ │ │ │ ├── recursive_struct_nested_mapping_memory.sol │ │ │ │ │ ├── recursive_struct_nested_mapping_storage.sol │ │ │ │ │ ├── recursive_struct_with_internal_function_as_library_function_parameter.sol │ │ │ │ │ ├── return_recursive_structs.sol │ │ │ │ │ ├── return_recursive_structs2.sol │ │ │ │ │ ├── return_recursive_structs3.sol │ │ │ │ │ ├── static_array_of_recursive_structs.sol │ │ │ │ │ ├── struct_definition_directly_recursive.sol │ │ │ │ │ ├── struct_definition_directly_recursive_dynamic_array.sol │ │ │ │ │ ├── struct_definition_directly_recursive_fixed_array.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_complex.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_dynamic_array1.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_dynamic_array2.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_dynamic_array3.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_dynamic_multi_array.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_fixed_array1.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_fixed_array2.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_fixed_array3.sol │ │ │ │ │ ├── struct_definition_indirectly_recursive_fixed_multi_array.sol │ │ │ │ │ ├── struct_definition_not_really_recursive.sol │ │ │ │ │ ├── struct_definition_not_really_recursive_array.sol │ │ │ │ │ └── struct_definition_recursion_via_mapping.sol │ │ │ │ └── transient_data_location_member.sol │ │ │ ├── super/ │ │ │ │ ├── super_in_function.sol │ │ │ │ ├── super_in_library.sol │ │ │ │ ├── unimplemented_super_function.sol │ │ │ │ └── unimplemented_super_function_derived.sol │ │ │ ├── tryCatch/ │ │ │ │ ├── almost_call_options.sol │ │ │ │ ├── catch_error.sol │ │ │ │ ├── catch_error_named.sol │ │ │ │ ├── catch_low_level.sol │ │ │ │ ├── creation.sol │ │ │ │ ├── data_location_error_message.sol │ │ │ │ ├── double_panic.sol │ │ │ │ ├── double_panic_correct.sol │ │ │ │ ├── elementary_non_address_state_mutability_catch.sol │ │ │ │ ├── elementary_non_address_state_mutability_try_returns.sol │ │ │ │ ├── empty_catch.sol │ │ │ │ ├── empty_returns.sol │ │ │ │ ├── error_and_panic.sol │ │ │ │ ├── error_with_wrong_type.sol │ │ │ │ ├── invalid_catch_parameter_location_calldata.sol │ │ │ │ ├── invalid_catch_parameter_location_storage.sol │ │ │ │ ├── invalid_error_name.sol │ │ │ │ ├── invalid_returns.sol │ │ │ │ ├── invalid_returns_var_location.sol │ │ │ │ ├── invalid_returns_vars_and_catch_parameter_indexed.sol │ │ │ │ ├── invalid_returns_vars_and_catch_parameter_mutability.sol │ │ │ │ ├── invalid_returns_vars_and_catch_parameter_visibility.sol │ │ │ │ ├── library_call.sol │ │ │ │ ├── low_level_homestead.sol │ │ │ │ ├── low_level_spuriousDragon.sol │ │ │ │ ├── low_level_tangerineWhistle.sol │ │ │ │ ├── low_level_with_wrong_type.sol │ │ │ │ ├── multiple_returns_vars_and_catch_parameter_location.sol │ │ │ │ ├── no_catch.sol │ │ │ │ ├── no_external_call.sol │ │ │ │ ├── no_returns.sol │ │ │ │ ├── no_special.sol │ │ │ │ ├── returns.sol │ │ │ │ ├── returns_memory.sol │ │ │ │ ├── returns_memory_anonymous.sol │ │ │ │ ├── returns_mismatch.sol │ │ │ │ ├── scoping.sol │ │ │ │ ├── simple_catch.sol │ │ │ │ ├── structured_homestead.sol │ │ │ │ ├── structured_spuriousDragon.sol │ │ │ │ ├── structured_tangerineWhistle.sol │ │ │ │ ├── two_catch_clauses.sol │ │ │ │ ├── two_error_catch_clauses.sol │ │ │ │ ├── two_low_level_catch_clauses.sol │ │ │ │ ├── wrong_panic.sol │ │ │ │ └── wrong_panic_2.sol │ │ │ ├── tupleAssignments/ │ │ │ │ ├── assignments_to_tuple_and_non_tuple_expressions_of_tuple_types.sol │ │ │ │ ├── double_storage_crash.sol │ │ │ │ ├── empty_tuple_assignment.sol │ │ │ │ ├── empty_tuples_lhs.sol │ │ │ │ ├── err_fill_assignment.sol │ │ │ │ ├── error_fill.sol │ │ │ │ ├── fixed_byte_array_assignment_in_tuple.sol │ │ │ │ ├── large_component_count.sol │ │ │ │ ├── nested_tuple_to_tuple_assignment.sol │ │ │ │ ├── nowarn_swap_memory.sol │ │ │ │ ├── nowarn_swap_storage_pointers.sol │ │ │ │ ├── tuple_in_tuple_long.sol │ │ │ │ ├── tuple_in_tuple_short.sol │ │ │ │ ├── tuple_to_function_assignment.sol │ │ │ │ └── warn_multiple_storage_storage_copies.sol │ │ │ ├── types/ │ │ │ │ ├── address/ │ │ │ │ │ ├── address_abi_decode.sol │ │ │ │ │ ├── address_binary_operators.sol │ │ │ │ │ ├── address_constant.sol │ │ │ │ │ ├── address_constant_assignment.sol │ │ │ │ │ ├── address_in_struct_fail.sol │ │ │ │ │ ├── address_in_struct_fine.sol │ │ │ │ │ ├── address_literal_to_payable.sol │ │ │ │ │ ├── address_literal_to_payable_err.sol │ │ │ │ │ ├── address_members.sol │ │ │ │ │ ├── address_members_in_contract.sol │ │ │ │ │ ├── address_nonpayable_selfdestruct.sol │ │ │ │ │ ├── address_payable_external_overload.sol │ │ │ │ │ ├── address_payable_internal_overload_nonpayable.sol │ │ │ │ │ ├── address_payable_internal_overload_payable.sol │ │ │ │ │ ├── address_payable_memory_array_conversion.sol │ │ │ │ │ ├── address_payable_public_overload.sol │ │ │ │ │ ├── address_payable_selfdestruct.sol │ │ │ │ │ ├── address_payable_storage_array_conversion.sol │ │ │ │ │ ├── address_payable_storage_array_conversion_fail.sol │ │ │ │ │ ├── address_to_contract.sol │ │ │ │ │ ├── address_to_contract_implicitly.sol │ │ │ │ │ ├── address_to_contract_payable_fallback.sol │ │ │ │ │ ├── address_to_contract_receive.sol │ │ │ │ │ ├── address_to_payable_address.sol │ │ │ │ │ ├── address_to_payable_address_double.sol │ │ │ │ │ ├── address_tuple_fail.sol │ │ │ │ │ ├── address_tuple_fine.sol │ │ │ │ │ ├── address_uint_bytes20_this.sol │ │ │ │ │ ├── address_uint_bytes20_this_to_payable_err.sol │ │ │ │ │ ├── address_zero_to_payable_err.sol │ │ │ │ │ ├── bytes_long_to_payable_address.sol │ │ │ │ │ ├── bytes_short_to_payable_address.sol │ │ │ │ │ ├── bytes_to_payable_address.sol │ │ │ │ │ ├── codehash.sol │ │ │ │ │ ├── codehash_before_constantinople.sol │ │ │ │ │ ├── contract_no_fallback_to_payable_address.sol │ │ │ │ │ ├── contract_non_payable_fallback_to_payable_address.sol │ │ │ │ │ ├── contract_payable_fallback_to_payable_address.sol │ │ │ │ │ ├── contract_payable_fallback_to_payable_address_implicitly.sol │ │ │ │ │ ├── contract_receive_to_payable_address.sol │ │ │ │ │ ├── contract_receive_to_payable_address_implicitly.sol │ │ │ │ │ ├── contract_to_address.sol │ │ │ │ │ ├── contract_to_address_implicitly.sol │ │ │ │ │ ├── contract_type_to_address.sol │ │ │ │ │ ├── conversion.sol │ │ │ │ │ ├── conversion_error.sol │ │ │ │ │ ├── eof/ │ │ │ │ │ │ └── address_members.sol │ │ │ │ │ ├── literal_to_address.sol │ │ │ │ │ ├── literal_to_address_call.sol │ │ │ │ │ ├── literal_to_address_oversized.sol │ │ │ │ │ ├── literal_to_payable_address.sol │ │ │ │ │ ├── literal_to_payable_address_err.sol │ │ │ │ │ ├── nonpayable_address_to_contract_payable_fallback.sol │ │ │ │ │ ├── nonpayable_address_to_contract_receive.sol │ │ │ │ │ ├── payable_address_to_address.sol │ │ │ │ │ ├── payable_conversion.sol │ │ │ │ │ ├── payable_conversion_err.sol │ │ │ │ │ ├── payable_conversion_strict.sol │ │ │ │ │ ├── payable_conversion_strict_err.sol │ │ │ │ │ ├── payable_conversions_literals.sol │ │ │ │ │ ├── payable_to_contract_receive.sol │ │ │ │ │ ├── state_variable_address_payable_transient.sol │ │ │ │ │ ├── state_variable_address_transient_payable.sol │ │ │ │ │ ├── super_to_address.sol │ │ │ │ │ ├── type_type_to_address.sol │ │ │ │ │ └── uint_to_payable_address.sol │ │ │ │ ├── array_index_too_large.sol │ │ │ │ ├── binary_add_op.sol │ │ │ │ ├── bool_ops.sol │ │ │ │ ├── byte.sol │ │ │ │ ├── bytes0.sol │ │ │ │ ├── bytes1_to_uint256.sol │ │ │ │ ├── bytes256.sol │ │ │ │ ├── bytes32_to_uint32.sol │ │ │ │ ├── bytes33.sol │ │ │ │ ├── bytesNN_bitnot.sol │ │ │ │ ├── bytesNN_index_assign.sol │ │ │ │ ├── bytesNN_to_contract.sol │ │ │ │ ├── bytesNN_to_uint_same_size.sol │ │ │ │ ├── bytesNN_upcasting.sol │ │ │ │ ├── bytesNN_with_oversized_hex_string.sol │ │ │ │ ├── call_unimplemented_internal_function.sol │ │ │ │ ├── constant_of_invalid_function_type.sol │ │ │ │ ├── contractTypeType/ │ │ │ │ │ └── members/ │ │ │ │ │ ├── assign_function_via_base_name_to_var.sol │ │ │ │ │ ├── assign_function_via_contract_name_to_var.sol │ │ │ │ │ ├── base_contract.sol │ │ │ │ │ ├── base_contract_invalid.sol │ │ │ │ │ ├── call_function_via_contract_name.sol │ │ │ │ │ ├── call_unimplemented_base.sol │ │ │ │ │ ├── function_selector_via_contract_name.sol │ │ │ │ │ ├── function_selector_via_interface_name.sol │ │ │ │ │ ├── function_via_contract_name_internal.sol │ │ │ │ │ ├── function_via_contract_name_overloaded.sol │ │ │ │ │ ├── function_via_contract_name_private.sol │ │ │ │ │ ├── function_via_contract_name_public.sol │ │ │ │ │ ├── modifier.sol │ │ │ │ │ ├── modifier_base.sol │ │ │ │ │ └── struct_enum.sol │ │ │ │ ├── contract_to_base.sol │ │ │ │ ├── contract_to_base_base.sol │ │ │ │ ├── contract_to_derived.sol │ │ │ │ ├── contract_to_unrelated_contract.sol │ │ │ │ ├── cyclic_dependency_check_on_consts_exhausted.sol │ │ │ │ ├── cyclic_dependency_check_on_consts_good.sol │ │ │ │ ├── cyclic_dependency_check_on_struct_exhausted.sol │ │ │ │ ├── cyclic_dependency_check_on_struct_good.sol │ │ │ │ ├── decimal_literal_to_bytesNN_explicit.sol │ │ │ │ ├── decimal_literal_to_bytesNN_implicit.sol │ │ │ │ ├── empty_tuple_event.sol │ │ │ │ ├── empty_tuple_function.sol │ │ │ │ ├── empty_tuple_lvalue.sol │ │ │ │ ├── empty_tuple_lvalue_array.sol │ │ │ │ ├── encoding_fractional.sol │ │ │ │ ├── encoding_fractional_abiencoderv2.sol │ │ │ │ ├── encoding_packed_fractional.sol │ │ │ │ ├── encoding_packed_fractional_abiencoderv2.sol │ │ │ │ ├── event_with_rational_size_array.sol │ │ │ │ ├── functionTypes/ │ │ │ │ │ ├── function_definition_expression.sol │ │ │ │ │ ├── function_parameter_return_types_fail.sol │ │ │ │ │ ├── function_parameter_return_types_success.sol │ │ │ │ │ ├── function_state_mutability_fail.sol │ │ │ │ │ ├── function_state_mutability_success.sol │ │ │ │ │ └── selector/ │ │ │ │ │ ├── event_error_selector_pure_assignment.sol │ │ │ │ │ ├── function_selector_pure.sol │ │ │ │ │ ├── local_variable_selector_not_pure.sol │ │ │ │ │ ├── state_variable_selector_contract_name.sol │ │ │ │ │ ├── state_variable_selector_not_pure.sol │ │ │ │ │ └── state_variable_selector_super.sol │ │ │ │ ├── function_call_fail.sol │ │ │ │ ├── function_call_fail2.sol │ │ │ │ ├── global_struct_recursive.sol │ │ │ │ ├── hex_literal_bitnot.sol │ │ │ │ ├── hex_literal_to_bytesNN_different_size_explicit.sol │ │ │ │ ├── hex_literal_to_bytesNN_different_size_implicit.sol │ │ │ │ ├── hex_literal_to_bytesNN_same_size_explicit.sol │ │ │ │ ├── hex_literal_to_bytesNN_same_size_implicit.sol │ │ │ │ ├── hex_string_to_bytesNN_different_size_explicit.sol │ │ │ │ ├── hex_string_to_bytesNN_different_size_implicit.sol │ │ │ │ ├── hex_string_to_bytesNN_same_size_explicit.sol │ │ │ │ ├── hex_string_to_bytesNN_same_size_implicit.sol │ │ │ │ ├── index_access_for_bytes.sol │ │ │ │ ├── integer_implicit_err.sol │ │ │ │ ├── library_function_selector.sol │ │ │ │ ├── library_function_selector_internal.sol │ │ │ │ ├── library_function_selector_private_inside.sol │ │ │ │ ├── library_function_selector_private_outside.sol │ │ │ │ ├── library_function_selector_view_pure.sol │ │ │ │ ├── library_internal_call.sol │ │ │ │ ├── library_to_address.sol │ │ │ │ ├── library_to_address_payable.sol │ │ │ │ ├── magic_block.sol │ │ │ │ ├── magic_block_basefee_error.sol │ │ │ │ ├── magic_block_blobbasefee_cancun.sol │ │ │ │ ├── magic_block_blobbasefee_error.sol │ │ │ │ ├── magic_block_istanbul.sol │ │ │ │ ├── magic_block_london.sol │ │ │ │ ├── magic_block_paris.sol │ │ │ │ ├── mapping/ │ │ │ │ │ ├── abstract_constructor_param.sol │ │ │ │ │ ├── access_index_omitted.sol │ │ │ │ │ ├── argument_external.sol │ │ │ │ │ ├── argument_internal.sol │ │ │ │ │ ├── argument_private.sol │ │ │ │ │ ├── argument_public.sol │ │ │ │ │ ├── array_argument_external.sol │ │ │ │ │ ├── array_argument_internal.sol │ │ │ │ │ ├── array_argument_private.sol │ │ │ │ │ ├── array_argument_public.sol │ │ │ │ │ ├── assignment_local.sol │ │ │ │ │ ├── assignment_local_err.sol │ │ │ │ │ ├── assignment_map.sol │ │ │ │ │ ├── assignment_state_variable.sol │ │ │ │ │ ├── assignment_struct.sol │ │ │ │ │ ├── assignment_type_mismatch.sol │ │ │ │ │ ├── constructor_parameter.sol │ │ │ │ │ ├── contract_mapping.sol │ │ │ │ │ ├── contract_mapping_invalid.sol │ │ │ │ │ ├── contract_storage_parameter_with_mapping.sol │ │ │ │ │ ├── enum_mapping.sol │ │ │ │ │ ├── enum_mapping_invalid.sol │ │ │ │ │ ├── error_parameter.sol │ │ │ │ │ ├── event_parameter.sol │ │ │ │ │ ├── function_type_argument_array.sol │ │ │ │ │ ├── function_type_argument_external.sol │ │ │ │ │ ├── function_type_argument_internal.sol │ │ │ │ │ ├── function_type_return_external.sol │ │ │ │ │ ├── function_type_return_internal.sol │ │ │ │ │ ├── int_mapping.sol │ │ │ │ │ ├── library_argument_external.sol │ │ │ │ │ ├── library_argument_internal.sol │ │ │ │ │ ├── library_argument_private.sol │ │ │ │ │ ├── library_argument_public.sol │ │ │ │ │ ├── library_argument_storage.sol │ │ │ │ │ ├── library_array_argument_external.sol │ │ │ │ │ ├── library_array_argument_internal.sol │ │ │ │ │ ├── library_array_argument_private.sol │ │ │ │ │ ├── library_array_argument_public.sol │ │ │ │ │ ├── library_mapping.sol │ │ │ │ │ ├── library_nested_mapping.sol │ │ │ │ │ ├── library_nested_storage.sol │ │ │ │ │ ├── library_return_external.sol │ │ │ │ │ ├── library_return_internal.sol │ │ │ │ │ ├── library_return_private.sol │ │ │ │ │ ├── library_return_public.sol │ │ │ │ │ ├── library_storage_parameter_with_mapping.sol │ │ │ │ │ ├── library_storage_parameter_with_nested_mapping.sol │ │ │ │ │ ├── mapping_array_data_location_function_param_external.sol │ │ │ │ │ ├── mapping_array_return_external.sol │ │ │ │ │ ├── mapping_array_return_internal.sol │ │ │ │ │ ├── mapping_array_return_public.sol │ │ │ │ │ ├── mapping_data_location_calldata.sol │ │ │ │ │ ├── mapping_data_location_default.sol │ │ │ │ │ ├── mapping_data_location_function_param_external.sol │ │ │ │ │ ├── mapping_data_location_function_param_internal.sol │ │ │ │ │ ├── mapping_data_location_function_param_public.sol │ │ │ │ │ ├── mapping_data_location_memory.sol │ │ │ │ │ ├── mapping_dynamic_key.sol │ │ │ │ │ ├── mapping_dynamic_key_public.sol │ │ │ │ │ ├── mapping_function_calldata.sol │ │ │ │ │ ├── mapping_return_external.sol │ │ │ │ │ ├── mapping_return_internal.sol │ │ │ │ │ ├── mapping_return_public.sol │ │ │ │ │ ├── mapping_return_public_memory.sol │ │ │ │ │ ├── mapping_struct_data_location_memory.sol │ │ │ │ │ ├── mapping_struct_recursive_data_location_memory.sol │ │ │ │ │ ├── memory_struct_recursive.sol │ │ │ │ │ ├── memory_structs_with_mappings.sol │ │ │ │ │ └── user_defined_types_mapping_memory.sol │ │ │ │ ├── no_singleton_tuple.sol │ │ │ │ ├── rational_negative_numerator_negative_exp.sol │ │ │ │ ├── rational_number_array_index_limit.sol │ │ │ │ ├── rational_number_bitshift_limit.sol │ │ │ │ ├── rational_number_div_limit.sol │ │ │ │ ├── rational_number_exp_limit_fail.sol │ │ │ │ ├── rational_number_exp_limit_fine.sol │ │ │ │ ├── rational_number_huge.sol │ │ │ │ ├── rational_number_huge_fail.sol │ │ │ │ ├── rational_number_literal_limit_1.sol │ │ │ │ ├── rational_number_literal_limit_2.sol │ │ │ │ ├── rational_number_literal_limit_3.sol │ │ │ │ ├── rational_number_literal_to_fixed_implicit.sol │ │ │ │ ├── rational_number_mul_limit.sol │ │ │ │ ├── rational_number_signed_to_unsigned.sol │ │ │ │ ├── rational_number_too_large.sol │ │ │ │ ├── strict_explicit.sol │ │ │ │ ├── strict_explicit_err.sol │ │ │ │ ├── struct_mapping_recursion.sol │ │ │ │ ├── too_small_negative_numbers.sol │ │ │ │ ├── uint256_to_bytes1.sol │ │ │ │ ├── uint32_to_bytes32.sol │ │ │ │ ├── unnamed_tuple_decl.sol │ │ │ │ ├── var_decl_val_mismatch.sol │ │ │ │ ├── var_empty_decl_1.sol │ │ │ │ ├── var_empty_decl_2.sol │ │ │ │ ├── var_empty_decl_3.sol │ │ │ │ ├── var_type_invalid_rational.sol │ │ │ │ ├── weird_sized_types.sol │ │ │ │ ├── zero_literal_to_bytesNN_explicit.sol │ │ │ │ └── zero_literal_to_bytesNN_implicit.sol │ │ │ ├── unchecked/ │ │ │ │ ├── unchecked_for_header.sol │ │ │ │ ├── unchecked_function_body.sol │ │ │ │ ├── unchecked_modifier.sol │ │ │ │ ├── unchecked_nested.sol │ │ │ │ ├── unchecked_post_for.sol │ │ │ │ ├── unchecked_vardecl.sol │ │ │ │ └── unchecked_while_body.sol │ │ │ ├── underscore/ │ │ │ │ ├── as_function.sol │ │ │ │ ├── in_function.sol │ │ │ │ └── in_modifier.sol │ │ │ ├── unterminatedBlocks/ │ │ │ │ ├── one_dot.sol │ │ │ │ ├── one_dot_x.sol │ │ │ │ ├── zero_dot.sol │ │ │ │ └── zero_dot_x.sol │ │ │ ├── unusedVariables/ │ │ │ │ └── try_catch.sol │ │ │ ├── userDefinedValueType/ │ │ │ │ ├── all_value_types.sol │ │ │ │ ├── constant.sol │ │ │ │ ├── conversion_err.sol │ │ │ │ ├── explicit_conversion_self.sol │ │ │ │ ├── explicit_conversions_err.sol │ │ │ │ ├── explicit_conversions_wrap.sol │ │ │ │ ├── explicit_literal_conversion_wrap.sol │ │ │ │ ├── forward_reference_array.sol │ │ │ │ ├── forward_reference_constant_variable_declaration.sol │ │ │ │ ├── forward_reference_err.sol │ │ │ │ ├── forward_reference_struct.sol │ │ │ │ ├── implicit_conversion.sol │ │ │ │ ├── implicit_conversion_err.sol │ │ │ │ ├── mapping_key.sol │ │ │ │ ├── multisource1.sol │ │ │ │ ├── multisource2.sol │ │ │ │ ├── multisource3.sol │ │ │ │ ├── multisource4.sol │ │ │ │ ├── name_conflict_contract_warning.sol │ │ │ │ ├── name_conflict_err.sol │ │ │ │ ├── non_value_type_bytes.sol │ │ │ │ ├── non_value_type_contract_err.sol │ │ │ │ ├── non_value_type_enum_err.sol │ │ │ │ ├── non_value_type_function_err.sol │ │ │ │ ├── non_value_type_mapping_err.sol │ │ │ │ ├── non_value_type_string_err.sol │ │ │ │ ├── non_value_type_struct_err.sol │ │ │ │ ├── overload_clash_err.sol │ │ │ │ ├── recursive_err.sol │ │ │ │ ├── recursive_function_parameter_err.sol │ │ │ │ ├── reference.sol │ │ │ │ ├── repetition_err.sol │ │ │ │ ├── self_reference_err.sol │ │ │ │ ├── wrap_unwrap_assign_err.sol │ │ │ │ ├── wrap_unwrap_calls_err.sol │ │ │ │ ├── wrap_unwrap_via_contract_name.sol │ │ │ │ └── wrap_unwrap_via_contract_name_different.sol │ │ │ ├── using/ │ │ │ │ ├── bound_calldata_parameter_accepting_calldata.sol │ │ │ │ ├── bound_calldata_parameter_not_accepting_memory.sol │ │ │ │ ├── double_asterisk.sol │ │ │ │ ├── erc7201_builtin_as_custom_operator.sol │ │ │ │ ├── erc7201_builtin_using_for.sol │ │ │ │ ├── external_function_qualified_with_this.sol │ │ │ │ ├── file_level_inactive_after_import.sol │ │ │ │ ├── free_functions_implicit_conversion.sol │ │ │ │ ├── free_functions_implicit_conversion_err.sol │ │ │ │ ├── free_functions_non_unique_err.sol │ │ │ │ ├── free_overloads.sol │ │ │ │ ├── free_overloads_array.sol │ │ │ │ ├── free_reference_type.sol │ │ │ │ ├── function_from_base_contract_qualified_with_super.sol │ │ │ │ ├── function_name_without_braces_at_file_level_err.sol │ │ │ │ ├── function_name_without_braces_inside_contract_err.sol │ │ │ │ ├── global_and_local.sol │ │ │ │ ├── global_for_asterisk.sol │ │ │ │ ├── global_for_non_user_defined.sol │ │ │ │ ├── global_for_type_defined_elsewhere.sol │ │ │ │ ├── global_for_type_from_other_file.sol │ │ │ │ ├── global_inside_contract.sol │ │ │ │ ├── global_library_for_builtin.sol │ │ │ │ ├── global_library_for_defined_elsewhere.sol │ │ │ │ ├── global_library_for_interface.sol │ │ │ │ ├── global_library_foreign.sol │ │ │ │ ├── global_library_with_asterisk.sol │ │ │ │ ├── global_local_clash.sol │ │ │ │ ├── global_multiple_global_keywords.sol │ │ │ │ ├── global_nonglobal.sol │ │ │ │ ├── global_with_asterisk.sol │ │ │ │ ├── global_working.sol │ │ │ │ ├── interface_function_at_file_level.sol │ │ │ │ ├── interface_function_inside_contract.sol │ │ │ │ ├── interface_using_for.sol │ │ │ │ ├── library_at_file_level.sol │ │ │ │ ├── library_function_attached_and_called.sol │ │ │ │ ├── library_function_attached_but_not_called.sol │ │ │ │ ├── library_function_attached_to_all_types.sol │ │ │ │ ├── library_functions_at_file_level.sol │ │ │ │ ├── library_functions_attached_at_file_level_used_inside_library.sol │ │ │ │ ├── library_functions_attached_in_single_directive_at_file_level.sol │ │ │ │ ├── library_functions_attached_in_single_directive_inside_contract.sol │ │ │ │ ├── library_functions_inside_contract.sol │ │ │ │ ├── library_import_as.sol │ │ │ │ ├── library_inside_contract.sol │ │ │ │ ├── library_non_free_external_function_err.sol │ │ │ │ ├── library_non_free_function.sol │ │ │ │ ├── module_1.sol │ │ │ │ ├── module_2.sol │ │ │ │ ├── module_3.sol │ │ │ │ ├── module_identifier_not_found.sol │ │ │ │ ├── private_library_function_inside_scope.sol │ │ │ │ ├── private_library_function_outside_scope.sol │ │ │ │ ├── public_state_variable_getter.sol │ │ │ │ ├── undeclared_library.sol │ │ │ │ ├── unqualified_library_functions_attached_in_single_directive_inside_library.sol │ │ │ │ ├── using_contract_err.sol │ │ │ │ ├── using_empty_list_err.sol │ │ │ │ ├── using_empty_list_file_level.sol │ │ │ │ ├── using_for_ast_file_level.sol │ │ │ │ ├── using_for_enum.sol │ │ │ │ ├── using_free_functions.sol │ │ │ │ ├── using_free_no_parameters_err.sol │ │ │ │ ├── using_free_no_parameters_struct_err.sol │ │ │ │ ├── using_functions_with_ast.sol │ │ │ │ ├── using_lhs_asterisk.sol │ │ │ │ ├── using_lhs_asterisk_contract.sol │ │ │ │ ├── using_library_ast_file_level.sol │ │ │ │ ├── using_library_file_level.sol │ │ │ │ ├── using_library_for_library.sol │ │ │ │ ├── using_non_free_function_err.sol │ │ │ │ ├── using_non_function.sol │ │ │ │ └── using_struct_for_struct.sol │ │ │ ├── variableDeclaration/ │ │ │ │ ├── do_while.sol │ │ │ │ ├── else.sol │ │ │ │ ├── for.sol │ │ │ │ ├── if.sol │ │ │ │ ├── illegal_names.sol │ │ │ │ ├── state_variables_both_transient_storage_identical_name.sol │ │ │ │ ├── transient_as_identifier.sol │ │ │ │ ├── transient_as_identifier_and_data_location.sol │ │ │ │ └── while.sol │ │ │ ├── viewPureChecker/ │ │ │ │ ├── access_to_base_member_constant.sol │ │ │ │ ├── access_to_base_member_function.sol │ │ │ │ ├── access_to_base_member_struct.sol │ │ │ │ ├── access_to_base_members.sol │ │ │ │ ├── address.sol │ │ │ │ ├── address_constantinople.sol │ │ │ │ ├── array/ │ │ │ │ │ ├── access_to_array_push.sol │ │ │ │ │ ├── access_to_array_push_view.sol │ │ │ │ │ └── access_to_base_member_array.sol │ │ │ │ ├── assembly.sol │ │ │ │ ├── assembly_chainid_not_pure.sol │ │ │ │ ├── assembly_constantinople.sol │ │ │ │ ├── assembly_istanbul.sol │ │ │ │ ├── basefee_not_pure.sol │ │ │ │ ├── blobbasefee_not_pure.sol │ │ │ │ ├── blobhash.sol │ │ │ │ ├── blobhash_not_pure.sol │ │ │ │ ├── builtin_blobhash_restrict_warning.sol │ │ │ │ ├── builtin_functions.sol │ │ │ │ ├── builtin_functions_restrict_warning.sol │ │ │ │ ├── builtin_functions_view_fail.sol │ │ │ │ ├── call_internal_functions_fail.sol │ │ │ │ ├── call_internal_functions_success.sol │ │ │ │ ├── call_options_without_call.sol │ │ │ │ ├── callvalue_nonpayable_assembly_fallback.sol │ │ │ │ ├── callvalue_nonpayable_assembly_function.sol │ │ │ │ ├── callvalue_nonpayable_assembly_function_internal.sol │ │ │ │ ├── callvalue_nonpayable_assembly_function_modifier.sol │ │ │ │ ├── callvalue_payable_assembly_fallback.sol │ │ │ │ ├── callvalue_payable_assembly_function.sol │ │ │ │ ├── callvalue_payable_assembly_function_modifier.sol │ │ │ │ ├── constant.sol │ │ │ │ ├── constant_restrict_warning.sol │ │ │ │ ├── creation_no_restrict_warning.sol │ │ │ │ ├── creation_view_fail.sol │ │ │ │ ├── eof/ │ │ │ │ │ ├── assembly.sol │ │ │ │ │ ├── builtin_functions.sol │ │ │ │ │ ├── inline_assembly_instructions_allowed.sol │ │ │ │ │ ├── inline_assembly_instructions_allowed_pure.sol │ │ │ │ │ ├── inline_assembly_instructions_allowed_view.sol │ │ │ │ │ ├── inline_assembly_instructions_disallowed.sol │ │ │ │ │ ├── inline_assembly_instructions_disallowed_pure.sol │ │ │ │ │ └── inline_assembly_instructions_disallowed_view.sol │ │ │ │ ├── function_types.sol │ │ │ │ ├── function_types_fail.sol │ │ │ │ ├── gas_value_without_call.sol │ │ │ │ ├── gas_with_call_nonpayable.sol │ │ │ │ ├── immutable.sol │ │ │ │ ├── inline_assembly_instructions_allowed.sol │ │ │ │ ├── inline_assembly_instructions_allowed_london.sol │ │ │ │ ├── inline_assembly_instructions_allowed_pure.sol │ │ │ │ ├── inline_assembly_instructions_allowed_pure_cancun.sol │ │ │ │ ├── inline_assembly_instructions_allowed_view.sol │ │ │ │ ├── inline_assembly_instructions_allowed_view_cancun.sol │ │ │ │ ├── inline_assembly_instructions_allowed_view_london.sol │ │ │ │ ├── inline_assembly_instructions_disallowed.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure_byzantium.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure_cancun.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure_constantinople.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure_istanbul.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure_london.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure_paris.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_pure_pre_paris.sol │ │ │ │ ├── inline_assembly_instructions_disallowed_view.sol │ │ │ │ ├── interface.sol │ │ │ │ ├── local_storage_variables.sol │ │ │ │ ├── local_storage_variables_fail.sol │ │ │ │ ├── mappings.sol │ │ │ │ ├── mcopy_pure.sol │ │ │ │ ├── modifiers.sol │ │ │ │ ├── modifiers_fail.sol │ │ │ │ ├── msg_value_modifier.sol │ │ │ │ ├── msg_value_modifier_view.sol │ │ │ │ ├── overriding_fail.sol │ │ │ │ ├── overriding_no_restrict_warning.sol │ │ │ │ ├── read_storage_pure_fail.sol │ │ │ │ ├── returning_structs_fail.sol │ │ │ │ ├── returning_structs_no_restrict_warning.sol │ │ │ │ ├── selector.sol │ │ │ │ ├── selector_complex.sol │ │ │ │ ├── selector_complex2.sol │ │ │ │ ├── smoke_test.sol │ │ │ │ ├── staticcall_gas_view.sol │ │ │ │ ├── suggest_pure.sol │ │ │ │ ├── suggest_view.sol │ │ │ │ ├── tload_not_pure.sol │ │ │ │ ├── tload_view.sol │ │ │ │ ├── transient_storage_value_type.sol │ │ │ │ ├── tstore_not_pure.sol │ │ │ │ ├── tstore_not_view.sol │ │ │ │ ├── user_operator_with_pure_modifier_can_be_restricted.sol │ │ │ │ ├── value_with_call_nonpayable.sol │ │ │ │ ├── view_pure_abi_encode.sol │ │ │ │ ├── view_pure_abi_encode_arguments.sol │ │ │ │ └── write_storage_fail.sol │ │ │ ├── virtualLookup/ │ │ │ │ └── modifiers_in_libraries.sol │ │ │ └── visibility/ │ │ │ ├── external_library_function.sol │ │ │ ├── file_level_variable_visibility.sol │ │ │ ├── function_no_visibility.sol │ │ │ ├── interface/ │ │ │ │ ├── function_default.sol │ │ │ │ ├── function_external.sol │ │ │ │ ├── function_internal.sol │ │ │ │ ├── function_private.sol │ │ │ │ ├── function_public.sol │ │ │ │ └── interface_contract_function_default.sol │ │ │ ├── invalid_function_parameter_and_return_var_visibility.sol │ │ │ ├── invalid_variable_visibility.sol │ │ │ ├── library_self_delegatecall.sol │ │ │ ├── multiple_visibility_specifiers.sol │ │ │ └── multiple_visibility_specifiers_external.sol │ │ └── util/ │ │ ├── BytesUtils.cpp │ │ ├── BytesUtils.h │ │ ├── BytesUtilsTests.cpp │ │ ├── Common.cpp │ │ ├── Common.h │ │ ├── ContractABIUtils.cpp │ │ ├── ContractABIUtils.h │ │ ├── SoltestErrors.h │ │ ├── SoltestTypes.h │ │ ├── TestFileParser.cpp │ │ ├── TestFileParser.h │ │ ├── TestFileParserTests.cpp │ │ ├── TestFunctionCall.cpp │ │ ├── TestFunctionCall.h │ │ └── TestFunctionCallTests.cpp │ ├── libsolutil/ │ │ ├── Checksum.cpp │ │ ├── CommonData.cpp │ │ ├── CommonIO.cpp │ │ ├── DisjointSet.cpp │ │ ├── DominatorFinderTest.cpp │ │ ├── FixedHash.cpp │ │ ├── FunctionSelector.cpp │ │ ├── IpfsHash.cpp │ │ ├── IterateReplacing.cpp │ │ ├── JSON.cpp │ │ ├── Keccak256.cpp │ │ ├── LEB128.cpp │ │ ├── LazyInit.cpp │ │ ├── StringUtils.cpp │ │ ├── SwarmHash.cpp │ │ ├── TemporaryDirectoryTest.cpp │ │ ├── UTF8.cpp │ │ └── Whiskers.cpp │ ├── libyul/ │ │ ├── Common.cpp │ │ ├── Common.h │ │ ├── CompilabilityChecker.cpp │ │ ├── ControlFlowGraphTest.cpp │ │ ├── ControlFlowGraphTest.h │ │ ├── ControlFlowSideEffectsTest.cpp │ │ ├── ControlFlowSideEffectsTest.h │ │ ├── EVMCodeTransformTest.cpp │ │ ├── EVMCodeTransformTest.h │ │ ├── EVMDialectCompatibility.cpp │ │ ├── FunctionSideEffects.cpp │ │ ├── FunctionSideEffects.h │ │ ├── Inliner.cpp │ │ ├── KnowledgeBaseTest.cpp │ │ ├── Metrics.cpp │ │ ├── ObjectCompilerTest.cpp │ │ ├── ObjectCompilerTest.h │ │ ├── ObjectParser.cpp │ │ ├── Parser.cpp │ │ ├── SSAControlFlowGraphTest.cpp │ │ ├── SSAControlFlowGraphTest.h │ │ ├── StackLayoutGeneratorTest.cpp │ │ ├── StackLayoutGeneratorTest.h │ │ ├── StackShufflingTest.cpp │ │ ├── StackShufflingTest.h │ │ ├── SyntaxTest.cpp │ │ ├── SyntaxTest.h │ │ ├── YulInterpreterTest.cpp │ │ ├── YulInterpreterTest.h │ │ ├── YulOptimizerTest.cpp │ │ ├── YulOptimizerTest.h │ │ ├── YulOptimizerTestCommon.cpp │ │ ├── YulOptimizerTestCommon.h │ │ ├── controlFlowSideEffects/ │ │ │ ├── eval_order.yul │ │ │ ├── for_loop.yul │ │ │ ├── leave.yul │ │ │ ├── nondisambiguated.yul │ │ │ ├── recursion.yul │ │ │ ├── simple_conditionals.yul │ │ │ ├── simple_functions.yul │ │ │ └── switch.yul │ │ ├── evmCodeTransform/ │ │ │ ├── after_terminating_function.yul │ │ │ ├── early_push_on_deep_swap.yul │ │ │ ├── eof_dup256.yul │ │ │ ├── eof_swap17.yul │ │ │ ├── eof_swap256.yul │ │ │ ├── literal_loop.yul │ │ │ ├── nonempty_initial_layout.yul │ │ │ ├── pops_in_reverting_branch.yul │ │ │ ├── stackReuse/ │ │ │ │ ├── eof/ │ │ │ │ │ └── function_argument_reuse_without_retparams.yul │ │ │ │ ├── for_1.yul │ │ │ │ ├── for_2.yul │ │ │ │ ├── function_argument_reuse.yul │ │ │ │ ├── function_argument_reuse_without_retparams.yul │ │ │ │ ├── function_call.yul │ │ │ │ ├── function_many_arguments.yul │ │ │ │ ├── function_params.yul │ │ │ │ ├── function_params_and_retparams.yul │ │ │ │ ├── function_params_and_retparams_partly_used.yul │ │ │ │ ├── function_retparam.yul │ │ │ │ ├── function_retparam_block.yul │ │ │ │ ├── function_retparam_declaration.yul │ │ │ │ ├── function_retparam_for.yul │ │ │ │ ├── function_retparam_if.yul │ │ │ │ ├── function_retparam_leave.yul │ │ │ │ ├── function_retparam_read.yul │ │ │ │ ├── function_retparam_unassigned.yul │ │ │ │ ├── function_retparam_unassigned_multiple.yul │ │ │ │ ├── function_trivial.yul │ │ │ │ ├── function_with_body_embedded.yul │ │ │ │ ├── functions_multi_return.yul │ │ │ │ ├── if.yul │ │ │ │ ├── last_use_in_nested_block.yul │ │ │ │ ├── multi_reuse_same_variable_name.yul │ │ │ │ ├── multi_reuse_single_slot.yul │ │ │ │ ├── multi_reuse_single_slot_nested.yul │ │ │ │ ├── reuse_on_decl_assign_not_same_scope.yul │ │ │ │ ├── reuse_on_decl_assign_to_last_used.yul │ │ │ │ ├── reuse_on_decl_assign_to_last_used_expr.yul │ │ │ │ ├── reuse_on_decl_assign_to_not_last_used.yul │ │ │ │ ├── reuse_slots.yul │ │ │ │ ├── reuse_slots_function.yul │ │ │ │ ├── reuse_slots_function_with_gaps.yul │ │ │ │ ├── reuse_too_deep_slot.yul │ │ │ │ ├── single_var.yul │ │ │ │ ├── single_var_assigned.yul │ │ │ │ ├── single_var_assigned_plus_code.yul │ │ │ │ ├── single_var_assigned_plus_code_and_reused.yul │ │ │ │ ├── smoke.yul │ │ │ │ └── switch.yul │ │ │ ├── stub.yul │ │ │ └── unassigned_return_variable.yul │ │ ├── functionSideEffects/ │ │ │ ├── cyclic_graph.yul │ │ │ ├── doubly_recursive_function.yul │ │ │ ├── empty.yul │ │ │ ├── empty_with_sstore.yul │ │ │ ├── memory.yul │ │ │ ├── mload_in_function.yul │ │ │ ├── multi_calls.yul │ │ │ ├── otherImmovables.yul │ │ │ ├── recursive_function.yul │ │ │ ├── simple_functions.yul │ │ │ ├── state.yul │ │ │ ├── storage.yul │ │ │ ├── structures.yul │ │ │ ├── verbatim.yul │ │ │ └── with_loop.yul │ │ ├── objectCompiler/ │ │ │ ├── data.yul │ │ │ ├── datacopy.yul │ │ │ ├── dataoffset_code.yul │ │ │ ├── dataoffset_data.yul │ │ │ ├── dataoffset_self.yul │ │ │ ├── datasize_code.yul │ │ │ ├── datasize_data.yul │ │ │ ├── datasize_self.yul │ │ │ ├── eof/ │ │ │ │ ├── 256_subcontainers.yul │ │ │ │ ├── creation_with_immutables.yul │ │ │ │ ├── dataloadn.yul │ │ │ │ ├── extcall.yul │ │ │ │ ├── functions.yul │ │ │ │ ├── leading_and_trailing_dots.yul │ │ │ │ ├── long_object_name.yul │ │ │ │ ├── prune_unreachable_function_non_returning.yul │ │ │ │ ├── prune_unreachable_function_recursion.yul │ │ │ │ ├── prune_unreferenced_container.yul │ │ │ │ ├── prune_unreferenced_function.yul │ │ │ │ ├── rjumps.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── subObject.yul │ │ │ │ ├── subSubObject.yul │ │ │ │ └── verbatim_bug.yul │ │ │ ├── function_series.yul │ │ │ ├── identical_subobjects_creation_deployed.yul │ │ │ ├── identical_subobjects_full_debug_info.yul │ │ │ ├── identical_subobjects_no_debug_info.yul │ │ │ ├── identical_subobjects_partial_debug_info.yul │ │ │ ├── identical_subobjects_partial_debug_info_no_use_src.yul │ │ │ ├── identical_subobjects_with_subject_references.yul │ │ │ ├── immutable_long_name_does_not_end_up_in_bytecode.yul │ │ │ ├── jump_tags.yul │ │ │ ├── leading_and_trailing_dots.yul │ │ │ ├── linkersymbol.yul │ │ │ ├── long_object_name.yul │ │ │ ├── manySubObjects.yul │ │ │ ├── metadata.yul │ │ │ ├── namedObject.yul │ │ │ ├── namedObjectCode.yul │ │ │ ├── nested_optimizer.yul │ │ │ ├── prune_unreachable_function_non_returning.yul │ │ │ ├── prune_unreachable_function_recursion.yul │ │ │ ├── prune_unreferenced_function.yul │ │ │ ├── simple.yul │ │ │ ├── simple_optimizer.yul │ │ │ ├── smoke.yul │ │ │ ├── sourceLocations.yul │ │ │ ├── subObject.yul │ │ │ ├── subObjectAccess.yul │ │ │ ├── subSubObject.yul │ │ │ └── verbatim_bug.yul │ │ ├── ssa/ │ │ │ ├── StackLayoutGeneratorTest.cpp │ │ │ ├── StackLayoutGeneratorTest.h │ │ │ ├── StackShufflerTest.cpp │ │ │ ├── StackShufflerTest.h │ │ │ ├── stackLayoutGenerator/ │ │ │ │ ├── can_continue.yul │ │ │ │ ├── dead_code.yul │ │ │ │ ├── function.yul │ │ │ │ ├── multi_return.yul │ │ │ │ ├── nested_for.yul │ │ │ │ ├── recursion.yul │ │ │ │ ├── simple_for.yul │ │ │ │ ├── simple_if.yul │ │ │ │ └── switch.yul │ │ │ └── stackShuffler/ │ │ │ ├── deep_argument_dup_order.stack │ │ │ ├── deep_argument_shrink.stack │ │ │ ├── dup_up_args.stack │ │ │ ├── empty.stack │ │ │ ├── grow.stack │ │ │ ├── introduce_junk.stack │ │ │ ├── reduce_size.stack │ │ │ ├── satisfy_tail_requirements.stack │ │ │ ├── shrink_and_grow_a_lot.stack │ │ │ ├── superfluous_top_slots.stack │ │ │ └── swap_junk_over_pop.stack │ │ ├── yulControlFlowGraph/ │ │ │ ├── ambiguous_names.yul │ │ │ ├── break.yul │ │ │ ├── complex.yul │ │ │ ├── eof/ │ │ │ │ └── function.yul │ │ │ ├── for.yul │ │ │ ├── function.yul │ │ │ ├── if.yul │ │ │ ├── leave.yul │ │ │ ├── nested_loop_complex.yul │ │ │ ├── stub.yul │ │ │ ├── switch.yul │ │ │ ├── variables.yul │ │ │ └── verbatim.yul │ │ ├── yulInterpreterTests/ │ │ │ ├── access_large_memory_offsets.yul │ │ │ ├── ambiguous_vars.yul │ │ │ ├── and_create.yul │ │ │ ├── and_create2.yul │ │ │ ├── blobbasefee.yul │ │ │ ├── blobhash.yul │ │ │ ├── bounded_recursion.yul │ │ │ ├── clz.yul │ │ │ ├── create2.yul │ │ │ ├── datacopy.yul │ │ │ ├── dataoffset.yul │ │ │ ├── datasize.yul │ │ │ ├── difficulty.yul │ │ │ ├── exp.yul │ │ │ ├── expr_nesting_depth_exceeded.yul │ │ │ ├── expr_nesting_depth_not_exceeded.yul │ │ │ ├── external_call_to_self.yul │ │ │ ├── external_call_unexecuted.yul │ │ │ ├── external_callcode_unexecuted.yul │ │ │ ├── external_delegatecall_unexecuted.yul │ │ │ ├── external_staticcall_unexecuted.yul │ │ │ ├── function_calls.yul │ │ │ ├── function_scopes.yul │ │ │ ├── hex_literals.yul │ │ │ ├── infinite_recursion.yul │ │ │ ├── infinite_recursion_tracelimit.yul │ │ │ ├── isoltestTesting/ │ │ │ │ ├── linkersymbol.yul │ │ │ │ ├── loadimmutable.yul │ │ │ │ └── setimmutable_stub.yul │ │ │ ├── leave.yul │ │ │ ├── leave_for_init.yul │ │ │ ├── long_object_name.yul │ │ │ ├── loop.yul │ │ │ ├── mcopy.yul │ │ │ ├── mcopy_memory_access_out_of_range.yul │ │ │ ├── mcopy_memory_expansion_on_read.yul │ │ │ ├── mcopy_memory_expansion_on_write.yul │ │ │ ├── mcopy_memory_expansion_zero_size.yul │ │ │ ├── mcopy_overlap.yul │ │ │ ├── pop_byte_shr_call.yul │ │ │ ├── pop_byte_shr_func.yul │ │ │ ├── prevrandao.yul │ │ │ ├── recursion.yul │ │ │ ├── recursive_function_for_loop.yul │ │ │ ├── self_balance.yul │ │ │ ├── shadowed_symbol.yul │ │ │ ├── side_effect_free.yul │ │ │ ├── simple_mstore.yul │ │ │ ├── smoke.yul │ │ │ ├── switch_statement.yul │ │ │ ├── transient_storage.yul │ │ │ ├── zero_length_reads.yul │ │ │ ├── zero_length_reads_and_revert.yul │ │ │ └── zero_range.yul │ │ ├── yulOptimizerTests/ │ │ │ ├── blockFlattener/ │ │ │ │ ├── basic.yul │ │ │ │ ├── for_stmt.yul │ │ │ │ ├── if_stmt.yul │ │ │ │ ├── many_nested_blocks.yul │ │ │ │ └── switch_stmt.yul │ │ │ ├── circularReferencesPruner/ │ │ │ │ ├── called_from_non_function.yul │ │ │ │ ├── nested_different_names.yul │ │ │ │ ├── nested_same_name.yul │ │ │ │ └── trivial.yul │ │ │ ├── commonSubexpressionEliminator/ │ │ │ │ ├── branches_for.yul │ │ │ │ ├── branches_if.yul │ │ │ │ ├── case2.yul │ │ │ │ ├── clear_not_needed.yul │ │ │ │ ├── function_scopes.yul │ │ │ │ ├── long_literals_as_builtin_args.yul │ │ │ │ ├── loop.yul │ │ │ │ ├── movable_functions.yul │ │ │ │ ├── non_movable_instr.yul │ │ │ │ ├── non_movable_instr2.yul │ │ │ │ ├── object_access.yul │ │ │ │ ├── replace_return_nonzero.yul │ │ │ │ ├── scopes.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── trivial.yul │ │ │ │ ├── unassigned_return.yul │ │ │ │ ├── unassigned_variables.yul │ │ │ │ └── variable_for_variable.yul │ │ │ ├── conditionalSimplifier/ │ │ │ │ ├── clear_after_if_break.yul │ │ │ │ ├── clear_after_if_continue.yul │ │ │ │ ├── clear_before_for_condition.yul │ │ │ │ ├── clear_before_for_post.yul │ │ │ │ ├── no_opt_if_break_is_not_last.yul │ │ │ │ ├── no_opt_inside_if.yul │ │ │ │ ├── opt_after_terminating_if.yul │ │ │ │ ├── opt_switch.yul │ │ │ │ ├── side_effects_of_functions.yul │ │ │ │ └── smoke.yul │ │ │ ├── conditionalUnsimplifier/ │ │ │ │ ├── clear_after_if_break.yul │ │ │ │ ├── clear_after_if_continue.yul │ │ │ │ ├── clear_before_for_condition.yul │ │ │ │ ├── clear_before_for_post.yul │ │ │ │ ├── no_opt_if_break_is_not_last.yul │ │ │ │ ├── no_opt_inside_if.yul │ │ │ │ ├── opt_after_terminating_if.yul │ │ │ │ ├── opt_switch.yul │ │ │ │ ├── side_effects_of_functions.yul │ │ │ │ └── smoke.yul │ │ │ ├── constantOptimiser/ │ │ │ │ ├── difficult.yul │ │ │ │ ├── gaps.yul │ │ │ │ └── smallNumbers.yul │ │ │ ├── controlFlowSimplifier/ │ │ │ │ ├── empty_if_movable_condition.yul │ │ │ │ ├── empty_if_non_movable_condition.yul │ │ │ │ ├── remove_leave.yul │ │ │ │ ├── switch_only_default.yul │ │ │ │ ├── switch_remove_empty_all.yul │ │ │ │ ├── switch_remove_empty_case.yul │ │ │ │ ├── switch_remove_empty_cases.yul │ │ │ │ ├── switch_remove_empty_default_case.yul │ │ │ │ ├── switch_to_if.yul │ │ │ │ ├── terminating_for.yul │ │ │ │ ├── terminating_for_nested.yul │ │ │ │ ├── terminating_for_nested_reversed.yul │ │ │ │ ├── terminating_for_revert.yul │ │ │ │ ├── terminating_for_revert_plus_break.yul │ │ │ │ └── terminating_for_with_continue.yul │ │ │ ├── deadCodeEliminator/ │ │ │ │ ├── conditional_break.yul │ │ │ │ ├── dead_code_user_functions.yul │ │ │ │ ├── early_break.yul │ │ │ │ ├── early_continue.yul │ │ │ │ ├── early_leave.yul │ │ │ │ ├── early_revert.yul │ │ │ │ ├── early_stop.yul │ │ │ │ ├── for_loop_init_decl.yul │ │ │ │ ├── function_after_revert.yul │ │ │ │ ├── nested_revert.yul │ │ │ │ ├── no_removal.yul │ │ │ │ ├── normal_break.yul │ │ │ │ ├── normal_continue.yul │ │ │ │ └── normal_stop.yul │ │ │ ├── disambiguator/ │ │ │ │ ├── for_statement.yul │ │ │ │ ├── function_call.yul │ │ │ │ ├── if_statement.yul │ │ │ │ ├── long_names.yul │ │ │ │ ├── similar_literals.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── string_as_hex_and_hex_as_string.yul │ │ │ │ ├── switch_statement.yul │ │ │ │ ├── variables.yul │ │ │ │ ├── variables_clash.yul │ │ │ │ └── variables_inside_functions.yul │ │ │ ├── equalStoreEliminator/ │ │ │ │ ├── branching.yul │ │ │ │ ├── forloop.yul │ │ │ │ ├── functionbody.yul │ │ │ │ ├── indirect_inferrence.yul │ │ │ │ ├── mcopy.yul │ │ │ │ ├── mcopy_mstore.yul │ │ │ │ ├── mcopy_mstore_overlap.yul │ │ │ │ ├── mcopy_same_area.yul │ │ │ │ ├── mcopy_same_area_mcopy.yul │ │ │ │ ├── mcopy_same_read_area_mcopy.yul │ │ │ │ ├── mcopy_same_read_area_mstore.yul │ │ │ │ ├── mcopy_same_read_area_mstore8_mstore8.yul │ │ │ │ ├── mcopy_same_read_area_mstore_mstore.yul │ │ │ │ ├── mcopy_same_read_area_mstore_mstore_overlap.yul │ │ │ │ ├── mcopy_same_write_area_mcopy.yul │ │ │ │ ├── mstore8_mstore8.yul │ │ │ │ ├── mstore_mcopy.yul │ │ │ │ ├── mstore_mstore.yul │ │ │ │ ├── mstore_with_keccak.yul │ │ │ │ ├── transient_storage.yul │ │ │ │ ├── value_change.yul │ │ │ │ └── verbatim.yul │ │ │ ├── equivalentFunctionCombiner/ │ │ │ │ ├── constant_representation.yul │ │ │ │ ├── constant_representation_datasize.yul │ │ │ │ ├── multiple_complex.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── simple_different_vars.yul │ │ │ │ └── switch_case_order.yul │ │ │ ├── expressionInliner/ │ │ │ │ ├── argument_duplication_heuristic.yul │ │ │ │ ├── complex_with_evm.yul │ │ │ │ ├── double_calls.yul │ │ │ │ ├── double_recursive_calls.yul │ │ │ │ ├── no_inline_mload.yul │ │ │ │ ├── no_move_with_sideeffects.yul │ │ │ │ ├── simple.yul │ │ │ │ └── with_args.yul │ │ │ ├── expressionJoiner/ │ │ │ │ ├── if_condition.yul │ │ │ │ ├── muli_wrong_order3.yul │ │ │ │ ├── multi.yul │ │ │ │ ├── multi_reference.yul │ │ │ │ ├── multi_wrong_order.yul │ │ │ │ ├── multi_wrong_order2.yul │ │ │ │ ├── no_replacement_across_blocks.yul │ │ │ │ ├── no_replacement_in_loop_condition1.yul │ │ │ │ ├── no_replacement_in_loop_condition2.yul │ │ │ │ ├── only_assignment.yul │ │ │ │ ├── reassignment.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── single_wrong_order.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── switch_expression.yul │ │ │ │ └── triple.yul │ │ │ ├── expressionSimplifier/ │ │ │ │ ├── assigned_vars_multi.yul │ │ │ │ ├── byte_after_shr_non_mul_of_8.yul │ │ │ │ ├── combine_add_and_mod_constant.yul │ │ │ │ ├── combine_mul_and_mod_constant.yul │ │ │ │ ├── combine_shift_and_and.yul │ │ │ │ ├── combine_shift_and_and_2.yul │ │ │ │ ├── combine_shift_and_and_3.yul │ │ │ │ ├── constant_propagation.yul │ │ │ │ ├── constants.yul │ │ │ │ ├── create2_and_mask.yul │ │ │ │ ├── create_and_mask.yul │ │ │ │ ├── exp_simplifications.yul │ │ │ │ ├── idempotency.yul │ │ │ │ ├── identity_rules_complex.yul │ │ │ │ ├── identity_rules_negative.yul │ │ │ │ ├── identity_rules_simple.yul │ │ │ │ ├── including_function_calls.yul │ │ │ │ ├── inside_for.yul │ │ │ │ ├── invalid_match.yul │ │ │ │ ├── invariant.yul │ │ │ │ ├── iszero_sub_to_eq.yul │ │ │ │ ├── large_byte_access.yul │ │ │ │ ├── mcopy_non_zero_size.yul │ │ │ │ ├── mcopy_zero_size.yul │ │ │ │ ├── mod_and_1.yul │ │ │ │ ├── mod_and_2.yul │ │ │ │ ├── not_applied_function_call_different_arguments.yul │ │ │ │ ├── not_applied_function_call_different_names.yul │ │ │ │ ├── not_applied_function_call_equality_not_movable.yul │ │ │ │ ├── not_applied_removes_non_constant_and_not_movable.yul │ │ │ │ ├── optimize_shl_over_and.yul │ │ │ │ ├── pop_byte_shr_call.yul │ │ │ │ ├── pop_byte_shr_func.yul │ │ │ │ ├── pop_byte_shr_func_trivial.yul │ │ │ │ ├── reassign.yul │ │ │ │ ├── remove_redundant_shift_masking.yul │ │ │ │ ├── replace_too_large_shift.yul │ │ │ │ ├── return_vars_zero.yul │ │ │ │ ├── reversed.yul │ │ │ │ ├── selfbalance_not_supported.yul │ │ │ │ ├── selfbalance_split.yul │ │ │ │ ├── selfbalance_supported.yul │ │ │ │ ├── side_effects_in_for_condition.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── unassigend_vars_multi.yul │ │ │ │ ├── unassigned_vars.yul │ │ │ │ ├── zero_length_read.yul │ │ │ │ ├── zero_length_read_call.yul │ │ │ │ └── zero_length_read_codecopy.yul │ │ │ ├── expressionSplitter/ │ │ │ │ ├── control_flow.yul │ │ │ │ ├── inside_function.yul │ │ │ │ ├── object_access.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── switch.yul │ │ │ │ └── trivial.yul │ │ │ ├── fakeStackLimitEvader/ │ │ │ │ ├── connected.yul │ │ │ │ ├── function_arg.yul │ │ │ │ ├── multi_variable_declaration_without_value.yul │ │ │ │ ├── outer_block.yul │ │ │ │ ├── return_leave.yul │ │ │ │ ├── return_one.yul │ │ │ │ ├── return_one_with_args.yul │ │ │ │ ├── same_variable_in_lhs_and_rhs.yul │ │ │ │ └── stub.yul │ │ │ ├── forLoopConditionIntoBody/ │ │ │ │ ├── cond_types.yul │ │ │ │ ├── empty_body.yul │ │ │ │ ├── nested.yul │ │ │ │ └── simple.yul │ │ │ ├── forLoopInitRewriter/ │ │ │ │ ├── complex_pre.yul │ │ │ │ ├── empty_pre.yul │ │ │ │ ├── nested.yul │ │ │ │ └── simple.yul │ │ │ ├── fullInliner/ │ │ │ │ ├── call_arguments_with_side_effects.yul │ │ │ │ ├── call_arguments_without_side_effects.yul │ │ │ │ ├── double_inline.yul │ │ │ │ ├── inside_condition.yul │ │ │ │ ├── large_function_multi_use.yul │ │ │ │ ├── large_function_single_use.yul │ │ │ │ ├── long_names.yul │ │ │ │ ├── move_up_rightwards_argument.yul │ │ │ │ ├── multi_fun.yul │ │ │ │ ├── multi_fun_callback.yul │ │ │ │ ├── multi_return.yul │ │ │ │ ├── no_inline_into_big_function.yul │ │ │ │ ├── no_inline_into_big_function_homestead.yul │ │ │ │ ├── no_inline_into_big_global_context.yul │ │ │ │ ├── no_inline_into_big_global_context_homestead.yul │ │ │ │ ├── no_inline_leave.yul │ │ │ │ ├── no_return.yul │ │ │ │ ├── not_inside_for.yul │ │ │ │ ├── pop_result.yul │ │ │ │ ├── recursion.yul │ │ │ │ └── simple.yul │ │ │ ├── fullInlinerWithoutSplitter/ │ │ │ │ ├── call_arguments_with_side_effects.yul │ │ │ │ ├── call_arguments_without_side_effects.yul │ │ │ │ └── simple.yul │ │ │ ├── fullSimplify/ │ │ │ │ ├── constant_propagation.yul │ │ │ │ ├── constants.yul │ │ │ │ ├── identity_rules_complex.yul │ │ │ │ ├── identity_rules_negative.yul │ │ │ │ ├── identity_rules_simple.yul │ │ │ │ ├── including_function_calls.yul │ │ │ │ ├── inside_for.yul │ │ │ │ ├── invariant.yul │ │ │ │ ├── mod_and_1.yul │ │ │ │ ├── mod_and_2.yul │ │ │ │ ├── not_applied_function_call_different_arguments.yul │ │ │ │ ├── not_applied_function_call_different_names.yul │ │ │ │ ├── not_applied_function_call_equality_not_movable.yul │ │ │ │ ├── not_applied_removes_non_constant_and_not_movable.yul │ │ │ │ ├── operations.yul │ │ │ │ ├── reversed.yul │ │ │ │ ├── scoped_var_ref_in_function_call.yul │ │ │ │ ├── signextend.yul │ │ │ │ └── smoke.yul │ │ │ ├── fullSuite/ │ │ │ │ ├── abi2.yul │ │ │ │ ├── abi_example1.yul │ │ │ │ ├── ackermann_function.yul │ │ │ │ ├── ackermann_function_if.yul │ │ │ │ ├── and_or_combination.yul │ │ │ │ ├── aztec.yul │ │ │ │ ├── call_arguments_with_side_effects.yul │ │ │ │ ├── call_arguments_without_side_effects.yul │ │ │ │ ├── clear_after_if_continue.yul │ │ │ │ ├── combine_shift_and_and.yul │ │ │ │ ├── combine_shift_and_and_2.yul │ │ │ │ ├── combine_shift_and_and_3.yul │ │ │ │ ├── combine_shift_and_and_unsplit.yul │ │ │ │ ├── create2_and_mask.yul │ │ │ │ ├── create_and_mask.yul │ │ │ │ ├── devcon_example.yul │ │ │ │ ├── extcodelength.yul │ │ │ │ ├── fibonacci.yul │ │ │ │ ├── loopInvariantCodeMotion.yul │ │ │ │ ├── mcopy.yul │ │ │ │ ├── mcopy_redundant_overwritten.yul │ │ │ │ ├── mcopy_redundant_same_area.yul │ │ │ │ ├── mcopy_redundant_zero_size.yul │ │ │ │ ├── medium.yul │ │ │ │ ├── name_cleaner_reserved.yul │ │ │ │ ├── name_dependent_cse_bug_part_1.yul │ │ │ │ ├── name_dependent_cse_bug_part_1_pre_shanghai.yul │ │ │ │ ├── name_dependent_cse_bug_part_2.yul │ │ │ │ ├── name_dependent_cse_bug_part_2_pre_shanghai.yul │ │ │ │ ├── no_move_loop_orig.yul │ │ │ │ ├── remove_redundant_assignments_in_switch.yul │ │ │ │ ├── reserved_identifiers.yul │ │ │ │ ├── reuse_vars_bug_in_simplifier.yul │ │ │ │ ├── shift_signextend.yul │ │ │ │ ├── ssaReverse.yul │ │ │ │ ├── ssaReverseComplex.yul │ │ │ │ ├── stack_compressor_msize.yul │ │ │ │ ├── stack_shuffler_bring_up_target_slot_bfs_dedup.yul │ │ │ │ ├── static_array_slot_computation.yul │ │ │ │ ├── storage.yul │ │ │ │ ├── structural_simplification.yul │ │ │ │ ├── sub_objects.yul │ │ │ │ ├── switch_inline.yul │ │ │ │ ├── switch_inline_match_default.yul │ │ │ │ ├── transient_storage.yul │ │ │ │ ├── unusedFunctionParameterPruner.yul │ │ │ │ ├── unusedFunctionParameterPruner_loop.yul │ │ │ │ ├── unusedFunctionParameterPruner_recursion.yul │ │ │ │ ├── unusedFunctionParameterPruner_return.yul │ │ │ │ └── unusedFunctionParameterPruner_simple.yul │ │ │ ├── functionGrouper/ │ │ │ │ ├── already_grouped.yul │ │ │ │ ├── empty_block.yul │ │ │ │ ├── grouped_but_not_ordered.yul │ │ │ │ ├── multi_fun_mixed.yul │ │ │ │ ├── nested_fun.yul │ │ │ │ ├── single_fun.yul │ │ │ │ └── smoke.yul │ │ │ ├── functionHoister/ │ │ │ │ ├── empty_block.yul │ │ │ │ ├── multi_mixed.yul │ │ │ │ ├── nested.yul │ │ │ │ ├── single.yul │ │ │ │ └── smoke.yul │ │ │ ├── functionSpecializer/ │ │ │ │ ├── multiple.yul │ │ │ │ ├── partial.yul │ │ │ │ ├── recursion.yul │ │ │ │ ├── simple.yul │ │ │ │ └── smoke.yul │ │ │ ├── loadResolver/ │ │ │ │ ├── double_mload.yul │ │ │ │ ├── double_mload_with_other_reassignment.yul │ │ │ │ ├── double_mload_with_reassignment.yul │ │ │ │ ├── extstaticcall.yul │ │ │ │ ├── keccak.yul │ │ │ │ ├── keccak_crash.yul │ │ │ │ ├── keccak_fail1.yul │ │ │ │ ├── keccak_fail2.yul │ │ │ │ ├── keccak_reuse_basic.yul │ │ │ │ ├── keccak_reuse_expr_mstore.yul │ │ │ │ ├── keccak_reuse_in_expression.yul │ │ │ │ ├── keccak_reuse_msize.yul │ │ │ │ ├── keccak_reuse_mstore.yul │ │ │ │ ├── keccak_reuse_reassigned_branch.yul │ │ │ │ ├── keccak_reuse_reassigned_value.yul │ │ │ │ ├── keccak_short.yul │ │ │ │ ├── keccak_string_literal.yul │ │ │ │ ├── keccak_symbolic_memory.yul │ │ │ │ ├── keccak_with_msize.yul │ │ │ │ ├── loop.yul │ │ │ │ ├── memory_with_call_invalidation.yul │ │ │ │ ├── memory_with_extcall_invalidation.yul │ │ │ │ ├── memory_with_function_call_invalidation.yul │ │ │ │ ├── memory_with_msize.yul │ │ │ │ ├── memory_with_mstore_invalidation.yul │ │ │ │ ├── merge_known_write.yul │ │ │ │ ├── merge_known_write_with_distance.yul │ │ │ │ ├── merge_mload_with_known_distance.yul │ │ │ │ ├── merge_mload_with_rewrite.yul │ │ │ │ ├── merge_mload_without_rewrite.yul │ │ │ │ ├── merge_unknown_write.yul │ │ │ │ ├── merge_with_rewrite.yul │ │ │ │ ├── mload_in_function.yul │ │ │ │ ├── mload_self.yul │ │ │ │ ├── mstore_in_function_loop_body.yul │ │ │ │ ├── mstore_in_function_loop_init.yul │ │ │ │ ├── multi_sload_loop.yul │ │ │ │ ├── re_store_memory.yul │ │ │ │ ├── re_store_storage.yul │ │ │ │ ├── reassign.yul │ │ │ │ ├── reassign_value_expression.yul │ │ │ │ ├── scoped_var_ref_in_keccak.yul │ │ │ │ ├── second_mstore_with_delta.yul │ │ │ │ ├── second_store.yul │ │ │ │ ├── second_store_same_value.yul │ │ │ │ ├── second_store_with_delta.yul │ │ │ │ ├── side_effects_of_user_functions.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── simple_memory.yul │ │ │ │ ├── staticcall.yul │ │ │ │ ├── verbatim_mload.yul │ │ │ │ ├── verbatim_sload.yul │ │ │ │ ├── zero_length_reads.yul │ │ │ │ └── zero_length_reads_eof.yul │ │ │ ├── loopInvariantCodeMotion/ │ │ │ │ ├── complex_move.yul │ │ │ │ ├── create_sload.yul │ │ │ │ ├── dependOnVarInLoop.yul │ │ │ │ ├── move_memory_function.yul │ │ │ │ ├── move_state_function.yul │ │ │ │ ├── move_storage_function.yul │ │ │ │ ├── multi.yul │ │ │ │ ├── no_move_gas.yul │ │ │ │ ├── no_move_immovables.yul │ │ │ │ ├── no_move_loop.yul │ │ │ │ ├── no_move_memory.yul │ │ │ │ ├── no_move_memory_loop.yul │ │ │ │ ├── no_move_memory_msize.yul │ │ │ │ ├── no_move_recursive_function.yul │ │ │ │ ├── no_move_state.yul │ │ │ │ ├── no_move_state_function.yul │ │ │ │ ├── no_move_state_loop.yul │ │ │ │ ├── no_move_state_recursive_function.yul │ │ │ │ ├── no_move_staticall_returndatasize.yul │ │ │ │ ├── no_move_storage.yul │ │ │ │ ├── no_move_storage_function.yul │ │ │ │ ├── no_move_storage_in_body.yul │ │ │ │ ├── no_move_storage_in_post.yul │ │ │ │ ├── no_move_storage_loop.yul │ │ │ │ ├── no_move_transient_storage.yul │ │ │ │ ├── non-ssavar.yul │ │ │ │ ├── nonMovable.yul │ │ │ │ ├── not_first.yul │ │ │ │ ├── recursive.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── simple_memory.yul │ │ │ │ ├── simple_state.yul │ │ │ │ └── simple_storage.yul │ │ │ ├── nameDisplacer/ │ │ │ │ ├── funtion_call.yul │ │ │ │ ├── variables.yul │ │ │ │ └── variables_inside_functions.yul │ │ │ ├── rematerialiser/ │ │ │ │ ├── branches_for1.yul │ │ │ │ ├── branches_for2.yul │ │ │ │ ├── branches_if.yul │ │ │ │ ├── branches_switch.yul │ │ │ │ ├── cheap_caller.yul │ │ │ │ ├── do_not_move_out_of_scope.yul │ │ │ │ ├── do_remat_large_amounts_of_code_if_used_once.yul │ │ │ │ ├── for_break.yul │ │ │ │ ├── for_continue.yul │ │ │ │ ├── for_continue_2.yul │ │ │ │ ├── for_continue_with_assignment_in_post.yul │ │ │ │ ├── large_constant.yul │ │ │ │ ├── large_constant_used_once.yul │ │ │ │ ├── many_refs_small_cost_loop.yul │ │ │ │ ├── medium_sized_constant.yul │ │ │ │ ├── no_remat_in_loop.yul │ │ │ │ ├── non_movable_function.yul │ │ │ │ ├── non_movable_instruction.yul │ │ │ │ ├── reassign.yul │ │ │ │ ├── reassignment.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── some_refs_small_cost_loop.yul │ │ │ │ ├── some_refs_small_cost_nested_loop.yul │ │ │ │ ├── trivial.yul │ │ │ │ └── update_asignment_remat.yul │ │ │ ├── splitJoin/ │ │ │ │ ├── control_flow.yul │ │ │ │ ├── functions.yul │ │ │ │ └── smoke.yul │ │ │ ├── ssaAndBack/ │ │ │ │ ├── for_loop.yul │ │ │ │ ├── multi_assign.yul │ │ │ │ ├── multi_assign_if.yul │ │ │ │ ├── multi_assign_multi_var_if.yul │ │ │ │ ├── multi_assign_multi_var_switch.yul │ │ │ │ ├── multi_assign_switch.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── single_assign_if.yul │ │ │ │ ├── single_assign_switch.yul │ │ │ │ ├── ssaReverse.yul │ │ │ │ └── two_vars.yul │ │ │ ├── ssaPlusCleanup/ │ │ │ │ ├── control_structures.yul │ │ │ │ ├── multi_reassign.yul │ │ │ │ └── multi_reassign_with_use.yul │ │ │ ├── ssaReverser/ │ │ │ │ ├── abi_example.yul │ │ │ │ ├── self_assign.yul │ │ │ │ └── simple.yul │ │ │ ├── ssaTransform/ │ │ │ │ ├── branches.yul │ │ │ │ ├── for_def_in_init.yul │ │ │ │ ├── for_reassign_body.yul │ │ │ │ ├── for_reassign_init.yul │ │ │ │ ├── for_reassign_post.yul │ │ │ │ ├── for_simple.yul │ │ │ │ ├── for_simpler.yul │ │ │ │ ├── function.yul │ │ │ │ ├── multi_assign.yul │ │ │ │ ├── multi_decl.yul │ │ │ │ ├── nested.yul │ │ │ │ ├── nested_reassign.yul │ │ │ │ ├── notransform.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── switch.yul │ │ │ │ ├── switch_no_default_case.yul │ │ │ │ ├── switch_reassign.yul │ │ │ │ ├── typed.yul │ │ │ │ └── used.yul │ │ │ ├── stackCompressor/ │ │ │ │ ├── inlineInBlock.yul │ │ │ │ ├── inlineInFunction.yul │ │ │ │ ├── noInline.yul │ │ │ │ └── unusedPrunerWithMSize.yul │ │ │ ├── stackLimitEvader/ │ │ │ │ ├── cycle.yul │ │ │ │ ├── cycle_after.yul │ │ │ │ ├── cycle_after_2.yul │ │ │ │ ├── cycle_before.yul │ │ │ │ ├── cycle_before_2.yul │ │ │ │ ├── cycle_before_after.yul │ │ │ │ ├── function_arg.yul │ │ │ │ ├── stub.yul │ │ │ │ ├── too_many_args_14.yul │ │ │ │ ├── too_many_args_15.yul │ │ │ │ ├── too_many_args_16.yul │ │ │ │ ├── too_many_returns_15.yul │ │ │ │ ├── too_many_returns_16.yul │ │ │ │ ├── tree.yul │ │ │ │ ├── verbatim_many_arguments.yul │ │ │ │ ├── verbatim_many_arguments_and_returns.yul │ │ │ │ └── verbatim_many_returns.yul │ │ │ ├── structuralSimplifier/ │ │ │ │ ├── bugfix_visit_after_change.yul │ │ │ │ ├── for_false_condition.yul │ │ │ │ ├── if_false_condition.yul │ │ │ │ ├── if_multi_unassigned_condition.yul │ │ │ │ ├── if_true_condition.yul │ │ │ │ ├── if_unassigned_condition.yul │ │ │ │ ├── nested.yul │ │ │ │ ├── switch_inline.yul │ │ │ │ ├── switch_inline_match_default.yul │ │ │ │ ├── switch_inline_no_match.yul │ │ │ │ ├── switch_inline_no_match_mixed.yul │ │ │ │ └── switch_no_remove_empty_case.yul │ │ │ ├── unusedAssignEliminator/ │ │ │ │ ├── conditionally_assign_before_conditional_revert.yul │ │ │ │ ├── conditionally_assign_before_leave.yul │ │ │ │ ├── conditionally_assign_before_revert.yul │ │ │ │ ├── for.yul │ │ │ │ ├── for_branch.yul │ │ │ │ ├── for_break.yul │ │ │ │ ├── for_continue.yul │ │ │ │ ├── for_continue_2.yul │ │ │ │ ├── for_continue_3.yul │ │ │ │ ├── for_decl_inside_break_continue.yul │ │ │ │ ├── for_deep_noremove.yul │ │ │ │ ├── for_deep_simple.yul │ │ │ │ ├── for_multi_break.yul │ │ │ │ ├── for_nested.yul │ │ │ │ ├── for_rerun.yul │ │ │ │ ├── for_stmnts_after_break_continue.yul │ │ │ │ ├── function.yul │ │ │ │ ├── if.yul │ │ │ │ ├── if_overwrite_all_branches.yul │ │ │ │ ├── if_used_in_one_branch.yul │ │ │ │ ├── leave.yul │ │ │ │ ├── multi_assign.yul │ │ │ │ ├── multivar.yul │ │ │ │ ├── non_movable.yul │ │ │ │ ├── remove_break.yul │ │ │ │ ├── remove_continue.yul │ │ │ │ ├── revert_after_assign_return.yul │ │ │ │ ├── scopes.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── switch_overwrite_in_all.yul │ │ │ │ ├── switch_overwrite_in_one.yul │ │ │ │ ├── switch_overwrite_use_combination.yul │ │ │ │ └── switch_unused.yul │ │ │ ├── unusedFunctionParameterPruner/ │ │ │ │ ├── LiteralRematerialiser.yul │ │ │ │ ├── multiple_param.yul │ │ │ │ ├── multiple_return.yul │ │ │ │ ├── nested_function.yul │ │ │ │ ├── nested_function_name_collision.yul │ │ │ │ ├── no_return.yul │ │ │ │ ├── no_unused.yul │ │ │ │ ├── recursion.yul │ │ │ │ ├── simple.yul │ │ │ │ ├── smoke.yul │ │ │ │ └── too_many_arguments.yul │ │ │ ├── unusedPruner/ │ │ │ │ ├── functions.yul │ │ │ │ ├── intermediate_assignment.yul │ │ │ │ ├── intermediate_multi_assignment.yul │ │ │ │ ├── keccak.yul │ │ │ │ ├── movable_user_defined_function.yul │ │ │ │ ├── msize.yul │ │ │ │ ├── multi_assign.yul │ │ │ │ ├── multi_assignments.yul │ │ │ │ ├── multi_declarations.yul │ │ │ │ ├── multi_declare.yul │ │ │ │ ├── multi_partial_assignments.yul │ │ │ │ ├── no_msize.yul │ │ │ │ ├── pop.yul │ │ │ │ ├── smoke.yul │ │ │ │ ├── transient_storage.yul │ │ │ │ ├── trivial.yul │ │ │ │ └── verbatim.yul │ │ │ ├── unusedStoreEliminator/ │ │ │ │ ├── call_does_not_need_to_write.yul │ │ │ │ ├── covering_calldatacopy.yul │ │ │ │ ├── covering_calldatacopy_fixed.yul │ │ │ │ ├── create.yul │ │ │ │ ├── create_inside_function.yul │ │ │ │ ├── function_end.yul │ │ │ │ ├── function_side_effects.yul │ │ │ │ ├── function_side_effects_2.yul │ │ │ │ ├── if_overwrite_all_branches.yul │ │ │ │ ├── leave.yul │ │ │ │ ├── mcopy_mcopy_no_overlap.yul │ │ │ │ ├── mcopy_mstore_no_overlap.yul │ │ │ │ ├── mcopy_non_overlapping_areas.yul │ │ │ │ ├── mcopy_overlapping_areas.yul │ │ │ │ ├── mcopy_overwriting_mcopy.yul │ │ │ │ ├── mcopy_overwriting_mstore.yul │ │ │ │ ├── mcopy_overwriting_mstore_overlap.yul │ │ │ │ ├── mcopy_reading_mcopy.yul │ │ │ │ ├── mcopy_reading_mstore.yul │ │ │ │ ├── mcopy_reading_mstore8.yul │ │ │ │ ├── mcopy_reading_mstore_overhang.yul │ │ │ │ ├── mcopy_reading_mstore_overlap.yul │ │ │ │ ├── mcopy_reading_mstore_underhang.yul │ │ │ │ ├── mcopy_reading_writing_overlapping_areas_mstore.yul │ │ │ │ ├── mcopy_reading_writing_same_area_mcopy.yul │ │ │ │ ├── mcopy_reading_writing_same_area_mstore.yul │ │ │ │ ├── mcopy_reading_writing_same_area_mstore8.yul │ │ │ │ ├── mcopy_reading_writing_same_area_mstore_overlap.yul │ │ │ │ ├── mcopy_same_area.yul │ │ │ │ ├── mcopy_same_write_area_overwriting_mcopy.yul │ │ │ │ ├── mcopy_sstore.yul │ │ │ │ ├── memoryguard.yul │ │ │ │ ├── mload.yul │ │ │ │ ├── mload_reading_mcopy.yul │ │ │ │ ├── mstore_overwriting_mcopy.yul │ │ │ │ ├── mstore_overwriting_mstore.yul │ │ │ │ ├── no_storage_inside_function.yul │ │ │ │ ├── overflow.yul │ │ │ │ ├── overlapping.yul │ │ │ │ ├── overlapping_small.yul │ │ │ │ ├── remove_before_revert.yul │ │ │ │ ├── returndatacopy_fixed_size.yul │ │ │ │ ├── returndatacopy_returndatasize.yul │ │ │ │ ├── returndatacopy_returndatasize_nonzero_start.yul │ │ │ │ ├── returndatacopy_returndatasize_var.yul │ │ │ │ ├── store_before_conditionally_terminating_function_call.yul │ │ │ │ ├── store_before_conditionally_terminating_function_call_complex_control_flow.yul │ │ │ │ ├── store_before_conditionally_terminating_function_call_revert.yul │ │ │ │ ├── store_before_indirectly_conditionally_terminating_function_call.yul │ │ │ │ ├── store_before_terminating_verbatim_revert.yul │ │ │ │ ├── store_before_unconditionally_terminating_function_call.yul │ │ │ │ ├── tload.yul │ │ │ │ ├── tstore.yul │ │ │ │ ├── unaligned_access.yul │ │ │ │ ├── unknown_length2.yul │ │ │ │ ├── unrelated_relative.yul │ │ │ │ └── write_before_recursion.yul │ │ │ ├── varDeclInitializer/ │ │ │ │ ├── ambiguous.yul │ │ │ │ ├── inside_func.yul │ │ │ │ ├── multi.yul │ │ │ │ ├── multi_assign.yul │ │ │ │ └── simple.yul │ │ │ └── varNameCleaner/ │ │ │ ├── builtins.yul │ │ │ ├── function_names.yul │ │ │ ├── function_parameters.yul │ │ │ ├── function_scopes.yul │ │ │ ├── instructions.yul │ │ │ ├── name_stripping.yul │ │ │ ├── reshuffling-inverse.yul │ │ │ └── reshuffling.yul │ │ ├── yulSSAControlFlowGraph/ │ │ │ ├── complex.yul │ │ │ ├── complex2.yul │ │ │ ├── default_initialized_variable.yul │ │ │ ├── function.yul │ │ │ ├── if.yul │ │ │ ├── if_const.yul │ │ │ ├── nested_for.yul │ │ │ ├── nested_function.yul │ │ │ ├── switch.yul │ │ │ └── switch_const.yul │ │ ├── yulStackLayout/ │ │ │ ├── complex.yul │ │ │ ├── eof/ │ │ │ │ └── function.yul │ │ │ ├── for.yul │ │ │ ├── function.yul │ │ │ ├── if.yul │ │ │ ├── literal_loop.yul │ │ │ ├── stub.yul │ │ │ ├── switch.yul │ │ │ └── variables.yul │ │ ├── yulStackShuffling/ │ │ │ ├── pop_early_to_avoid_swap17.stack │ │ │ ├── swap17.stack │ │ │ └── swap_cycle.stack │ │ └── yulSyntaxTests/ │ │ ├── are_we_perl_yet.yul │ │ ├── assign_from_stack.yul │ │ ├── assignment.yul │ │ ├── assignment_duplicate_vars.yul │ │ ├── assignment_of_function.yul │ │ ├── assignment_to_builtin.yul │ │ ├── assignment_to_number.yul │ │ ├── blobbasefee_identifier_pre_cancun.yul │ │ ├── blobbasefee_reserved_identifier_post_cancun.yul │ │ ├── blobhash.yul │ │ ├── blobhash_pre_cancun.yul │ │ ├── blocks.yul │ │ ├── break_outside_of_for_loop.yul │ │ ├── builtin_function_literal.yul │ │ ├── builtin_identifier_1.yul │ │ ├── builtin_identifier_2.yul │ │ ├── builtin_identifier_3.yul │ │ ├── builtin_identifier_4.yul │ │ ├── builtin_identifier_5.yul │ │ ├── builtin_identifier_6.yul │ │ ├── builtin_identifier_7.yul │ │ ├── builtin_types.yul │ │ ├── byte_of_string_literal.yul │ │ ├── call_literal.yul │ │ ├── clz.yul │ │ ├── clz_pre_osaka.yul │ │ ├── constants.yul │ │ ├── continue_outside_of_for_loop.yul │ │ ├── datacopy_shadowing.yul │ │ ├── dataoffset_shadowing.yul │ │ ├── datasize_shadowing.yul │ │ ├── declaration_duplicate_vars.yul │ │ ├── dot_consecutive_function.yul │ │ ├── dot_consecutive_function_arg.yul │ │ ├── dot_consecutive_function_ret.yul │ │ ├── dot_consecutive_variabledeclaration.yul │ │ ├── dot_ellipse_function.yul │ │ ├── dot_ellipse_function_arg.yul │ │ ├── dot_ellipse_function_ret.yul │ │ ├── dot_ellipse_variabledeclaration.yul │ │ ├── dot_leading_function.yul │ │ ├── dot_leading_function_arg.yul │ │ ├── dot_leading_function_ret.yul │ │ ├── dot_leading_variabledeclaration.yul │ │ ├── dot_middle_function.yul │ │ ├── dot_middle_function_arg.yul │ │ ├── dot_middle_function_ret.yul │ │ ├── dot_middle_variabledeclaration.yul │ │ ├── dot_trailing_function.yul │ │ ├── dot_trailing_function_arg.yul │ │ ├── dot_trailing_function_ret.yul │ │ ├── dot_trailing_variabledeclaration.yul │ │ ├── empty_call.yul │ │ ├── eof/ │ │ │ ├── auxdataloadn_in_eof.yul │ │ │ ├── auxdataloadn_in_eof_invalid_literal_type.yul │ │ │ ├── auxdataloadn_in_eof_invalid_value.yul │ │ │ ├── auxdataloadn_in_eof_offset_too_high.yul │ │ │ ├── auxdataloadn_in_legacy.yul │ │ │ ├── builtin_function_literal.yul │ │ │ ├── call_instruction_in_eof.yul │ │ │ ├── callf_jumpf_retf.yul │ │ │ ├── create2_in_eof.yul │ │ │ ├── datacopy_shadowing.yul │ │ │ ├── dataoffset_shadowing.yul │ │ │ ├── datasize_shadowing.yul │ │ │ ├── eof_identifiers_not_defined_in_legacy.yul │ │ │ ├── eof_identifiers_not_reserved_in_legacy.yul │ │ │ ├── eof_names_reserved_in_eof.yul │ │ │ ├── eof_opcodes_identifiers_reserved_in_eof.yul │ │ │ ├── eofcreate.yul │ │ │ ├── eofcreate_invalid_object.yul │ │ │ ├── eofcreate_invalid_object_name_data.yul │ │ │ ├── eofcreate_invalid_object_name_path.yul │ │ │ ├── extcall_function_in_eof.yul │ │ │ ├── extcalls.yul │ │ │ ├── extcalls_invalid_in_legacy.yul │ │ │ ├── extcodehash_in_eof.yul │ │ │ ├── extdelegatecall_function_in_eof.yul │ │ │ ├── extstaticcall_function_in_eof.yul │ │ │ ├── legacy_calls_in_eof.yul │ │ │ ├── loadimmutable_shadowing.yul │ │ │ ├── object_name_in_eof.yul │ │ │ ├── passing_builtin_with_literal_argument_into_literal_argument.yul │ │ │ ├── returncontract.yul │ │ │ ├── returncontract_invalid_object.yul │ │ │ ├── rjump_rjumpi.yul │ │ │ ├── selfdestruct.yul │ │ │ ├── setimmutable_shadowing.yul │ │ │ ├── too_large_code_section.yul │ │ │ ├── too_many_functions_arguments_or_returns.yul │ │ │ └── too_many_subcontainers.yul │ │ ├── for_expr_invalid_1.yul │ │ ├── for_expr_invalid_2.yul │ │ ├── for_expr_invalid_3.yul │ │ ├── for_expr_invalid_4.yul │ │ ├── for_expr_invalid_5.yul │ │ ├── for_expr_invalid_6.yul │ │ ├── for_loop_condition.yul │ │ ├── for_statement.yul │ │ ├── for_statement_2.yul │ │ ├── for_statement_break.yul │ │ ├── for_statement_break_init.yul │ │ ├── for_statement_break_nested_body_in_init.yul │ │ ├── for_statement_break_nested_body_in_post.yul │ │ ├── for_statement_break_post.yul │ │ ├── for_statement_continue.yul │ │ ├── for_statement_continue_fail_init.yul │ │ ├── for_statement_continue_fail_post.yul │ │ ├── for_statement_continue_nested_body_in_init.yul │ │ ├── for_statement_continue_nested_body_in_post.yul │ │ ├── for_statement_continue_nested_init_in_body.yul │ │ ├── for_statement_nested_break.yul │ │ ├── for_statement_nested_continue.yul │ │ ├── for_visibility_1.yul │ │ ├── for_visibility_2.yul │ │ ├── for_visibility_3.yul │ │ ├── for_visibility_4.yul │ │ ├── for_visibility_5.yul │ │ ├── for_visibility_6.yul │ │ ├── for_visibility_7.yul │ │ ├── for_visibility_8.yul │ │ ├── for_visibility_9.yul │ │ ├── for_visibility_A.yul │ │ ├── for_visibility_B.yul │ │ ├── for_visibility_C.yul │ │ ├── for_visibility_D.yul │ │ ├── for_visibility_E.yul │ │ ├── function_calls.yul │ │ ├── function_calls_2.yul │ │ ├── function_def_multiple_args.yul │ │ ├── function_defined_in_init_block_1.yul │ │ ├── function_defined_in_init_block_2.yul │ │ ├── function_defined_in_init_block_3.yul │ │ ├── function_defined_in_init_nested_1.yul │ │ ├── function_defined_in_init_nested_2.yul │ │ ├── function_defined_in_init_nested_3.yul │ │ ├── function_definition.yul │ │ ├── function_definition_whitespace.yul │ │ ├── function_definitions.yul │ │ ├── function_embedded.yul │ │ ├── function_literal.yul │ │ ├── function_literal_valid.yul │ │ ├── function_shadowing_outside_vars_1.yul │ │ ├── function_shadowing_outside_vars_2.yul │ │ ├── functional.yul │ │ ├── functional_assign_complex.yul │ │ ├── functional_assignment.yul │ │ ├── functional_partial.yul │ │ ├── functional_partial_success.yul │ │ ├── functional_returndatacopy.yul │ │ ├── functions_in_parallel_scopes.yul │ │ ├── functions_multiple_args.yul │ │ ├── hex_assignment.yul │ │ ├── hex_assignment_long.yul │ │ ├── hex_expression.yul │ │ ├── hex_string_literal_non_printable_characters.yul │ │ ├── hex_string_literal_odd.yul │ │ ├── hex_switch_case.yul │ │ ├── hex_switch_case_long.yul │ │ ├── if_statement.yul │ │ ├── if_statement_1.yul │ │ ├── if_statement_2.yul │ │ ├── if_statement_3.yul │ │ ├── if_statement_fail_1.yul │ │ ├── if_statement_fail_2.yul │ │ ├── if_statement_invalid_1.yul │ │ ├── if_statement_invalid_2.yul │ │ ├── if_statement_invalid_3.yul │ │ ├── if_statement_invalid_4.yul │ │ ├── if_statement_scope_1.yul │ │ ├── if_statement_scope_2.yul │ │ ├── instructions.yul │ │ ├── instructions_too_few_args_1.yul │ │ ├── instructions_too_few_args_2.yul │ │ ├── instructions_too_many_args.yul │ │ ├── invalid/ │ │ │ ├── builtin_name_as_type.yul │ │ │ ├── clash_with_non_reserved_pure_yul_builtin.yul │ │ │ ├── clash_with_reserved_builtin.yul │ │ │ ├── clash_with_reserved_non_builtin.yul │ │ │ ├── clash_with_reserved_pure_yul_builtin.yul │ │ │ ├── clash_with_reserved_pure_yul_builtin_eof.yul │ │ │ ├── dup_disallowed.yul │ │ │ ├── invalid_octal_number.yul │ │ │ ├── jump_disallowed.yul │ │ │ ├── jumpdest_disallowed.yul │ │ │ ├── jumpi_disallowed.yul │ │ │ ├── label_disallowed.yul │ │ │ ├── leave_items_on_stack.yul │ │ │ ├── leave_items_on_stack_with_debug_info.yul │ │ │ ├── literals_on_stack_disallowed.yul │ │ │ ├── literals_on_stack_disallowed_with_debug_info.yul │ │ │ ├── pc_disallowed.yul │ │ │ ├── push0_disallowed.yul │ │ │ ├── push_disallowed.yul │ │ │ ├── reserved_identifier_as_type.yul │ │ │ ├── swap_disallowed.yul │ │ │ ├── unicode_comment_direction_override.yul │ │ │ ├── unicode_string_direction_override.yul │ │ │ ├── verbatim_empty_string.yul │ │ │ ├── verbatim_leading_zero.yul │ │ │ ├── verbatim_reserved.yul │ │ │ └── verbatim_reserved2.yul │ │ ├── invalid_tuple_assignment.yul │ │ ├── invalid_tuple_assignment_with_debug_info.yul │ │ ├── invalid_type.yul │ │ ├── invalid_type2.yul │ │ ├── invalid_type3.yul │ │ ├── invalid_type4.yul │ │ ├── keywords.yul │ │ ├── linkersymbol_bad_literal.yul │ │ ├── linkersymbol_evm.yul │ │ ├── linkersymbol_invalid_redefine_builtin.yul │ │ ├── linkersymbol_non_literal_args.yul │ │ ├── linkersymbol_shadowing.yul │ │ ├── literal_invalid_type.yul │ │ ├── loadimmutable.yul │ │ ├── loadimmutable_bad_literal.yul │ │ ├── loadimmutable_shadowing.yul │ │ ├── loadimmutable_without_setimmutable.yul │ │ ├── mcopy.yul │ │ ├── mcopy_as_identifier.yul │ │ ├── mcopy_as_identifier_pre_cancun.yul │ │ ├── mcopy_pre_cancun.yul │ │ ├── mcopy_wrong_args.yul │ │ ├── metadata_access.yul │ │ ├── metadata_access_2.yul │ │ ├── metadata_access_subobject.yul │ │ ├── more_than_256_analysis_errors.yul │ │ ├── multiple_assignment_1.yul │ │ ├── multiple_assignment_2.yul │ │ ├── multiple_assignment_3.yul │ │ ├── name_clash_function_var_subscope.yul │ │ ├── name_clash_function_var_subscope_reverse.yul │ │ ├── name_clash_sub_scope.yul │ │ ├── name_clash_sub_scope_reverse.yul │ │ ├── name_clash_sub_scope_with_debug_info.yul │ │ ├── name_clashes.yul │ │ ├── number_literal_1.yul │ │ ├── number_literal_2.yul │ │ ├── number_literal_3.yul │ │ ├── number_literal_4.yul │ │ ├── number_literal_5.yul │ │ ├── number_literals_1.yul │ │ ├── number_literals_2.yul │ │ ├── number_literals_3.yul │ │ ├── number_literals_4.yul │ │ ├── number_literals_5.yul │ │ ├── objects/ │ │ │ ├── basic_subobject.yul │ │ │ ├── code.yul │ │ │ ├── code_without_object.yul │ │ │ ├── complex_subobject.yul │ │ │ ├── conflict_data_data.yul │ │ │ ├── conflict_data_parent.yul │ │ │ ├── conflict_object_data.yul │ │ │ ├── conflict_object_object.yul │ │ │ ├── conflict_object_parent.yul │ │ │ ├── data.yul │ │ │ ├── data_access.yul │ │ │ ├── data_first.yul │ │ │ ├── data_hex_name.yul │ │ │ ├── data_invalid_hex1.yul │ │ │ ├── data_invalid_hex2.yul │ │ │ ├── data_name_with_literal_newline.yul │ │ │ ├── data_name_with_special_chars.yul │ │ │ ├── datacopy.yul │ │ │ ├── dataoffset_nonliteral.yul │ │ │ ├── dataoffset_nonstring.yul │ │ │ ├── dataoffset_notfound.yul │ │ │ ├── datasize_nonliteral.yul │ │ │ ├── datasize_nonstring.yul │ │ │ ├── datasize_notfound.yul │ │ │ ├── empty_code.yul │ │ │ ├── empty_data.yul │ │ │ ├── empty_object.yul │ │ │ ├── empty_object_name.yul │ │ │ ├── incomplete1.yul │ │ │ ├── incomplete2.yul │ │ │ ├── multiple_code.yul │ │ │ ├── multiple_data.yul │ │ │ ├── multiple_root_object.yul │ │ │ ├── nested_object.yul │ │ │ ├── object_hex_name.yul │ │ │ ├── object_name_with_all_special_chars.yul │ │ │ ├── object_name_with_special_chars.yul │ │ │ ├── subobject_access.yul │ │ │ ├── subobject_first.yul │ │ │ └── subobject_hex_name.yul │ │ ├── opcode_for_function_args_1.yul │ │ ├── opcode_for_function_args_2.yul │ │ ├── opcode_for_functions.yul │ │ ├── optional_types.yul │ │ ├── passing_builtin_with_literal_argument_into_literal_argument.yul │ │ ├── period_in_identifier.yul │ │ ├── period_in_identifier_spaced_1.yul │ │ ├── period_in_identifier_spaced_2.yul │ │ ├── period_in_identifier_spaced_3.yul │ │ ├── period_in_identifier_start.yul │ │ ├── period_in_identifier_start_with_comment.yul │ │ ├── period_not_as_identifier_start.yul │ │ ├── push.yul │ │ ├── recursion_depth.yul │ │ ├── selfdestruct.yul │ │ ├── setimmutable.yul │ │ ├── setimmutable_bad_literal.yul │ │ ├── setimmutable_shadowing.yul │ │ ├── simple_functions.yul │ │ ├── simple_instructions.yul │ │ ├── smoke.yul │ │ ├── smoke_test.yul │ │ ├── solidity_keywords.yul │ │ ├── string_literal_switch_case.yul │ │ ├── string_literal_too_long.yul │ │ ├── string_literal_too_long_byte.yul │ │ ├── string_literal_too_long_immutable.yul │ │ ├── string_literal_too_long_linkersymbol.yul │ │ ├── surplus_input.yul │ │ ├── switch_case.yul │ │ ├── switch_case_different_literal.yul │ │ ├── switch_case_string_literal_too_long.yul │ │ ├── switch_case_string_literal_very_long.yul │ │ ├── switch_default_before_case.yul │ │ ├── switch_duplicate_case.yul │ │ ├── switch_duplicate_case_different_literal.yul │ │ ├── switch_duplicate_default.yul │ │ ├── switch_invalid_body.yul │ │ ├── switch_invalid_case.yul │ │ ├── switch_invalid_expr_1.yul │ │ ├── switch_invalid_expr_2.yul │ │ ├── switch_invalid_expr_3.yul │ │ ├── switch_statement_1.yul │ │ ├── switch_statement_2.yul │ │ ├── switch_statement_duplicate_case.yul │ │ ├── switch_statement_no_access.yul │ │ ├── tload_as_identifier_post_cancun.yul │ │ ├── token_as_identifier.yul │ │ ├── tstore_as_identifier_post_cancun.yul │ │ ├── tstore_tload.yul │ │ ├── tstore_tload_as_identifiers_pre_cancun.yul │ │ ├── tstore_warning_only_once.yul │ │ ├── tuple_assignment.yul │ │ ├── user_defined_functions_fail.yul │ │ ├── user_defined_functions_fine.yul │ │ ├── vardecl.yul │ │ ├── vardecl_bool.yul │ │ ├── vardecl_complex.yul │ │ ├── vardecl_empty.yul │ │ ├── vardecl_multi.yul │ │ ├── vardecl_multi_conflict.yul │ │ ├── vardecl_name_clashes.yul │ │ ├── variable_access_cross_funcs.yul │ │ ├── variable_declaration.yul │ │ ├── variable_declaration_bool.yul │ │ ├── variable_declaration_complex.yul │ │ ├── variable_declaration_empty.yul │ │ ├── variable_use_before_decl_1.yul │ │ ├── variable_use_before_decl_2.yul │ │ └── verbatim_leading_zero.yul │ ├── localeTest.sh │ ├── lsp.py │ ├── pyscriptTests.py │ ├── scripts/ │ │ ├── fixtures/ │ │ │ ├── code_block.rst │ │ │ ├── code_block_with_directives.rst │ │ │ ├── code_generation_error_cli_output.txt │ │ │ ├── code_generation_error_json_output.json │ │ │ ├── eth_gas_report_gnosis.rst │ │ │ ├── library_inherited2_sol_cli_output.txt │ │ │ ├── library_inherited2_sol_json_output.json │ │ │ ├── smt_contract_with_cr_newlines.sol │ │ │ ├── smt_contract_with_crlf_newlines.sol │ │ │ ├── smt_contract_with_lf_newlines.sol │ │ │ ├── smt_contract_with_mixed_newlines.sol │ │ │ ├── smt_smoke_test.sol │ │ │ ├── solc_0.4.0_cli_output.txt │ │ │ ├── solc_0.4.8_cli_output.txt │ │ │ ├── stack_too_deep_cli_output.txt │ │ │ ├── stack_too_deep_json_output.json │ │ │ ├── summarized-benchmark-diff-develop-branch-humanized.md │ │ │ ├── summarized-benchmarks-branch.json │ │ │ ├── summarized-benchmarks-develop.json │ │ │ ├── unimplemented_feature_cli_output.txt │ │ │ ├── unimplemented_feature_json_output.json │ │ │ ├── unknown_pragma_sol_cli_output.txt │ │ │ └── unknown_pragma_sol_json_output.json │ │ ├── test_bytecodecompare_prepare_report.py │ │ ├── test_externalTests_benchmark_diff.py │ │ ├── test_externalTests_benchmark_downloader.py │ │ ├── test_externalTests_parse_eth_gas_report.py │ │ ├── test_gas_diff_stats.py │ │ ├── test_isolate_tests.py │ │ └── unittest_helpers.py │ ├── solc/ │ │ ├── CommandLineInterface.cpp │ │ ├── CommandLineInterfaceAllowPaths.cpp │ │ ├── CommandLineParser.cpp │ │ ├── Common.cpp │ │ └── Common.h │ ├── soltest.cpp │ ├── stopAfterParseTests.sh │ ├── tools/ │ │ ├── CMakeLists.txt │ │ ├── IsolTestOptions.cpp │ │ ├── IsolTestOptions.h │ │ ├── afl_fuzzer.cpp │ │ ├── fuzzer_common.cpp │ │ ├── fuzzer_common.h │ │ ├── isoltest.cpp │ │ ├── ossfuzz/ │ │ │ ├── AbiV2IsabelleFuzzer.cpp │ │ │ ├── CMakeLists.txt │ │ │ ├── Generators.h │ │ │ ├── README.md │ │ │ ├── SolidityCustomMutatorInterface.cpp │ │ │ ├── SolidityCustomMutatorInterface.h │ │ │ ├── SolidityEvmoneInterface.cpp │ │ │ ├── SolidityEvmoneInterface.h │ │ │ ├── SolidityGenerator.cpp │ │ │ ├── SolidityGenerator.h │ │ │ ├── StackReuseCodegenFuzzer.cpp │ │ │ ├── YulEvmoneInterface.cpp │ │ │ ├── YulEvmoneInterface.h │ │ │ ├── abiV2Proto.proto │ │ │ ├── abiV2ProtoFuzzer.cpp │ │ │ ├── config/ │ │ │ │ ├── solc_noopt_ossfuzz.options │ │ │ │ ├── solc_opt_ossfuzz.options │ │ │ │ ├── solidity.dict │ │ │ │ ├── strict_assembly.dict │ │ │ │ ├── strictasm_assembly_ossfuzz.options │ │ │ │ └── strictasm_opt_ossfuzz.options │ │ │ ├── const_opt_ossfuzz.cpp │ │ │ ├── protoToAbiV2.cpp │ │ │ ├── protoToAbiV2.h │ │ │ ├── protoToSol.cpp │ │ │ ├── protoToSol.h │ │ │ ├── protoToYul.cpp │ │ │ ├── protoToYul.h │ │ │ ├── protomutators/ │ │ │ │ ├── YulProtoMutator.cpp │ │ │ │ └── YulProtoMutator.h │ │ │ ├── solProto.proto │ │ │ ├── solProtoFuzzer.cpp │ │ │ ├── solc_ossfuzz.cpp │ │ │ ├── strictasm_assembly_ossfuzz.cpp │ │ │ ├── strictasm_diff_ossfuzz.cpp │ │ │ ├── strictasm_opt_ossfuzz.cpp │ │ │ ├── yulFuzzerCommon.cpp │ │ │ ├── yulFuzzerCommon.h │ │ │ ├── yulOptimizerFuzzDictionary.h │ │ │ ├── yulProto.proto │ │ │ ├── yulProtoFuzzer.cpp │ │ │ └── yulProto_diff_ossfuzz.cpp │ │ ├── yulInterpreter/ │ │ │ ├── CMakeLists.txt │ │ │ ├── EVMInstructionInterpreter.cpp │ │ │ ├── EVMInstructionInterpreter.h │ │ │ ├── Inspector.cpp │ │ │ ├── Inspector.h │ │ │ ├── Interpreter.cpp │ │ │ └── Interpreter.h │ │ ├── yulopti.cpp │ │ └── yulrun.cpp │ └── yulPhaser/ │ ├── AlgorithmRunner.cpp │ ├── Chromosome.cpp │ ├── Common.cpp │ ├── FitnessMetrics.cpp │ ├── GeneticAlgorithms.cpp │ ├── Mutations.cpp │ ├── PairSelections.cpp │ ├── Phaser.cpp │ ├── Population.cpp │ ├── Program.cpp │ ├── ProgramCache.cpp │ ├── Selections.cpp │ ├── SimulationRNG.cpp │ ├── TestHelpers.cpp │ ├── TestHelpers.h │ └── TestHelpersTest.cpp └── tools/ ├── CMakeLists.txt └── yulPhaser/ ├── AlgorithmRunner.cpp ├── AlgorithmRunner.h ├── Chromosome.cpp ├── Chromosome.h ├── Common.cpp ├── Common.h ├── Exceptions.h ├── FitnessMetrics.cpp ├── FitnessMetrics.h ├── GeneticAlgorithms.cpp ├── GeneticAlgorithms.h ├── Mutations.cpp ├── Mutations.h ├── PairSelections.cpp ├── PairSelections.h ├── Phaser.cpp ├── Phaser.h ├── Population.cpp ├── Population.h ├── Program.cpp ├── Program.h ├── ProgramCache.cpp ├── ProgramCache.h ├── README.md ├── Selections.cpp ├── Selections.h ├── SimulationRNG.cpp ├── SimulationRNG.h └── main.cpp ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/README.md ================================================ ## CircleCI integration ### Docker images The docker images are built locally on the developer machine: ```sh cd .circleci/docker/ docker build -t ethereum/solidity-buildpack-deps:ubuntu2404- -f Dockerfile.ubuntu2404 . docker push ethereum/solidity-buildpack-deps:ubuntu2404- ``` The current revisions per docker image are stored in [circle ci pipeline parameters](https://github.com/CircleCI-Public/api-preview-docs/blob/master/docs/pipeline-parameters.md#pipeline-parameters) called `-docker-image-rev` (e.g., `ubuntu-2404-docker-image-rev`). Please update the value assigned to the parameter(s) corresponding to the docker image(s) being updated at the time of the update. Please verify that the value assigned to the parameter matches the revision part of the docker image tag (`` in the docker build/push snippet shown above). Otherwise, the docker image used by circle ci and the one actually pushed to docker hub will differ. Once the docker image has been built and pushed to Docker Hub, you can find it at: https://hub.docker.com/r/ethereum/solidity-buildpack-deps:ubuntu2404- where the image tag reflects the target OS and revision to build Solidity and run its tests on. ### Testing docker images locally ```sh cd solidity # Mounts your local solidity directory in docker container for testing docker run -v `pwd`:/src/solidity -ti ethereum/solidity-buildpack-deps:ubuntu2404- /bin/bash cd /src/solidity ``` ================================================ FILE: .circleci/cln-asan.supp ================================================ leak:*libcln* ================================================ FILE: .circleci/compare_bytecode_reports.sh ================================================ #!/usr/bin/env bash set -euo pipefail #------------------------------------------------------------------------------ # Compares bytecode reports generated by prepare_report.py/.js. # # ------------------------------------------------------------------------------ # This file is part of solidity. # # solidity is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # solidity is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with solidity. If not, see # # (c) 2023 solidity contributors. #------------------------------------------------------------------------------ no_cli_platforms=( emscripten ) native_platforms=( ubuntu2004-static ubuntu_arm ubuntu osx osx_intel windows ) interfaces=( cli standard-json ) for preset in "$@"; do report_files=() for platform in "${no_cli_platforms[@]}"; do report_files+=("bytecode-report-${platform}-${preset}.txt") done for platform in "${native_platforms[@]}"; do for interface in "${interfaces[@]}"; do report_files+=("bytecode-report-${platform}-${interface}-${preset}.txt") done done echo "Reports to compare:" printf -- "- %s\n" "${report_files[@]}" if ! diff --brief --report-identical-files --from-file "${report_files[@]}"; then diff --unified=0 --report-identical-files --from-file "${report_files[@]}" | head --lines 50 zip "bytecode-reports-${preset}.zip" "${report_files[@]}" exit 1 fi done ================================================ FILE: .circleci/config.yml ================================================ # vim:ts=2:sw=2:et # -------------------------------------------------------------------------- # Prefixes used in order to keep CircleCI workflow overview more readable: # - b: build # - t: test # - ubu: ubuntu # - ems: Emscripten version: 2.1 parameters: ubuntu-2004-docker-image: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2004-26 default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:1f387a77be889f65a2a25986a5c5eccc88cec23fabe6aeaf351790751145c81e" ubuntu-2404-docker-image: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404-7 default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:e52bd8fbb38908f203c6866e39562548faf26e5b7a5174f9860b44aae2b8f0cd" ubuntu-2404-arm-docker-image: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.arm-3 default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:1e6dbf9a9173f2645449281a1e11918a95ca6dc04e59aa9d70824cffc44697ed" ubuntu-2404-clang-docker-image: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu2404.clang-8 default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:e283c8ec6a59c76565c89b856d8019af2fa5beb96f27d3064fc4dda42bf3524d" ubuntu-clang-ossfuzz-docker-image: type: string # ghcr.io/argotorg/solidity-buildpack-deps:ubuntu.clang.ossfuzz-13 default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:2acb5d6f254ece25a96096f26960b5fe114eb86ceca92312cd20d59c096bf6e4" emscripten-docker-image: type: string # NOTE: Please remember to update the `scripts/build_emscripten.sh` whenever the hash of this image changes. # ghcr.io/argotorg/solidity-buildpack-deps:emscripten-22 default: "ghcr.io/argotorg/solidity-buildpack-deps@sha256:b9c953144d82cca5553f65626bc43b8af456dbc8966f8732ff9522f33ca8d722" evm-version: type: string default: osaka orbs: win: circleci/windows@2.2.0 commands: matrix_notify_unless_pr: description: "Posts a notification to the solidity-dev room on Matrix (if not running on a PR)." parameters: event: type: enum enum: ["failure", "success", "release"] condition: type: string steps: - run: name: "Matrix notification" when: << parameters.condition >> command: scripts/ci/notification/matrix_notification.sh << parameters.event >> matrix_notify_failure_unless_pr: description: "Posts a failure notification to the main room on Matrix (if not running on a PR)." steps: - matrix_notify_unless_pr: event: failure condition: on_fail matrix_notify_success_unless_pr: description: "Posts a success notification to the main room on Matrix (if not running on a PR)." steps: - matrix_notify_unless_pr: event: success condition: on_success matrix_notify_release_unless_pr: description: "Posts a release notification to the main room on Matrix (if not running on a PR)." steps: - matrix_notify_unless_pr: event: release condition: on_success restore_ccache_if_allowed: description: "Restore ccache unless on a tag or a skipped branch." parameters: skip_branches_regex: description: "Regex of branches that should skip restoring the cache." type: string default: "^(develop|breaking)$" steps: # Tags always skip ccache. Selected branches intentionally start from scratch. - when: condition: and: - equal: ["", << pipeline.git.tag >>] - not: matches: pattern: "<< parameters.skip_branches_regex >>" value: << pipeline.git.branch >> steps: - restore_cache: keys: # Reuse cache produced on develop (prefix match; restores the most recent). - v1-ccache-{{ .Environment.CIRCLE_JOB }}-develop- save_ccache_if_develop: description: "Save a fresh ccache only on the develop branch." steps: # On `develop` we always generate a fresh cache by never restoring and by saving under a unique key. - when: condition: equal: ["develop", << pipeline.git.branch >>] steps: - save_cache: key: v1-ccache-{{ .Environment.CIRCLE_JOB }}-develop-{{ .Revision }} paths: - ~/.ccache run_with_ccache_unless_tag: description: "Run a command with ccache enabled unless building a tag." parameters: command: type: string step_name: type: string steps: - when: condition: equal: ["", << pipeline.git.tag >>] steps: - run: name: << parameters.step_name >> (ccache) command: << parameters.command >> - when: condition: not: equal: ["", << pipeline.git.tag >>] steps: - run: name: << parameters.step_name >> (no ccache) command: CCACHE_DISABLE=1 << parameters.command >> prepare_bytecode_report: description: "Generate bytecode report and upload it as an artifact." parameters: label: type: string binary_type: type: enum enum: - solcjs - native - osx_intel binary_path: type: string preset: type: string steps: - run: name: Generate bytecode reports for the selected preset command: | .circleci/parallel_bytecode_report.sh \ "<< parameters.label >>" \ "<< parameters.binary_type >>" \ "${PWD}/<< parameters.binary_path >>" \ "<< parameters.preset >>" - store_artifacts: path: bytecode-report-<< parameters.label >>-standard-json-<< parameters.preset >>.txt - store_artifacts: path: bytecode-report-<< parameters.label >>-cli-<< parameters.preset >>.txt - store_artifacts: path: bytecode-report-<< parameters.label >>-<< parameters.preset >>.txt - persist_to_workspace: root: . paths: - bytecode-report-<< parameters.label >>*.txt - matrix_notify_failure_unless_pr install_python3: description: "Install python3 and given packages." parameters: packages: description: "List of extra Python packages to be installed (separated by space)." type: string default: "" steps: - run: name: Install python and dependencies command: | sudo apt update sudo apt install python3 python3-pip --assume-yes --no-install-recommends if [[ "<< parameters.packages >>" != "" ]] then echo "Installing additional packages..." python3 -m pip install --user --break-system-packages << parameters.packages >> fi install_foundry: description: "Install Foundry." parameters: version: type: string default: "stable" install_path: type: string default: /home/circleci/bin steps: - run: name: Setup Foundry environment variables command: | FOUNDRY_REPO="foundry-rs/foundry" FOUNDRY_VERSION="<< parameters.version >>" RELEASE_URL="https://github.com/${FOUNDRY_REPO}/releases/download/${FOUNDRY_VERSION}" echo "export FOUNDRY_VERSION=${FOUNDRY_VERSION}" >> "$BASH_ENV" echo "export RELEASE_URL=${RELEASE_URL}" >> "$BASH_ENV" ATTESTATION_URL=$(curl --silent --location --fail "${RELEASE_URL}/foundry_${FOUNDRY_VERSION}_linux_amd64.attestation.txt") || { echo "Failed to fetch attestation file" exit 1 } ATTESTATION_JSON=$(curl --silent --location --fail --header "Accept: application/json" "${ATTESTATION_URL}") || { echo "Failed to fetch attestation JSON" exit 1 } RELEASE_SHA=$(echo "${ATTESTATION_JSON}" | jq --raw-output '.payload.attestation.sourceRepositoryDigest') if [[ -z "$RELEASE_SHA" || "$RELEASE_SHA" == "null" ]]; then echo "Failed to extract release SHA from attestation" exit 1 fi echo "${RELEASE_SHA}" > /tmp/workspace/foundry-release-sha # Extract forge checksum from the attestation EXPECTED_FORGE_CHECKSUM=$(echo "${ATTESTATION_JSON}" | jq --raw-output '.payload.attestation.subjects[] | select(.subjectName=="forge") | .subjectDigest' | sed 's/sha256://') if [[ -z "$EXPECTED_FORGE_CHECKSUM" || "$EXPECTED_FORGE_CHECKSUM" == "null" ]]; then echo "Failed to extract forge checksum from attestation" exit 1 fi echo "export EXPECTED_FORGE_CHECKSUM=${EXPECTED_FORGE_CHECKSUM}" >> "$BASH_ENV" - restore_cache: keys: - foundry-v1-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }} # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually. - run: name: Install foundry command: | if forge --version 2> /dev/null; then echo "Foundry already cached, skipping install" else curl --fail --location --output /tmp/foundry.tar.gz "${RELEASE_URL}/foundry_${FOUNDRY_VERSION}_linux_amd64.tar.gz" cd "<< parameters.install_path >>" tar --extract --gzip --file /tmp/foundry.tar.gz --one-top-level # TODO: Use `gh attestation verify foundry/forge --owner foundry-rs` for signature verification. # Current approach only verifies checksum without validating the signature. # https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations#verifying-an-artifact-attestation-for-binaries ACTUAL=$(sha256sum foundry/forge | cut --delimiter=' ' --fields=1) if [[ "$EXPECTED_FORGE_CHECKSUM" != "$ACTUAL" ]]; then echo "Checksum mismatch: expected $EXPECTED_FORGE_CHECKSUM, got $ACTUAL" exit 1 fi ln --symbolic --force foundry/{forge,anvil,cast,chisel} . fi - save_cache: key: foundry-v1-<< parameters.version >>-{{ arch }}-{{ checksum "/tmp/workspace/foundry-release-sha" }} paths: - << parameters.install_path >> # -------------------------------------------------------------------------- # Build Commands setup_prerelease: steps: - run: name: Store prerelease suffix command: | "scripts/prerelease_suffix.sh" nightly "$CIRCLE_TAG" > prerelease.txt install_and_check_minimum_requirements: parameters: compiler: description: "Compiler to check: gcc or clang" type: enum enum: - gcc - clang steps: - run: name: Install and check minimum requirements command: scripts/ci/install_and_check_minimum_requirements.sh "--<< parameters.compiler >>" run_build: steps: - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: Build command: scripts/ci/build.sh - save_ccache_if_develop run_build_ossfuzz: steps: - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: Build_ossfuzz command: scripts/ci/build_ossfuzz.sh - save_ccache_if_develop run_proofs: steps: - run: name: Correctness proofs for optimization rules command: scripts/run_proofs.sh run_soltest: steps: - run: name: soltest no_output_timeout: 30m command: .circleci/soltest.sh run_soltest_all: parameters: # NOTE: If not specified, soltest_all.sh will use the default values as specified in the script. # In other words, it will execute for all EVM versions that are not marked as low priority. evm_versions: description: "List of EVM versions (separated by space)." type: string default: "" steps: - run: name: soltest_all no_output_timeout: 30m command: .circleci/soltest_all.sh "<< parameters.evm_versions >>" run_cmdline_tests: steps: - run: name: command line tests no_output_timeout: 30m command: .circleci/parallel_cli_tests.py run_docs_pragma_min_version: steps: - run: name: docs pragma version check command: scripts/docs_version_pragma_check.sh # -------------------------------------------------------------------------- # Artifact Commands store_artifacts_solc: description: Store compiled solc executable as artifact steps: - store_artifacts: path: build/solc/solc destination: solc store_artifacts_yul_phaser: steps: - store_artifacts: path: build/tools/yul-phaser destination: yul-phaser persist_executables_to_workspace: description: Persist compiled target executables to workspace steps: - persist_to_workspace: root: build paths: - solc/solc - test/soltest - test/tools/solfuzzer persist_executables_to_workspace_arm: description: Persist compiled target executables to workspace on Linux arm64 steps: - persist_to_workspace: root: build paths: - solc/solc-static-linux-arm - test/soltest-linux-arm - test/tools/solfuzzer-linux-arm persist_executables_to_workspace_osx: description: Persist compiled target executables to workspace on macOS steps: - persist_to_workspace: root: . paths: - build/solc/solc - build/test/soltest - build/test/tools/solfuzzer persist_ossfuzz_executables_to_workspace: description: Persist compiled OSSFUZZ executables to workspace steps: - persist_to_workspace: root: build paths: - test/tools/ossfuzz/abiv2_proto_ossfuzz - test/tools/ossfuzz/abiv2_isabelle_ossfuzz - test/tools/ossfuzz/const_opt_ossfuzz - test/tools/ossfuzz/solc_mutator_ossfuzz - test/tools/ossfuzz/solc_ossfuzz - test/tools/ossfuzz/stack_reuse_codegen_ossfuzz - test/tools/ossfuzz/strictasm_assembly_ossfuzz - test/tools/ossfuzz/strictasm_diff_ossfuzz - test/tools/ossfuzz/strictasm_opt_ossfuzz - test/tools/ossfuzz/yul_proto_diff_ossfuzz - test/tools/ossfuzz/yul_proto_diff_custom_mutate_ossfuzz - test/tools/ossfuzz/yul_proto_ossfuzz - test/tools/ossfuzz/sol_proto_ossfuzz store_artifacts_test_results: description: Store test output dir as artifact steps: - store_artifacts: path: test_results/ destination: test_results/ # -------------------------------------------------------------------------- # Complex Build Commands soltest: steps: - checkout - attach_workspace: at: build # NOTE: Different build jobs produce different soltest executables (release/debug, # clang/gcc, windows/linux/macos, etc.). The executable used by these steps comes from the # attached workspace and we only see the items added to the workspace by jobs we depend on. - run_soltest - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr test_lsp: steps: - checkout - attach_workspace: at: build - run: name: Executing solc LSP test suite command: test/lsp.py build/solc/solc --non-interactive - matrix_notify_failure_unless_pr build: steps: - checkout - run_build - store_artifacts_solc - store_artifacts_yul_phaser - persist_executables_to_workspace - matrix_notify_failure_unless_pr soltest_all: steps: - checkout - attach_workspace: at: build - run_soltest_all - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr cmdline_tests: steps: - checkout - attach_workspace: at: build - run_cmdline_tests - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr install_dependencies_osx: # An extra cache key is used to only save the flag that communicates whether the cache exists. # if this flag was set (the cache exist) we remove all files located in /usr/local & /opt/homebrew. # With this simple trick restoring the cache is much faster. Otherwise CircleCI is generating # warning messages if a file from the cache is overwriting an already existing file on disk. # Restoring the cache is much faster if we remove all potentially conflicting files beforehand. steps: - restore_cache: keys: - macos-dependencies-cached-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} - run: name: Installing dependencies / Restoring dependency cache command: | if [[ -f ~/macos-dependencies-cached ]]; then echo "Dependency flag exists. Removing /usr/local/, /opt/homebrew/, and /opt/boost. These directories will be restored from cache." # CircleCI is providing the circleci cli tools via some kind of symlink magic. # So we just save the original symlinks and restore them later. circleci_binary_path=$(command -v circleci) circleci_agent_binary_path=$(command -v circleci-agent) cp "${circleci_binary_path}" /tmp/circleci cp "${circleci_agent_binary_path}" /tmp/circleci-agent # Homebrew is installed in /usr/local on intel macs, but in /opt/homebrew on apple silicon. if [[ -d /opt/homebrew ]]; then sudo rm -rf /opt/homebrew sudo mkdir -p /opt/homebrew/bin sudo chmod 777 /opt/{homebrew,homebrew/bin} fi # under macos /usr/local itself is read-only, so we just remove its sub-directories. sudo rm -rf /usr/local/* sudo mkdir -p /usr/local/bin sudo chmod 777 /usr/{local,local/bin} sudo rm -rf /opt/boost sudo mkdir -p /opt/boost sudo chmod 777 /opt/boost mv /tmp/circleci "${circleci_binary_path}" mv /tmp/circleci-agent "${circleci_agent_binary_path}" fi - restore_cache: keys: - macos-dependencies-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} # DO NOT EDIT between here and save_cache, but rather edit ./circleci/osx_install_dependencies.sh # WARNING! If you do edit anything here instead, remember to invalidate the cache manually. - run: name: Install build dependencies command: .circleci/osx_install_dependencies.sh - run: name: Mark dependencies as cached command: touch ~/macos-dependencies-cached - save_cache: key: macos-dependencies-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} paths: # Homebrew is installed in /usr/local on intel macs, but in /opt/homebrew on apple silicon. - /usr/local - /opt/homebrew - /opt/boost - save_cache: key: macos-dependencies-cached-{{ arch }}-{{ checksum ".circleci/osx_install_dependencies.sh" }} paths: - ~/macos-dependencies-cached defaults: # -------------------------------------------------------------------------- # Matrix templates - bytecode_compare_env_presets: &bytecode_compare_env_presets PRESETS: legacy-optimize legacy-no-optimize via-ir-optimize via-ir-no-optimize - bytecode_compare_preset_matrix: &bytecode_compare_preset_matrix parameters: preset: # NOTE: Keep in sync with preset list in bytecode_compare_env_presets - legacy-optimize - legacy-no-optimize - via-ir-optimize - via-ir-no-optimize # -------------------------------------------------------------------------- # -------------------------------------------------------------------------- # Base Image Templates - base_archlinux: &base_archlinux docker: - image: archlinux:base environment: &base_archlinux_env TERM: xterm MAKEFLAGS: -j 3 CPUs: 3 - base_archlinux_large: &base_archlinux_large <<: *base_archlinux resource_class: large environment: &base_archlinux_large_env <<: *base_archlinux_env MAKEFLAGS: -j 5 CPUs: 5 - base_cimg_small: &base_cimg_small docker: - image: cimg/base:current resource_class: small environment: &base_cimg_small_env TERM: xterm MAKEFLAGS: -j 2 CPUs: 2 - base_ems_large: &base_ems_large docker: - image: << pipeline.parameters.emscripten-docker-image >> resource_class: large environment: &base_ems_large_env TERM: xterm MAKEFLAGS: -j 5 CPUs: 5 - base_node_small: &base_node_small docker: - image: cimg/node:current resource_class: small environment: &base_node_small_env TERM: xterm MAKEFLAGS: -j 2 CPUs: 2 - base_osx: &base_osx macos: xcode: 15.4.0 resource_class: m4pro.medium environment: &base_osx_env TERM: xterm MAKEFLAGS: -j8 CPUs: 8 - base_ubuntu_clang: &base_ubuntu_clang docker: - image: << pipeline.parameters.ubuntu-clang-ossfuzz-docker-image >> environment: &base_ubuntu_clang_env TERM: xterm MAKEFLAGS: -j 3 CPUs: 3 - base_ubuntu_clang_small: &base_ubuntu_clang_small <<: *base_ubuntu_clang resource_class: small environment: &base_ubuntu_clang_small_env <<: *base_ubuntu_clang_env MAKEFLAGS: -j 2 CPUs: 2 - base_ubuntu_clang_large: &base_ubuntu_clang_large <<: *base_ubuntu_clang resource_class: large environment: &base_ubuntu_clang_small_env <<: *base_ubuntu_clang_env MAKEFLAGS: -j 5 CPUs: 5 - base_ubuntu2004: &base_ubuntu2004 docker: - image: << pipeline.parameters.ubuntu-2004-docker-image >> environment: &base_ubuntu2004_env TERM: xterm MAKEFLAGS: -j 3 CPUs: 3 - base_ubuntu2004_small: &base_ubuntu2004_small <<: *base_ubuntu2004 resource_class: small environment: &base_ubuntu2004_small_env <<: *base_ubuntu2004_env MAKEFLAGS: -j 2 CPUs: 2 - base_ubuntu2004_xlarge: &base_ubuntu2004_xlarge <<: *base_ubuntu2004 resource_class: xlarge environment: &base_ubuntu2004_xlarge_env <<: *base_ubuntu2004_env MAKEFLAGS: -j 10 CPUs: 10 - base_ubuntu2404: &base_ubuntu2404 docker: - image: << pipeline.parameters.ubuntu-2404-docker-image >> environment: &base_ubuntu2404_env TERM: xterm MAKEFLAGS: -j 3 CPUs: 3 - base_ubuntu2404_clang: &base_ubuntu2404_clang docker: - image: << pipeline.parameters.ubuntu-2404-clang-docker-image >> environment: &base_ubuntu2404_clang_env TERM: xterm CC: clang CXX: clang++ MAKEFLAGS: -j 3 CPUs: 3 - base_ubuntu2404_clang_large: &base_ubuntu2404_clang_large <<: *base_ubuntu2404_clang resource_class: large environment: &base_ubuntu2404_clang_large_env <<: *base_ubuntu2404_clang_env MAKEFLAGS: -j 5 CPUs: 5 - base_ubuntu2404_small: &base_ubuntu2404_small <<: *base_ubuntu2404 resource_class: small environment: &base_ubuntu2404_small_env <<: *base_ubuntu2404_env MAKEFLAGS: -j 2 CPUs: 2 - base_ubuntu2404_large: &base_ubuntu2404_large <<: *base_ubuntu2404 resource_class: large environment: &base_ubuntu2404_large_env <<: *base_ubuntu2404_env MAKEFLAGS: -j 5 CPUs: 5 - base_ubuntu2404_arm_medium: &base_ubuntu2404_arm_medium docker: - image: << pipeline.parameters.ubuntu-2404-arm-docker-image >> resource_class: arm.medium environment: &base_ubuntu2404_arm_medium_env TERM: xterm MAKEFLAGS: -j 2 CPUs: 2 - base_ubuntu2404_arm_large: &base_ubuntu2404_arm_large docker: - image: << pipeline.parameters.ubuntu-2404-arm-docker-image >> resource_class: arm.large environment: &base_ubuntu2404_arm_large_env TERM: xterm MAKEFLAGS: -j 7 CPUs: 7 - base_ubuntu2404_xlarge: &base_ubuntu2404_xlarge <<: *base_ubuntu2404 resource_class: xlarge environment: &base_ubuntu2404_xlarge_env <<: *base_ubuntu2404_env MAKEFLAGS: -j 10 CPUs: 10 - base_win: &base_win executor: name: win/default shell: bash.exe - base_win_large: &base_win_large executor: name: win/default size: large shell: bash.exe # -------------------------------------------------------------------------- # Workflow Templates - on_all_tags_and_branches: &on_all_tags_and_branches filters: tags: only: /.*/ - on_version_tags: &on_version_tags filters: tags: only: /^v.*/ branches: ignore: /.*/ - on_develop: &on_develop filters: branches: only: - develop - requires_nothing: &requires_nothing <<: *on_all_tags_and_branches - requires_b_ubu: &requires_b_ubu <<: *on_all_tags_and_branches requires: - b_ubu - requires_b_ubu_clang: &requires_b_ubu_clang <<: *on_all_tags_and_branches requires: - b_ubu_clang - requires_b_ubu_force_release: &requires_b_ubu_force_release <<: *on_all_tags_and_branches requires: - b_ubu_force_release - requires_b_ubu_static: &requires_b_ubu_static <<: *on_all_tags_and_branches requires: - b_ubu_static - requires_b_ubu_static_arm: &requires_b_ubu_static_arm <<: *on_all_tags_and_branches requires: - b_ubu_static_arm - requires_b_archlinux: &requires_b_archlinux <<: *on_all_tags_and_branches requires: - b_archlinux - requires_b_osx: &requires_b_osx <<: *on_all_tags_and_branches requires: - b_osx - requires_b_ubu_asan: &requires_b_ubu_asan <<: *on_all_tags_and_branches requires: - b_ubu_asan - requires_b_ubu_asan_clang: &requires_b_ubu_asan_clang <<: *on_all_tags_and_branches requires: - b_ubu_asan_clang - requires_b_ubu_ubsan_clang: &requires_b_ubu_ubsan_clang <<: *on_all_tags_and_branches requires: - b_ubu_ubsan_clang - requires_b_ems: &requires_b_ems <<: *on_all_tags_and_branches requires: - b_ems - requires_b_ubu_ossfuzz: &requires_b_ubu_ossfuzz <<: *on_all_tags_and_branches requires: - b_ubu_ossfuzz - requires_b_win: &requires_b_win <<: *on_all_tags_and_branches requires: - b_win # -------------------------------------------------------------------------- # Parameterized Job Templates # Separate compile-only runs of those external tests where a full run takes much longer. # Also see https://github.com/argotorg/solidity/pull/14234 for why we excluded those # external tests from the nightly jobs. - job_ems_compile_ext_colony: &job_ems_compile_ext_colony <<: *requires_b_ems name: t_ems_compile_ext_colony project: colony binary_type: solcjs compile_only: 1 image: cimg/node:14.20 python2: true - job_native_compile_ext_gnosis: &job_native_compile_ext_gnosis <<: *requires_b_ubu_static name: t_native_compile_ext_gnosis project: gnosis binary_type: native # NOTE: We are disabling the gnosis test suite due to version discrepancies that are difficult to fix. # Check again after (and if) https://github.com/safe-global/safe-contracts/pull/644 is merged. compile_only: 1 image: cimg/node:18.16 - job_native_test_ext_zeppelin: &job_native_test_ext_zeppelin <<: *requires_b_ubu_static name: t_native_test_ext_zeppelin project: zeppelin binary_type: native image: cimg/node:lts resource_class: large - job_native_test_ext_ens: &job_native_test_ext_ens <<: *requires_b_ubu_static name: t_native_test_ext_ens project: ens binary_type: native image: cimg/node:lts - job_native_compile_ext_trident: &job_native_compile_ext_trident <<: *requires_b_ubu_static name: t_native_compile_ext_trident project: trident binary_type: native # NOTE: test suite disabled due to dependence on a specific version of Hardhat # which does not support shanghai EVM. compile_only: 1 image: cimg/node:18.16 - job_native_compile_ext_euler: &job_native_compile_ext_euler <<: *requires_b_ubu_static name: t_native_compile_ext_euler project: euler binary_type: native resource_class: medium - job_native_test_ext_yield_liquidator: &job_native_test_ext_yield_liquidator <<: *requires_b_ubu_static name: t_native_test_ext_yield_liquidator project: yield-liquidator binary_type: native image: cimg/node:18.16 - job_native_compile_ext_bleeps: &job_native_compile_ext_bleeps <<: *requires_b_ubu_static name: t_native_compile_ext_bleeps project: bleeps binary_type: native # NOTE: test suite disabled due to dependence on a specific version of Hardhat # which does not support shanghai EVM. compile_only: 1 resource_class: medium - job_native_compile_ext_pool_together: &job_native_compile_ext_pool_together <<: *requires_b_ubu_static name: t_native_compile_ext_pool_together project: pool-together binary_type: native # NOTE: test suite disabled due to dependence on a specific version of Hardhat # which does not support shanghai EVM. compile_only: 1 image: cimg/node:lts - job_native_test_ext_uniswap: &job_native_test_ext_uniswap <<: *requires_b_ubu_static name: t_native_test_ext_uniswap project: uniswap binary_type: native image: cimg/node:lts resource_class: large # Tests run out of memory on a smaller machine - job_native_test_ext_prb_math: &job_native_test_ext_prb_math <<: *requires_b_ubu_static name: t_native_test_ext_prb_math project: prb-math binary_type: native image: cimg/rust:1.74.0-node resource_class: large # Tests run out of memory on a smaller machine - job_native_test_ext_elementfi: &job_native_test_ext_elementfi <<: *requires_b_ubu_static name: t_native_test_ext_elementfi project: elementfi binary_type: native image: cimg/node:lts resource_class: medium - job_native_test_ext_brink: &job_native_test_ext_brink <<: *requires_b_ubu_static name: t_native_test_ext_brink project: brink binary_type: native image: cimg/node:lts - job_native_compile_ext_chainlink: &job_native_compile_ext_chainlink <<: *requires_b_ubu_static name: t_native_compile_ext_chainlink project: chainlink binary_type: native # NOTE: test suite disabled due to dependence on a specific version of Hardhat # which does not support shanghai EVM. compile_only: 1 image: cimg/node:16.20 resource_class: large # Tests run out of memory on a smaller machine - job_native_compile_ext_gp2: &job_native_compile_ext_gp2 <<: *requires_b_ubu_static name: t_native_compile_ext_gp2 project: gp2 binary_type: native # NOTE: test suite disabled due to constant failures. compile_only: 1 image: cimg/node:lts - job_b_ubu_asan_clang: &job_b_ubu_asan_clang <<: *on_all_tags_and_branches name: b_ubu_asan_clang cmake_options: -DSANITIZE=address - job_b_ubu_ubsan_clang: &job_b_ubu_ubsan_clang <<: *on_all_tags_and_branches name: b_ubu_ubsan_clang cmake_options: -DSANITIZE=undefined # ----------------------------------------------------------------------------------------------- jobs: chk_spelling: <<: *base_ubuntu2404_small steps: - checkout - attach_workspace: at: build - run: name: Install dependencies command: | pip install --user codespell - run: name: Check spelling command: ~/.local/bin/codespell - matrix_notify_failure_unless_pr chk_docs_examples: <<: *base_node_small steps: - checkout - attach_workspace: at: build - run: name: JS deps command: sudo npm install -g solhint - run: name: Test Docs examples command: test/docsCodeStyle.sh - matrix_notify_failure_unless_pr chk_coding_style: <<: *base_cimg_small steps: - checkout - run: name: Install shellcheck command: | sudo apt -q update sudo apt install -y shellcheck - run: name: Check for C++ coding style command: scripts/check_style.sh - run: name: checking shell scripts command: scripts/chk_shellscripts/chk_shellscripts.sh - run: name: Check for broken symlinks command: scripts/check_symlinks.sh - matrix_notify_failure_unless_pr chk_errorcodes: <<: *base_ubuntu2404_small steps: - checkout - run: name: Check for error codes command: scripts/error_codes.py --check - matrix_notify_failure_unless_pr chk_pylint: <<: *base_ubuntu2404_small steps: - install_python3: packages: pyyaml jsonschema pytest - checkout - run: pylint --version - run: name: Linting Python Scripts command: scripts/pylint_all.py - matrix_notify_failure_unless_pr chk_antlr_grammar: <<: *base_cimg_small steps: - checkout - run: name: Install Java command: | sudo apt -q update sudo apt install -y openjdk-17-jdk - run: name: Run tests command: scripts/test_antlr_grammar.sh - matrix_notify_failure_unless_pr chk_buglist: <<: *base_node_small steps: - checkout - run: name: JS deps command: | npm install download npm install JSONPath npm install mktemp - run: name: Test buglist command: test/buglistTests.js - matrix_notify_failure_unless_pr chk_proofs: <<: *base_ubuntu2404_small steps: - checkout - run_proofs - matrix_notify_failure_unless_pr chk_docs_pragma_min_version: <<: *base_ubuntu2404_small steps: - checkout - run_docs_pragma_min_version - matrix_notify_failure_unless_pr t_ubu_pyscripts: <<: *base_ubuntu2404_small steps: - checkout - run: name: Python unit tests command: python3 test/pyscriptTests.py - run: name: Smoke test for gas_diff_stats.py command: scripts/gas_diff_stats.py - matrix_notify_failure_unless_pr t_win_pyscripts: <<: *base_win steps: - run: git config --global core.autocrlf false - checkout - run: name: Install dependencies command: python -m pip install --user requests parsec tabulate - run: name: Python unit tests command: python.exe test/pyscriptTests.py - matrix_notify_failure_unless_pr b_ubu: &b_ubu # this runs 2x faster on xlarge but takes 4x more resources (compared to medium). # Enough other jobs depend on it that it's worth it though. <<: *base_ubuntu2404_xlarge steps: - build - run: cat prerelease.txt # x64 ASAN build, for testing for memory related bugs b_ubu_asan: &b_ubu_asan # Runs slightly faster on large and xlarge but we only run it nightly so efficiency matters more. <<: *base_ubuntu2404 environment: <<: *base_ubuntu2404_env # NOTE: Sanitizers may alter the intermediate code, potentially causing false warnings. # As a result, treating warnings as errors in instrumented builds can lead to build failures due to these false positives. # Therefore, we disable pedantic builds in such cases. # See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105562#c27 CMAKE_OPTIONS: -DSANITIZE=address -DPEDANTIC=OFF CMAKE_BUILD_TYPE: Release # Set the number of jobs to two instead of the default three, so that we do not run out of memory MAKEFLAGS: -j 2 steps: - build b_ubu_clang: &b_ubu_clang <<: *base_ubuntu2404_clang_large environment: <<: *base_ubuntu2404_clang_large_env MAKEFLAGS: -j 10 steps: - build b_ubu_san_clang: # This runs a bit faster on large and xlarge but on nightly efficiency matters more. parameters: cmake_options: type: string <<: *base_ubuntu2404_clang environment: <<: *base_ubuntu2404_clang_env # NOTE: Disabled pedantic builds to avoid false positives, see b_ubu_asan for a more detailed explanation. CMAKE_OPTIONS: -DPEDANTIC=OFF << parameters.cmake_options >> steps: - build b_ubu_force_release: &b_ubu_force_release <<: *b_ubu environment: <<: *base_ubuntu2404_xlarge_env FORCE_RELEASE: ON b_ubu_static: # We temporarily keep building static release binaries on ubuntu 20.04 # to avoid glibc incompatibilities. # See: https://github.com/argotorg/solidity/issues/13954 # On large runs 2x faster than on medium. 3x on xlarge. <<: *base_ubuntu2404_xlarge environment: <<: *base_ubuntu2404_xlarge_env CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_LINK_STATIC=ON steps: - checkout - run_build - run: name: strip binary command: strip build/solc/solc - store_artifacts: path: build/solc/solc destination: solc-static-linux - run: mv build/solc/solc build/solc/solc-static-linux - persist_to_workspace: root: build paths: - solc/solc-static-linux - matrix_notify_failure_unless_pr b_ubu_static_arm: &b_ubu_static_arm <<: *base_ubuntu2404_arm_large environment: <<: *base_ubuntu2404_arm_large_env CMAKE_OPTIONS: -DCMAKE_BUILD_TYPE=Release -DSOLC_LINK_STATIC=ON steps: - checkout - run_build - run: name: strip binary command: strip build/solc/solc - store_artifacts: path: build/solc/solc destination: solc-static-linux-arm - run: mv build/solc/solc build/solc/solc-static-linux-arm - run: mv build/test/soltest build/test/soltest-linux-arm - run: mv build/test/tools/solfuzzer build/test/tools/solfuzzer-linux-arm - persist_executables_to_workspace_arm - matrix_notify_failure_unless_pr b_ubu_min_req: <<: *base_ubuntu2404_large steps: - checkout - install_and_check_minimum_requirements: compiler: gcc - run_build - store_artifacts_solc - persist_executables_to_workspace - matrix_notify_failure_unless_pr - build b_ubu_min_req_clang: <<: *base_ubuntu2404_clang_large environment: <<: *base_ubuntu2404_clang_large_env MAKEFLAGS: -j 10 steps: - checkout - install_and_check_minimum_requirements: compiler: clang - run_build - matrix_notify_failure_unless_pr t_ubu_min_req_soltest: <<: *base_ubuntu2404_large parallelism: 20 environment: <<: *base_ubuntu2404_large_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 steps: - soltest b_ubu_ossfuzz: &b_ubu_ossfuzz <<: *base_ubuntu_clang_large steps: - checkout - setup_prerelease - run_build_ossfuzz - persist_ossfuzz_executables_to_workspace - matrix_notify_failure_unless_pr t_ubu_ossfuzz: &t_ubu_ossfuzz <<: *base_ubuntu_clang_small steps: - checkout - attach_workspace: at: build - run: name: Regression tests command: | git clone https://github.com/argotorg/solidity-fuzzing-corpus /tmp/solidity-fuzzing-corpus mkdir -p test_results scripts/regressions.py -o test_results - store_test_results: path: test_results/ - store_artifacts_test_results b_archlinux: <<: *base_archlinux_large environment: <<: *base_archlinux_large_env steps: - run: name: Install build dependencies command: | pacman --noconfirm -Syu --noprogressbar --needed base-devel boost cmake ccache git openssh tar - checkout - run_build - store_artifacts_solc - persist_executables_to_workspace - matrix_notify_failure_unless_pr b_osx: <<: *base_osx environment: <<: *base_osx_env CMAKE_BUILD_TYPE: Release # boost root configured to the prefix used in `osx_install_dependencies.sh` CMAKE_OPTIONS: -DCMAKE_OSX_ARCHITECTURES:STRING=x86_64;arm64 -DBoost_ROOT=/opt/boost steps: - checkout - install_dependencies_osx - run_build - store_artifacts_solc - store_artifacts_yul_phaser - persist_executables_to_workspace_osx - matrix_notify_failure_unless_pr t_osx_soltest: &t_osx_soltest <<: *base_osx environment: <<: *base_osx_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 steps: - checkout - install_dependencies_osx - attach_workspace: at: . - run_soltest - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr t_osx_cli: <<: *base_osx parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py steps: - checkout - install_dependencies_osx - attach_workspace: at: . - run_cmdline_tests - store_artifacts_test_results - matrix_notify_failure_unless_pr b_ems: <<: *base_ems_large environment: <<: *base_ems_large_env MAKEFLAGS: -j 10 steps: - checkout - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: Build command: scripts/ci/build_emscripten.sh - save_ccache_if_develop - store_artifacts: path: upload/soljson.js destination: soljson.js - run: mkdir -p workspace - run: cp upload/soljson.js workspace/soljson.js - run: scripts/get_version.sh > workspace/version.txt - persist_to_workspace: root: workspace paths: - soljson.js - version.txt - matrix_notify_failure_unless_pr b_docs: <<: *base_ubuntu2404_small steps: - checkout - setup_prerelease - run: name: Install build system dependencies command: | apt-get update apt-get install --quiet=2 --no-install-recommends python3-dev libcairo2-dev pkg-config - run: name: Build documentation command: docs/docs.sh - store_artifacts: path: docs/_build/html/ destination: docs-html - matrix_notify_failure_unless_pr t_ubu_soltest: &t_ubu_soltest <<: *base_ubuntu2404_large parallelism: 20 environment: <<: *base_ubuntu2404_large_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 steps: - soltest t_ubu_arm_soltest: &t_ubu_arm_soltest <<: *base_ubuntu2404_arm_medium parallelism: 20 environment: <<: *base_ubuntu2404_arm_medium_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 steps: - checkout - attach_workspace: at: build - run: name: Create symbolic link with expected soltest binary name command: | ln --symbolic --relative build/test/soltest-linux-arm build/test/soltest - run_soltest - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr t_ubu_soltest_low_priority_evm_versions: &t_ubu_soltest_low_priority_evm_versions <<: *base_ubuntu2404_large parallelism: 50 steps: - checkout - attach_workspace: at: build - run_soltest_all: # We test most EVM versions on every PR. The ones below are the exceptions. # # We do not test these at all. We were never doing that and no point starting now since # they are deprecated anyway: # - tangerineWhistle # - spuriousDragon # # These have a low chance of breaking so we only run them in nightly to save credits: # - byzantium: deprecated, if it breaks, homestead likely will as well # - petersburg: no changes compared to constantinople # - prague: no changes compared to cancun evm_versions: byzantium petersburg prague - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr t_ubu_lsp: &t_ubu_lsp <<: *base_ubuntu2404_small steps: - test_lsp t_archlinux_soltest: &t_archlinux_soltest <<: *base_archlinux parallelism: 20 environment: <<: *base_archlinux_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 # For Archlinux we do not have prebuilt docker images and we would need to build evmone from source, # thus we forgo semantics tests to speed things up. SOLTEST_FLAGS: --no-semantic-tests --no-smt steps: - run: name: Install runtime dependencies command: | pacman --noconfirm -Syu --noprogressbar --needed z3 git - soltest t_ubu_clang_soltest: &t_ubu_clang_soltest <<: *base_ubuntu2404_clang parallelism: 20 environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 # The high parallelism in this job is causing the SMT tests to run out of memory, # so disabling for now. SOLTEST_FLAGS: --no-smt steps: - soltest t_ubu_force_release_soltest_all: &t_ubu_force_release_soltest_all <<: *base_ubuntu2404_large parallelism: 50 steps: - soltest_all t_ubu_cli: &t_ubu_cli <<: *base_ubuntu2404_small parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py steps: - cmdline_tests t_ubu_arm_cli: &t_ubu_arm_cli <<: *base_ubuntu2404_arm_medium parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py steps: - checkout - attach_workspace: at: build - run: name: Create symbolic link with expected solc and solfuzzer binaries name command: | ln --symbolic --relative build/solc/solc-static-linux-arm build/solc/solc ln --symbolic --relative build/test/tools/solfuzzer-linux-arm build/test/tools/solfuzzer - run_cmdline_tests - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr t_ubu_force_release_cli: &t_ubu_force_release_cli <<: *t_ubu_cli t_ubu_locale: <<: *base_ubuntu2404_small steps: - checkout - attach_workspace: at: build - run: test/localeTest.sh build/solc/solc - matrix_notify_failure_unless_pr t_ubu_asan_cli: # Runs slightly faster on medium but we only run it nightly so efficiency matters more. <<: *base_ubuntu2404 parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py environment: <<: *base_ubuntu2404_env ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. # See: https://github.com/argotorg/solidity/issues/13891 for details. LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp:print_suppressions=0 steps: - cmdline_tests t_ubu_asan_soltest: <<: *base_ubuntu2404 parallelism: 20 environment: <<: *base_ubuntu2404_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 # Suppress CLN memory leak. # See: https://github.com/argotorg/solidity/issues/13891 for details. LSAN_OPTIONS: suppressions=/root/project/.circleci/cln-asan.supp steps: - soltest t_ubu_asan_clang_soltest: <<: *base_ubuntu2404_clang parallelism: 20 environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 OPTIMIZE: 0 SOLTEST_FLAGS: --no-smt ASAN_OPTIONS: check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true:strict_string_checks=true:detect_invalid_pointer_pairs=2 steps: - soltest t_ubu_ubsan_clang_soltest: <<: *base_ubuntu2404_clang parallelism: 20 environment: <<: *base_ubuntu2404_clang_env EVM: << pipeline.parameters.evm-version >> EOF_VERSION: 0 SOLTEST_FLAGS: --no-smt steps: - soltest t_ubu_ubsan_clang_cli: <<: *base_ubuntu2404_clang parallelism: 8 # Should match number of tests in .circleci/parallel_cli_tests.py steps: - cmdline_tests t_ems_solcjs: # Unlike other t_ems jobs this one actually runs 2x faster on medium (compared to small). <<: *base_ubuntu2404 steps: - checkout - attach_workspace: at: /tmp/workspace - run: name: Install test dependencies command: | apt-get update apt-get install -qqy --no-install-recommends nodejs npm - run: name: Test solcjs no_output_timeout: 30m command: | node --version npm --version test/externalTests/solc-js/solc-js.sh /tmp/workspace/soljson.js $(cat /tmp/workspace/version.txt) - matrix_notify_failure_unless_pr t_ems_ext_edr: # Runs out of memory on the small instance <<: *base_ubuntu2404 docker: - image: cimg/rust:1.79.0-node environment: <<: *base_ubuntu2404_env EDR_TESTS_SOLC_PATH: /tmp/workspace/soljson.js steps: - checkout - attach_workspace: at: /tmp/workspace - run: name: Ensure pnpm is installed if npm is present command: sudo npm install -g pnpm - run: name: Retrieve EDR latest release tag command: | # Make authenticated requests when the Github token is available if [[ -n "$GITHUB_READ_TOKEN" ]]; then EXTRA_HEADERS=(--header "Authorization: Bearer ${GITHUB_READ_TOKEN}") fi EDR_LATEST_RELEASE_TAG=$( curl \ --silent \ --location \ --fail \ --show-error \ "${EXTRA_HEADERS[@]}" \ https://api.github.com/repos/nomicfoundation/edr/releases/latest \ | jq --raw-output .tag_name \ ) echo "export EDR_LATEST_RELEASE_TAG='${EDR_LATEST_RELEASE_TAG}'" >> "$BASH_ENV" - run: git clone --depth 1 https://github.com/nomicfoundation/edr.git --branch "$EDR_LATEST_RELEASE_TAG" - run: name: Install dependencies command: | cd edr pnpm install --no-frozen-lockfile - run: name: Run hardhat-tests in EDR repo command: | EDR_TESTS_SOLC_VERSION=$(scripts/get_version.sh) export EDR_TESTS_SOLC_VERSION cd edr/hardhat-tests pnpm test - matrix_notify_failure_unless_pr t_ext: parameters: project: type: string binary_type: type: enum enum: - solcjs - native compile_only: type: integer default: 0 image: type: string default: cimg/node:current resource_class: type: string default: small python2: type: boolean default: false docker: - image: << parameters.image >> resource_class: << parameters.resource_class >> # NOTE: Each external test runs up to 6 independent settings presets. If parallelism is higher than # actual preset count, some runs will exit immediately. If it's lower, some runs will get more than one preset. parallelism: 6 environment: TERM: xterm COMPILE_ONLY: << parameters.compile_only >> steps: - checkout - attach_workspace: at: /tmp/workspace - install_foundry - run: name: Ensure pnpm is installed if npm is present command: | if command -v npm &> /dev/null; then sudo npm install -g pnpm fi - when: condition: << parameters.python2 >> steps: - run: name: Install Python 2 and make it the default command: | sudo apt update # python is used by node-gyp to build native modules (needed for Colony). # In the 14.x image node-gyp still requires Python 2. sudo apt install python2 --assume-yes --no-install-recommends sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 1 - when: condition: equal: [<< parameters.binary_type >>, "solcjs"] steps: - run: name: External << parameters.project >> tests (<< parameters.binary_type >>) command: | test/external_tests.py test --solc-binary-type "<< parameters.binary_type >>" --solc-binary-path /tmp/workspace/soljson.js --run "<< parameters.project >>" - when: condition: equal: [<< parameters.binary_type >>, "native"] steps: - run: name: External << parameters.project >> tests (<< parameters.binary_type >>) command: | test/external_tests.py test --solc-binary-type "<< parameters.binary_type >>" --solc-binary-path /tmp/workspace/solc/solc-static-linux --run "<< parameters.project >>" - store_artifacts: path: reports/externalTests/ # persist_to_workspace fails if the directory does not exist and the test script will create # it only if it actually has benchmark results. - run: mkdir -p reports/externalTests/ - persist_to_workspace: root: . paths: - reports/externalTests/ - matrix_notify_failure_unless_pr t_ethdebug_output_validity: <<: *base_node_small steps: - checkout - attach_workspace: at: /tmp/workspace - install_python3: packages: pyyaml jsonschema pytest - run: name: Ethdebug validity tests command: | pytest test/ethdebugSchemaTests --solc-binary-path=/tmp/workspace/solc/solc-static-linux -v c_ext_benchmarks: <<: *base_node_small steps: - install_python3: packages: requests - checkout - attach_workspace: at: . - run: name: Combine benchmark reports command: cat reports/externalTests/benchmark-*.json | scripts/externalTests/merge_benchmarks.sh > reports/externalTests/all-benchmarks.json - run: name: Summarize reports command: cat reports/externalTests/all-benchmarks.json | scripts/externalTests/summarize_benchmarks.sh > reports/externalTests/summarized-benchmarks.json - store_artifacts: path: reports/externalTests/all-benchmarks.json - store_artifacts: path: reports/externalTests/summarized-benchmarks.json - run: name: Check CircleCI token presence; Skip remaining steps if the token is not present. command: | # NOTE: download_benchmarks.py requires CIRCLECI_TOKEN environment variable to be set to # a valid CircleCI API token to download the benchmark artifacts. if [[ -z "$CIRCLECI_TOKEN" ]]; then echo "Skipping download benchmarks..." circleci-agent step halt fi - run: name: Download reports from base branch command: | if [[ $CIRCLE_PULL_REQUEST != "" ]]; then mkdir reports/externalTests/base-branch/ cd reports/externalTests/base-branch/ pr_id=$(echo "$CIRCLE_PULL_REQUEST" | sed 's|\(.*\)\/||') scripts_dir=../../../scripts # Our main goal here is to provide new benchmarks, the diff is optional. When benchmarks from # the previous run are not available for whatever reason, we still succeed and just skip the diff. # download_benchmarks.py exits with status 2 in that case. if "${scripts_dir}/externalTests/download_benchmarks.py" --base-of-pr "$pr_id" || [[ $? == 2 ]]; then echo 'export SKIP_BENCHMARK_DIFF=true' >> $BASH_ENV fi fi - run: name: Diff benchmarks command: | if [[ $CIRCLE_PULL_REQUEST != "" && $SKIP_BENCHMARK_DIFF != "true" ]]; then cd reports/externalTests/ mkdir diff/ scripts_dir=../../scripts "${scripts_dir}/externalTests/benchmark_diff.py" table \ --output-format markdown \ --style humanized \ base-branch/summarized-benchmarks-*.json \ summarized-benchmarks.json > diff/benchmark-diff-summarized-table-markdown-humanized.md "${scripts_dir}/externalTests/benchmark_diff.py" table \ --output-format markdown \ --style absolute \ base-branch/summarized-benchmarks-*.json \ summarized-benchmarks.json > diff/benchmark-diff-summarized-table-markdown-absolute.md "${scripts_dir}/externalTests/benchmark_diff.py" inplace \ --style absolute \ base-branch/summarized-benchmarks-*.json \ summarized-benchmarks.json > diff/benchmark-diff-summarized-inplace-absolute.md "${scripts_dir}/externalTests/benchmark_diff.py" inplace \ --style absolute \ base-branch/all-benchmarks-*.json \ all-benchmarks.json > diff/benchmark-diff-all-table-inplace-absolute.md fi - store_artifacts: path: reports/externalTests/diff/ - store_artifacts: path: reports/externalTests/base-branch/ b_win: &b_win <<: *base_win_large steps: # NOTE: Not disabling git's core.autocrlf here because we want to build using the typical Windows config. - checkout - restore_cache: keys: - dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} # DO NOT EDIT between here and save_cache, but rather edit .\scripts\install_deps.ps1 # WARNING! If you do edit anything here instead, remember to invalidate the cache manually. - run: name: "Installing dependencies" command: .\scripts\install_deps.ps1 shell: powershell.exe - save_cache: key: dependencies-win-{{ arch }}-{{ checksum "scripts/install_deps.ps1" }} paths: - .\deps - restore_ccache_if_allowed # WARNING! If you edit anything between here and save_cache, remember to invalidate the cache manually by bumping the version - run_with_ccache_unless_tag: step_name: "Building solidity" command: scripts/ci/build_win.sh - save_ccache_if_develop - run: name: "Run solc.exe to make sure build was successful." command: .\build\solc\Release\solc.exe --version shell: powershell.exe - store_artifacts: path: upload/ - persist_to_workspace: root: build paths: - .\solc\*\solc.exe - .\test\*\soltest.exe - matrix_notify_failure_unless_pr t_win_soltest: &t_win_soltest <<: *base_win steps: # NOTE: Git's default core.autocrlf is fine for running soltest. We get additional coverage # for files using CRLF that way. - checkout - attach_workspace: at: build - run: name: "Install evmone" command: scripts/install_evmone.ps1 shell: powershell.exe - run: name: "Run soltest" command: .circleci/soltest.ps1 shell: powershell.exe - run: name: Install LSP test dependencies command: python -m pip install --user numpy deepdiff colorama - run: name: Executing solc LSP test suite command: python test/lsp.py build\solc\Release\solc.exe --non-interactive shell: powershell.exe - store_test_results: path: test_results/ - store_artifacts_test_results - matrix_notify_failure_unless_pr # Note: b_bytecode_ubu_static is required because b_ubu_static and b_ubu # are currently built on different Ubuntu base images. # It can be safely removed once we move both to the same Ubuntu version. b_bytecode_ubu_static: parameters: preset: type: string <<: *base_ubuntu2004_small parallelism: 2 # For prepare_bytecode_report steps: - checkout - attach_workspace: at: build - prepare_bytecode_report: label: "ubuntu2004-static" binary_type: native binary_path: "build/solc/solc-static-linux" preset: "<< parameters.preset >>" b_bytecode_ubu: parameters: preset: type: string <<: *base_ubuntu2404_small parallelism: 2 # For prepare_bytecode_report steps: - checkout - attach_workspace: at: build - prepare_bytecode_report: label: "ubuntu" binary_type: native binary_path: "build/solc/solc" preset: "<< parameters.preset >>" b_bytecode_osx: parameters: preset: type: string <<: *base_osx parallelism: 2 # For prepare_bytecode_report steps: - checkout - attach_workspace: at: . - prepare_bytecode_report: label: "osx" binary_type: native binary_path: "build/solc/solc" preset: "<< parameters.preset >>" b_bytecode_osx_intel: parameters: preset: type: string <<: *base_osx parallelism: 2 # For prepare_bytecode_report steps: - checkout - attach_workspace: at: . - prepare_bytecode_report: label: "osx_intel" binary_type: osx_intel binary_path: "build/solc/solc" preset: "<< parameters.preset >>" b_bytecode_win: parameters: preset: type: string <<: *base_win parallelism: 2 # For prepare_bytecode_report steps: # NOTE: For bytecode generation we need the input files to be byte-for-byte identical on all # platforms so line ending conversions must absolutely be disabled. - run: git config --global core.autocrlf false - checkout - run: name: Force install python3.12 command: choco install python312 --pre --force - run: name: Create a symlink for python3 command: ln -s /c/ProgramData/chocolatey/bin/python3.12 /c/ProgramData/chocolatey/bin/python3 - attach_workspace: at: build - prepare_bytecode_report: label: "windows" binary_type: native binary_path: "build/solc/Release/solc.exe" preset: "<< parameters.preset >>" b_bytecode_ubu_arm: parameters: preset: type: string <<: *base_ubuntu2404_arm_medium parallelism: 2 # For prepare_bytecode_report steps: - checkout - attach_workspace: at: build - prepare_bytecode_report: label: "ubuntu_arm" binary_type: native binary_path: "build/solc/solc-static-linux-arm" preset: "<< parameters.preset >>" b_bytecode_ems: parameters: preset: type: string <<: *base_node_small steps: - checkout - attach_workspace: at: emscripten_build/libsolc - prepare_bytecode_report: label: "emscripten" binary_type: solcjs binary_path: "emscripten_build/libsolc/soljson.js" preset: "<< parameters.preset >>" t_bytecode_compare: <<: *base_ubuntu2404_small environment: <<: *base_ubuntu2404_small_env <<: *bytecode_compare_env_presets steps: - checkout - attach_workspace: at: . - run: .circleci/compare_bytecode_reports.sh $PRESETS - store_artifacts: # NOTE: store_artifacts does not support the 'when' attribute. # Fortunately when the artifact does not exist it just says "No artifact files found" and ignores it. path: bytecode-reports-*.zip - matrix_notify_failure_unless_pr c_release_binaries: <<: *base_ubuntu2404 steps: - checkout - attach_workspace: at: workspace - run: name: Gather and rename binaries from dependent jobs command: | mkdir github/ cp workspace/solc/solc-static-linux github/solc-static-linux cp workspace/solc/solc-static-linux-arm github/solc-static-linux-arm cp workspace/build/solc/solc github/solc-macos cp workspace/solc/Release/solc.exe github/solc-windows.exe cp workspace/soljson.js github/soljson.js cd github/ tar --create --file ../github-binaries.tar * - store_artifacts: path: github-binaries.tar - run: name: Rename binaries to solc-bin naming convention command: | full_version=$( github/solc-static-linux --version | sed -En 's/^Version: ([0-9.]+.*\+commit\.[0-9a-f]+(\.mod)?).*$/\1/p' ) mkdir -p solc-bin/{linux-amd64,linux-arm64,macosx-amd64,windows-amd64,bin} mv github/solc-static-linux-arm "solc-bin/linux-arm64/solc-linux-arm64-v${full_version}" mv github/solc-static-linux "solc-bin/linux-amd64/solc-linux-amd64-v${full_version}" mv github/solc-macos "solc-bin/macosx-amd64/solc-macosx-amd64-v${full_version}" mv github/solc-windows.exe "solc-bin/windows-amd64/solc-windows-amd64-v${full_version}.exe" mv github/soljson.js "solc-bin/bin/soljson-v${full_version}.js" cd solc-bin/ tar --create --file ../solc-bin-binaries.tar * - store_artifacts: path: solc-bin-binaries.tar - matrix_notify_failure_unless_pr - matrix_notify_release_unless_pr c_source_tarball: <<: *base_ubuntu2404_small steps: - checkout - setup_prerelease - run: scripts/create_source_tarball.sh - store_artifacts: path: upload/ - matrix_notify_failure_unless_pr - matrix_notify_release_unless_pr b_alpine_docker: <<: *base_cimg_small steps: - setup_remote_docker: # Always build from scratch to use current packages. # This job is only meant to run nightly so build time is not an issue. docker_layer_caching: false - checkout - run: name: Disable partial clone and fetch all objects command: | git config remote.origin.promisor false git config --unset remote.origin.partialclonefilter git fetch --refetch origin - run: name: Build and tag the container command: scripts/docker_deploy_manual.sh develop "file://$PWD" --no-push - run: name: Smoke test command: docker run --pull=never ghcr.io/argotorg/solc:build-alpine --version - matrix_notify_failure_unless_pr workflows: version: 2 main: jobs: # basic checks - chk_spelling: *requires_nothing - chk_coding_style: *requires_nothing # DISABLED FOR 0.6.0 - chk_docs_examples: *requires_nothing - chk_buglist: *requires_nothing - chk_proofs: *requires_nothing - chk_pylint: *requires_nothing - chk_errorcodes: *requires_nothing - chk_antlr_grammar: *requires_nothing - chk_docs_pragma_min_version: *requires_nothing - t_ubu_pyscripts: *requires_nothing - t_win_pyscripts: *requires_nothing # build-only - b_docs: *requires_nothing - b_ubu_ossfuzz: *requires_nothing # build and test with minimum supported versions of dependencies - b_ubu_min_req_clang: *requires_nothing - b_ubu_min_req: *requires_nothing - t_ubu_min_req_soltest: <<: *on_all_tags_and_branches requires: - b_ubu_min_req # OS/X build and tests - b_osx: *requires_nothing - t_osx_cli: *requires_b_osx - t_osx_soltest: *requires_b_osx # ArchLinux build and tests - b_archlinux: *requires_nothing - t_archlinux_soltest: *requires_b_archlinux # Static build - b_ubu_static: *requires_nothing - b_ubu_static_arm: *requires_nothing # Ubuntu build and tests - b_ubu: *requires_nothing - t_ubu_cli: *requires_b_ubu - t_ubu_arm_cli: *requires_b_ubu_static_arm - t_ubu_locale: *requires_b_ubu - t_ubu_soltest: *requires_b_ubu - t_ubu_arm_soltest: *requires_b_ubu_static_arm - b_ubu_clang: *requires_nothing - t_ubu_clang_soltest: *requires_b_ubu_clang - t_ubu_lsp: *requires_b_ubu # Ubuntu fake release build and tests - b_ubu_force_release: *requires_nothing - t_ubu_force_release_cli: *requires_b_ubu_force_release - t_ubu_force_release_soltest_all: *requires_b_ubu_force_release # Emscripten build and tests that take 15 minutes or less - b_ems: *requires_nothing - t_ems_solcjs: *requires_b_ems - t_ems_ext_edr: *requires_b_ems - t_ext: *job_ems_compile_ext_colony - t_ext: *job_native_compile_ext_gnosis - t_ext: *job_native_test_ext_zeppelin - t_ext: *job_native_test_ext_ens - t_ext: *job_native_test_ext_yield_liquidator - t_ext: *job_native_test_ext_uniswap - t_ext: *job_native_test_ext_prb_math - t_ext: *job_native_test_ext_elementfi - t_ext: *job_native_test_ext_brink - t_ext: *job_native_compile_ext_gp2 - t_ext: *job_native_compile_ext_euler - t_ext: *job_native_compile_ext_pool_together # TODO: Dropping the external tests below since they are based on old forks and # fail after update the default evm version to cancun. #- t_ext: *job_native_compile_ext_trident #- t_ext: *job_native_compile_ext_chainlink #- t_ext: *job_native_compile_ext_bleeps - t_ethdebug_output_validity: <<: *requires_b_ubu_static - c_ext_benchmarks: <<: *requires_nothing requires: - t_ems_compile_ext_colony - t_native_compile_ext_gnosis - t_native_test_ext_zeppelin - t_native_test_ext_ens - t_native_test_ext_yield_liquidator - t_native_test_ext_uniswap - t_native_test_ext_elementfi - t_native_test_ext_brink - t_native_compile_ext_gp2 # TODO: Dropping prb-math from the benchmarks since it is not implemented yet # in the new Foundry external testing infrastructure. # - t_native_test_ext_prb_math - t_native_compile_ext_euler - t_native_compile_ext_pool_together # TODO: Dropping the external tests below since they are based on old forks and # fail after update the default evm version to cancun. #- t_native_compile_ext_trident #- t_native_compile_ext_chainlink #- t_native_compile_ext_bleeps # Windows build and tests - b_win: *requires_nothing - t_win_soltest: *requires_b_win # Bytecode comparison: - b_bytecode_ubu_static: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix requires: - b_ubu_static - b_bytecode_ubu: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix requires: - b_ubu - b_bytecode_ubu_arm: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix requires: - b_ubu_static_arm - b_bytecode_win: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix requires: - b_win - b_bytecode_osx: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix requires: - b_osx - b_bytecode_osx_intel: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix requires: - b_osx - b_bytecode_ems: <<: *on_all_tags_and_branches matrix: *bytecode_compare_preset_matrix requires: - b_ems - t_bytecode_compare: <<: *on_all_tags_and_branches requires: - b_bytecode_ubu_static - b_bytecode_ubu - b_bytecode_ubu_arm - b_bytecode_win - b_bytecode_osx - b_bytecode_osx_intel - b_bytecode_ems # Final artifacts - c_release_binaries: <<: *on_version_tags requires: - b_ubu_static_arm - b_ubu_static - b_osx - b_win - b_ems - c_source_tarball: *requires_nothing nightly: triggers: - schedule: cron: "0 0 * * *" <<: *on_develop jobs: # ASan build and tests - b_ubu_asan: *requires_nothing - b_ubu_san_clang: *job_b_ubu_asan_clang - t_ubu_asan_soltest: *requires_b_ubu_asan - t_ubu_asan_clang_soltest: *requires_b_ubu_asan_clang - t_ubu_asan_cli: *requires_b_ubu_asan # UBSan build and tests - b_ubu_san_clang: *job_b_ubu_ubsan_clang - t_ubu_ubsan_clang_soltest: *requires_b_ubu_ubsan_clang - t_ubu_ubsan_clang_cli: *requires_b_ubu_ubsan_clang # Deprecated EVM versions tests - b_ubu: *requires_nothing - t_ubu_soltest_low_priority_evm_versions: *requires_b_ubu # Build in a Docker container (on Alpine Linux) - b_alpine_docker: *requires_nothing nightly-ossfuzz: triggers: - schedule: cron: "0 0 * * *" <<: *on_develop jobs: # OSSFUZZ builds and (regression) tests - b_ubu_ossfuzz: *requires_nothing - t_ubu_ossfuzz: *requires_b_ubu_ossfuzz ================================================ FILE: .circleci/osx_install_dependencies.sh ================================================ #! /bin/bash #------------------------------------------------------------------------------ # Bash script to install osx dependencies # # The documentation for solidity is hosted at: # # https://docs.soliditylang.org # # ------------------------------------------------------------------------------ # This file is part of solidity. # # solidity is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # solidity is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with solidity. If not, see # # (c) 2016-2019 solidity contributors. # ------------------------------------------------------------------------------ # note that the following directories may be cached by circleci: # - /usr/local # - /opt/homebrew set -eu function validate_checksum { local package="$1" local expected_checksum="$2" local actual_checksum actual_checksum=$(sha256sum "$package") if [[ $actual_checksum != "${expected_checksum} ${package}" ]] then >&2 echo "ERROR: Wrong checksum for package $package." >&2 echo "Actual: $actual_checksum" >&2 echo "Expected: $expected_checksum" exit 1 fi } if [ ! -f /usr/local/lib/libz3.a ] # if this file does not exists (cache was not restored), rebuild dependencies then brew update brew upgrade brew install cmake brew install ccache brew install wget brew install coreutils brew install diffutils brew install grep # JRE is required to run eldarica solver brew install openjdk@11 brew install unzip # boost boost_version="1.84.0" boost_package="boost_${boost_version//./_}.tar.bz2" boost_dir="boost_${boost_version//./_}" wget "https://archives.boost.io/release/$boost_version/source/$boost_package" tar xf "$boost_package" rm "$boost_package" cd "$boost_dir" ./bootstrap.sh --with-toolset=clang --with-libraries=thread,system,filesystem,program_options,serialization,test # the default number of jobs that b2 is taking, is the number of detected available CPU threads. # install boost to /opt/boost, to use it in CMake, specify Boost_ROOT sudo ./b2 -a address-model=64 architecture=arm+x86 --prefix=/opt/boost install cd .. sudo rm -rf "$boost_dir" # eldarica eldarica_version="2.1" wget "https://github.com/uuverifiers/eldarica/releases/download/v${eldarica_version}/eldarica-bin-${eldarica_version}.zip" -O /tmp/eld_binaries.zip validate_checksum /tmp/eld_binaries.zip 0ac43f45c0925383c9d2077f62bbb515fd792375f3b2b101b30c9e81dcd7785c unzip /tmp/eld_binaries.zip -d /tmp sudo mv /tmp/eldarica/{eld,eld-client,target,eldEnv} /usr/local/bin rm -rf /tmp/{eldarica,eld_binaries.zip} #cvc5 cvc5_version="1.2.0" cvc5_archive_name="cvc5-macOS-arm64-static" wget "https://github.com/cvc5/cvc5/releases/download/cvc5-${cvc5_version}/${cvc5_archive_name}.zip" -O /tmp/cvc5.zip validate_checksum /tmp/cvc5.zip 57d2d4855af3f3865110a254e415098b4e150a655f297010e27eb292f48f7da7 sudo unzip -j /tmp/cvc5.zip "${cvc5_archive_name}/bin/cvc5" -d /usr/local/bin rm -f /tmp/cvc5.zip # z3 z3_version="4.13.3" z3_dir="z3-z3-$z3_version" z3_package="z3-$z3_version.tar.gz" wget "https://github.com/Z3Prover/z3/archive/refs/tags/$z3_package" validate_checksum "$z3_package" f59c9cf600ea57fb64ffeffbffd0f2d2b896854f339e846f48f069d23bc14ba0 tar xf "$z3_package" rm "$z3_package" cd "$z3_dir" mkdir build cd build cmake -DCMAKE_OSX_ARCHITECTURES:STRING="x86_64;arm64" -DZ3_BUILD_LIBZ3_SHARED=false .. make -j "$(nproc)" sudo make install cd ../.. rm -rf "$z3_dir" # evmone evmone_version="0.16.0" evmone_package="evmone-${evmone_version}-darwin-arm64.tar.gz" wget "https://github.com/ipsilon/evmone/releases/download/v${evmone_version}/${evmone_package}" validate_checksum "$evmone_package" d26bcf7ada6c712b669ee70cbd8b534f80dadb6207fa15e15d1517d2b6823aa8 sudo tar xzpf "$evmone_package" -C /usr/local rm "$evmone_package" fi ================================================ FILE: .circleci/parallel_bytecode_report.sh ================================================ #!/usr/bin/env bash set -euo pipefail #------------------------------------------------------------------------------ # Splits all test source code into multiple files, generates bytecode and metadata # for each file and combines it into a single report.txt file. # # The script is meant to be executed in CI on all supported platforms. All generated # reports must be identical for a given compiler version. # # ------------------------------------------------------------------------------ # This file is part of solidity. # # solidity is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # solidity is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with solidity. If not, see # # (c) 2023 solidity contributors. #------------------------------------------------------------------------------ (( $# == 4 )) || { >&2 echo "Wrong number of arguments."; exit 1; } label="$1" binary_type="$2" binary_path="$3" # This path must be absolute preset="$4" [[ $binary_type == native || $binary_type == "osx_intel" || $binary_type == solcjs ]] || { >&2 echo "Invalid binary type: ${binary_type}"; exit 1; } # NOTE: Locale affects the order of the globbed files. export LC_ALL=C mkdir test-cases/ cd test-cases/ echo "Preparing input files" python3 ../scripts/isolate_tests.py ../test/ if [[ $binary_type == native || $binary_type == "osx_intel" ]]; then interface=$(echo -e "standard-json\ncli" | circleci tests split) echo "Selected interface: ${interface}" echo "Generating bytecode reports" python3 ../scripts/bytecodecompare/prepare_report.py \ "$binary_path" \ --interface "$interface" \ --preset "$preset" \ --execution-arch "$binary_type" \ --report-file "../bytecode-report-${label}-${interface}-${preset}.txt" else echo "Installing solc-js" git clone --depth 1 https://github.com/argotorg/solc-js.git solc-js cp "$binary_path" solc-js/soljson.js cd solc-js/ npm install npm run build cd .. npm install ./solc-js/dist cp ../scripts/bytecodecompare/prepare_report.js . echo "Generating bytecode reports" # shellcheck disable=SC2035 ./prepare_report.js \ --preset "$preset" \ *.sol --report-file "../bytecode-report-${label}-${preset}.txt" fi ================================================ FILE: .circleci/parallel_cli_tests.py ================================================ #!/usr/bin/env python3 import subprocess import sys # Slowest CLI tests, whose execution takes time on the order of minutes (as of June 2023). # When adding/removing items here, remember to update `parallelism` value in jobs that run this script. # TODO: We should switch to time-based splitting but that requires JUnit XML report support in cmdlineTests.sh. tests_to_run_in_parallel = [ '~ast_import_export', # ~7 min '~evmasm_import_export', # ~5 min '~ast_export_with_stop_after_parsing', # ~4 min '~soljson_via_fuzzer', # ~3 min '~via_ir_equivalence', # ~1 min '~compilation_tests', # ~1 min '~documentation_examples', # ~1 min '*', # This item represents all the remaining tests ] # Ask CircleCI to select a subset of tests for this parallel execution. # If `parallelism` in CI config is set correctly, we should get just one but we can handle any split. selected_tests = subprocess.check_output( ['circleci', 'tests', 'split'], input='\n'.join(tests_to_run_in_parallel), encoding='ascii', ).strip().split('\n') selected_tests = set(selected_tests) - {''} excluded_tests = set(tests_to_run_in_parallel) - selected_tests assert selected_tests.issubset(set(tests_to_run_in_parallel)) if len(selected_tests) == 0: print("No tests to run.") sys.exit(0) if '*' in selected_tests: filters = [arg for test_name in excluded_tests for arg in ['--exclude', test_name]] else: filters = list(selected_tests) try: subprocess.run( ['test/cmdlineTests.sh'] + filters, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr, check=True, ) except subprocess.CalledProcessError as exception: sys.exit(exception) ================================================ FILE: .circleci/soltest.ps1 ================================================ $ErrorActionPreference = "Stop" cd "$PSScriptRoot\.." .\build\solc\Release\solc.exe --version if ( -not $? ) { throw "Cannot execute solc --version." } mkdir test_results .\build\test\Release\soltest.exe --color_output=no --show_progress=yes --logger=JUNIT,error,test_results/result.xml --logger=HRF,error,stdout -- --no-smt if ( -not $? ) { throw "Unoptimized soltest run failed." } .\build\test\Release\soltest.exe --color_output=no --show_progress=yes --logger=JUNIT,error,test_results/result_opt.xml --logger=HRF,error,stdout -- --optimize --no-smt if ( -not $? ) { throw "Optimized soltest run failed." } ================================================ FILE: .circleci/soltest.sh ================================================ #!/usr/bin/env bash #------------------------------------------------------------------------------ # Bash script to execute the Solidity tests by CircleCI. # # The documentation for solidity is hosted at: # # https://docs.soliditylang.org # # ------------------------------------------------------------------------------ # Configuration Environment Variables: # # EVM=version_string Specifies EVM version to compile for (such as homestead, etc) # OPTIMIZE=1 Enables backend optimizer # ABI_ENCODER_V1=1 Forcibly enables ABI coder version 1 # SOLTEST_FLAGS= Appends to default SOLTEST_ARGS # # ------------------------------------------------------------------------------ # This file is part of solidity. # # solidity is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # solidity is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with solidity. If not, see # # (c) 2016-2019 solidity contributors. # ------------------------------------------------------------------------------ set -e OPTIMIZE=${OPTIMIZE:-"0"} EVM=${EVM:-"invalid"} EOF_VERSION=${EOF_VERSION:-0} CPUs=${CPUs:-3} REPODIR="$(realpath "$(dirname "$0")/..")" IFS=" " read -r -a BOOST_TEST_ARGS <<< "$BOOST_TEST_ARGS" IFS=" " read -r -a SOLTEST_FLAGS <<< "$SOLTEST_FLAGS" # TODO: [EOF] These won't pass on EOF yet. Reenable them when the implementation is complete. EOF_EXCLUDES=( --run_test='!yulStackLayout/literal_loop' ) # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" # Test result output directory (CircleCI is reading test results from here) mkdir -p test_results # in case we run with ASAN enabled, we must increase stack size. ulimit -s 16384 get_logfile_basename() { local run="$1" local filename="${EVM}" test "${OPTIMIZE}" = "1" && filename="${filename}_opt" test "${ABI_ENCODER_V1}" = "1" && filename="${filename}_abiv1" (( EOF_VERSION != 0 )) && filename="${filename}_eofv${EOF_VERSION}" filename="${filename}_${run}" echo -ne "${filename}" } [ -z "$CIRCLE_NODE_TOTAL" ] || [ "$CIRCLE_NODE_TOTAL" = 0 ] && CIRCLE_NODE_TOTAL=1 [ -z "$CIRCLE_NODE_INDEX" ] && CIRCLE_NODE_INDEX=0 [ -z "$INDEX_SHIFT" ] && INDEX_SHIFT=0 # Multiply by a prime number to get better spread, just in case # long-running test cases are next to each other. CIRCLE_NODE_INDEX=$(((CIRCLE_NODE_INDEX + 23 * INDEX_SHIFT) % CIRCLE_NODE_TOTAL)) PIDs=() for run in $(seq 0 $((CPUs - 1))) do BOOST_TEST_ARGS_RUN=( "--color_output=no" "--show_progress=yes" "--logger=JUNIT,error,test_results/$(get_logfile_basename "$((CPUs * CIRCLE_NODE_INDEX + run))").xml" "--logger=HRF,error,stdout" "${BOOST_TEST_ARGS[@]}" ) (( EOF_VERSION != 0 )) && BOOST_TEST_ARGS_RUN+=("${EOF_EXCLUDES[@]}") SOLTEST_ARGS=("--evm-version=$EVM" "${SOLTEST_FLAGS[@]}") test "${OPTIMIZE}" = "1" && SOLTEST_ARGS+=(--optimize) test "${ABI_ENCODER_V1}" = "1" && SOLTEST_ARGS+=(--abiencoderv1) (( EOF_VERSION != 0 )) && SOLTEST_ARGS+=(--eof-version "$EOF_VERSION") BATCH_ARGS=("--batches" "$((CPUs * CIRCLE_NODE_TOTAL))" "--selected-batch" "$((CPUs * CIRCLE_NODE_INDEX + run))") echo "Running ${REPODIR}/build/test/soltest ${BOOST_TEST_ARGS_RUN[*]} -- ${SOLTEST_ARGS[*]}" "${REPODIR}/build/test/soltest" -l test_suite "${BOOST_TEST_ARGS_RUN[@]}" -- "${SOLTEST_ARGS[@]}" "${BATCH_ARGS[@]}" & PIDs+=($!) done # wait for individual processes to get their exit status for pid in "${PIDs[@]}" do wait "$pid" done ================================================ FILE: .circleci/soltest_all.sh ================================================ #! /bin/bash #------------------------------------------------------------------------------ # Bash script to execute the Solidity tests by CircleCI. # # The documentation for solidity is hosted at: # # https://docs.soliditylang.org # # ------------------------------------------------------------------------------ # This file is part of solidity. # # solidity is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # solidity is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with solidity. If not, see # # (c) 2016-2019 solidity contributors. # ------------------------------------------------------------------------------ set -e REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" DEFAULT_EVM_VALUES=( homestead constantinople istanbul berlin london paris shanghai cancun osaka ) EVMS_WITH_EOF=(osaka) # Deserialize the EVM_VALUES array if it was provided as argument or # set EVM_VALUES to the default values. IFS=" " read -ra EVM_VALUES <<< "${1:-${DEFAULT_EVM_VALUES[@]}}" DEFAULT_EVM=osaka OPTIMIZE_VALUES=(0 1) # TODO: EOF is marked as experimental in evmone. Reenable when proper handling for that is added here. EOF_VERSIONS=(0) # Run for ABI encoder v1, without SMTChecker tests. EVM="${DEFAULT_EVM}" \ OPTIMIZE=1 \ ABI_ENCODER_V1=1 \ BOOST_TEST_ARGS="-t !smtCheckerTests" \ "${REPODIR}/.circleci/soltest.sh" # We shift the batch index so that long-running tests # do not always run in the same executor for all EVM versions INDEX_SHIFT=0 for OPTIMIZE in "${OPTIMIZE_VALUES[@]}" do for EVM in "${EVM_VALUES[@]}" do for EOF_VERSION in "${EOF_VERSIONS[@]}" do if (( EOF_VERSION > 0 )) && [[ ! " ${EVMS_WITH_EOF[*]} " == *" $EVM "* ]]; then continue fi ENFORCE_GAS_ARGS="" [ "${EVM}" = "${DEFAULT_EVM}" ] && ENFORCE_GAS_ARGS="--enforce-gas-cost" # Run SMTChecker tests only when OPTIMIZE == 0 DISABLE_SMTCHECKER="" [ "${OPTIMIZE}" != "0" ] && DISABLE_SMTCHECKER="-t !smtCheckerTests" EVM="$EVM" \ EOF_VERSION="$EOF_VERSION" \ OPTIMIZE="$OPTIMIZE" \ SOLTEST_FLAGS="$SOLTEST_FLAGS $ENFORCE_GAS_ARGS" \ BOOST_TEST_ARGS="-t !@nooptions $DISABLE_SMTCHECKER" \ INDEX_SHIFT="$INDEX_SHIFT" \ "${REPODIR}/.circleci/soltest.sh" INDEX_SHIFT=$((INDEX_SHIFT + 1)) done done done ================================================ FILE: .clang-format ================================================ # Formatting approximately used in Solidity's C++ # # See https://clang.llvm.org/docs/ClangFormatStyleOptions.html # For an online formatter to test settings, see # https://zed0.co.uk/clang-format-configurator/ # Note that clang-format cannot express the style that closing parentheses # behave similar to closing curly braces in a multi-line setting in that # they have to be on a line of their own at the same indentation level # as the opening part (aka "dangling parenthesis", see https://reviews.llvm.org/D33029). Language: Cpp BasedOnStyle: LLVM AccessModifierOffset: -4 AlignAfterOpenBracket: AlwaysBreak AlignEscapedNewlines: Left AlwaysBreakAfterReturnType: None AlwaysBreakTemplateDeclarations: Yes BinPackArguments: false BinPackParameters: false BreakBeforeBinaryOperators: All BreakBeforeBraces: Allman ColumnLimit: 120 ContinuationIndentWidth: 4 FixNamespaceComments: false IndentWidth: 4 KeepEmptyLinesAtTheStartOfBlocks: false MaxEmptyLinesToKeep: 2 PenaltyBreakBeforeFirstCallParameter: 2000 PointerAlignment: Left SpaceAfterCStyleCast: true SpaceAfterTemplateKeyword: false SpaceBeforeCtorInitializerColon: false SpaceBeforeInheritanceColon: false SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: false TabWidth: 4 UseTab: Always # Local Variables: # mode: yaml # End: ================================================ FILE: .codespellrc ================================================ [codespell] skip = .git,deps,LICENSE,*.enc,Dockerfile*,codespell_whitelist.txt,codespell_ignored_lines.txt ignore-words = scripts/codespell_whitelist.txt exclude-file = scripts/codespell_ignored_lines.txt ================================================ FILE: .dockerignore ================================================ # out-of-tree builds usually go here. This helps improving performance of uploading # the build context to the docker image build server /build ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [*.{cpp,h}] indent_style = tab indent_size = 4 [*.{py,rst,sh,yml}] indent_style = space indent_size = 4 [*.{sol,yul}] indent_style = space indent_size = 4 [*.{txt,cmake,json}] indent_style = tab indent_size = 4 ================================================ FILE: .gitattributes ================================================ *.sol linguist-language=Solidity ================================================ FILE: .github/CODEOWNERS ================================================ /docs/style-guide.rst @fulldecent ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug Report about: Problems, deficiencies, inaccuracies or crashes discovered on Solidity. title: '' labels: 'bug :bug:' assignees: '' --- ## Description ## Environment - Compiler version: - Compilation pipeline (legacy, IR, EOF): - Target EVM version (as per compiler settings): - Framework/IDE (e.g. Foundry, Hardhat, Remix): - EVM execution environment / backend / blockchain client: - Operating system: ## Steps to Reproduce ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: Initiate a language design or feedback discussion url: https://forum.soliditylang.org about: Open a thread on the Solidity forum. ================================================ FILE: .github/ISSUE_TEMPLATE/documentation_issue.md ================================================ --- name: Documentation Issue about: Corrections, improvements or requests for new content on Solidity's documentation. title: '' labels: 'documentation :book:' assignees: '' --- ## Page ## Abstract ## Pull request ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature Request about: Ideas, comments or messages asking for a particular functionality to be added to Solidity. title: '' labels: feature assignees: '' --- ## Abstract ## Motivation ## Specification ## Backwards Compatibility ================================================ FILE: .github/workflows/buildpack-deps.yml ================================================ name: buildpack-deps permissions: packages: write pull-requests: write on: pull_request: branches: [ develop ] paths: - 'scripts/docker/buildpack-deps/Dockerfile.emscripten' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu.clang.ossfuzz' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.clang' - 'scripts/docker/buildpack-deps/Dockerfile.ubuntu2404.arm' jobs: buildpack-deps: runs-on: ${{ matrix.runs-on }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DOCKER_REPOSITORY: ghcr.io/argotorg/solidity-buildpack-deps IMAGE_NAME: buildpack-deps strategy: fail-fast: false matrix: include: - image_variant: emscripten runs-on: ubuntu-latest - image_variant: ubuntu.clang.ossfuzz runs-on: ubuntu-latest - image_variant: ubuntu2404 runs-on: ubuntu-latest - image_variant: ubuntu2404.clang runs-on: ubuntu-latest - image_variant: ubuntu2404.arm runs-on: ubuntu-24.04-arm steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 - name: Log in to GitHub Container Registry uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Upgrade ${{ env.IMAGE_NAME }}-${{ matrix.image_variant }} run: | scripts/ci/docker_upgrade.sh ${{ env.IMAGE_NAME }} ${{ matrix.image_variant }} ${{ env.DOCKER_REPOSITORY }} - name: comment PR if: "env.DOCKER_IMAGE" uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1 with: message: "`${{ env.DOCKER_IMAGE }} ${{ env.DOCKER_REPO_DIGEST }}`." ================================================ FILE: .github/workflows/stale.yml ================================================ name: Check stale pull requests on: workflow_dispatch: schedule: - cron: '0 12 * * *' permissions: pull-requests: write env: # NOTE: We set the parameters below to -1, so issues will never be marked as stale or closed automatically. BEFORE_ISSUE_STALE: -1 BEFORE_ISSUE_CLOSE: -1 BEFORE_PR_STALE: 14 BEFORE_PR_CLOSE: 7 jobs: stale: runs-on: ubuntu-latest steps: - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 with: debug-only: false days-before-issue-stale: ${{ env.BEFORE_ISSUE_STALE }} days-before-issue-close: ${{ env.BEFORE_ISSUE_CLOSE }} ascending: true stale-pr-message: | This pull request is stale because it has been open for ${{ env.BEFORE_PR_STALE }} days with no activity. It will be closed in ${{ env.BEFORE_PR_CLOSE }} days unless the `stale` label is removed. close-pr-message: | This pull request was closed due to a lack of activity for ${{ env.BEFORE_PR_CLOSE }} days after it was stale. stale-pr-label: stale close-pr-label: closed-due-inactivity days-before-pr-stale: ${{ env.BEFORE_PR_STALE }} days-before-pr-close: ${{ env.BEFORE_PR_CLOSE }} exempt-pr-labels: 'external contribution :star:,roadmap,epic' exempt-draft-pr: false exempt-all-milestones: true remove-stale-when-updated: true operations-per-run: 256 ================================================ FILE: .github/workflows/welcome-external-pr.yml ================================================ name: External contributor greeter on: pull_request_target: types: - opened permissions: pull-requests: write contents: read env: DRY_RUN: false jobs: comment-external-pr: runs-on: ubuntu-latest steps: # Note: this step requires that the INTERNAL_CONTRIBUTORS environment variable # is already defined in the repository with the current json list of internal contributors. - name: Comment on external contribution PR if: "!contains(fromJSON(vars.INTERNAL_CONTRIBUTORS), github.event.pull_request.user.login)" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR: ${{ github.event.pull_request.html_url }} run: | echo "Commenting in a newly submitted or reopened external PR: $PR" if [[ $DRY_RUN == 'false' ]]; then gh pr edit "$PR" --add-label "external contribution :star:" comment_body=( "Thank you for your contribution to the Solidity compiler! A team member will follow up shortly." "\n\n" "If you haven't read our [contributing guidelines](https://docs.soliditylang.org/en/latest/contributing.html) and our " "[review checklist](https://github.com/argotorg/solidity/blob/develop/ReviewChecklist.md) before, " "please do it now, this makes the reviewing process and accepting your contribution smoother." "\n\n" "If you have any questions or need our help, feel free to post them in the PR or talk to us directly on the " "[#solidity-dev](https://matrix.to/#/#ethereum_solidity-dev:gitter.im) channel on Matrix." ) gh pr comment $PR --body "$(IFS='' ; echo -e "${comment_body[*]}")" fi ================================================ FILE: .gitignore ================================================ /commit_hash.txt /prerelease.txt # Compiled Object files *.slo *.lo *.o *.obj *.pyc __pycache__/ # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Compiled Static libraries *.lai *.la *.a *.lib # ignore git mergetool backup files *.orig # Executables *.exe *.out *.app # Build directory /cmake-build-*/ /build*/ emscripten_build/ /docs/_build/ /docs/_static/robots.txt /deps/ # Reports and benchmarks /reports/ /benchmarks/ # vim stuff [._]*.sw[a-p] [._]sw[a-p] # emacs stuff *~ # IDE files /.idea/ /.vscode/ /browse.VC.db /CMakeLists.txt.user /CMakeSettings.json /.vs /.cproject /.project # OS specific local files .DS_Store Thumbs.db # AI tooling /.claude/ ================================================ FILE: .gitmodules ================================================ [submodule "deps/nlohmann-json"] path = deps/nlohmann-json url = https://github.com/nlohmann/json.git [submodule "deps/range-v3"] path = deps/range-v3 url = https://github.com/ericniebler/range-v3.git [submodule "deps/fmtlib"] path = deps/fmtlib url = https://github.com/fmtlib/fmt.git ================================================ FILE: .readthedocs.yml ================================================ version: 2 build: os: ubuntu-24.04 tools: python: "3.13" sphinx: builder: html configuration: docs/conf.py formats: - pdf - epub python: install: - requirements: docs/requirements.txt ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.13.0) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(ETH_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake" CACHE PATH "The path to the cmake directory") list(APPEND CMAKE_MODULE_PATH ${ETH_CMAKE_DIR}) # Set the build type, if none was specified. if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) if(EXISTS "${PROJECT_SOURCE_DIR}/.git") set(DEFAULT_BUILD_TYPE "RelWithDebInfo") else() set(DEFAULT_BUILD_TYPE "Release") endif() set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo" "MinSizeRel") endif() include(EthToolchains) # Set cmake_policies include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 set(PROJECT_VERSION "0.8.35") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) include(TestBigEndian) TEST_BIG_ENDIAN(IS_BIG_ENDIAN) if (IS_BIG_ENDIAN) message(FATAL_ERROR "${PROJECT_NAME} currently does not support big endian systems.") endif() option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) option(SOLC_STATIC_STDLIBS "Link solc against static versions of libgcc and libstdc++ on supported platforms" OFF) option(STRICT_Z3_VERSION "Require the exact version of Z3 solver expected by our test suite." ON) option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warnings as errors." ON) option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) option( IGNORE_VENDORED_DEPENDENCIES "Ignore libraries provided as submodules of the repository and allow CMake to look for \ them in the typical locations, including system-wide dirs." OFF ) option( ONLY_BUILD_SOLIDITY_LIBRARIES "Only build library targets that can be statically linked against. Do not build executables or tests." OFF ) mark_as_advanced(PROFILE_OPTIMIZER_STEPS) mark_as_advanced(IGNORE_VENDORED_DEPENDENCIES) mark_as_advanced(ONLY_BUILD_SOLIDITY_LIBRARIES) # Setup cccache. include(EthCcache) # Let's find our dependencies include(EthDependencies) if (NOT IGNORE_VENDORED_DEPENDENCIES) include(fmtlib) include(nlohmann-json) include(range-v3) else () message(WARNING "-- Ignoring vendored dependencies. Will use installed versions if found. Versions may differ from the ones the compiler was tested with. Make sure to run the test suite and thoroughly test the resulting binaries before using them in production.") find_package(fmt REQUIRED) find_package(nlohmann_json REQUIRED) find_package(range-v3 REQUIRED) endif() find_package(Threads) if(NOT PEDANTIC) message(WARNING "-- Pedantic build flags turned off. Warnings will not make compilation fail. This is NOT recommended in development builds.") endif() if (PROFILE_OPTIMIZER_STEPS) add_definitions(-DPROFILE_OPTIMIZER_STEPS) endif() # Figure out what compiler and system are we using include(EthCompilerSettings) # Include utils include(EthUtils) # Create license.h from LICENSE.txt and template # Converting to char array is required due to MSVC's string size limit. file(READ ${PROJECT_SOURCE_DIR}/LICENSE.txt LICENSE_TEXT HEX) string(REGEX MATCHALL ".." LICENSE_TEXT "${LICENSE_TEXT}") string(REGEX REPLACE ";" ",\n\t0x" LICENSE_TEXT "${LICENSE_TEXT}") set(LICENSE_TEXT "0x${LICENSE_TEXT}") configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/license.h.in" include/license.h) include(EthOptions) configure_project(TESTS) if(EMSCRIPTEN) set(TESTED_Z3_VERSION "4.13.3") set(MINIMUM_Z3_VERSION "4.8.16") find_package(Z3) if (${Z3_FOUND}) add_definitions(-DEMSCRIPTEN_BUILD) if (${STRICT_Z3_VERSION}) if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${TESTED_Z3_VERSION})) message( FATAL_ERROR "SMTChecker tests require Z3 ${TESTED_Z3_VERSION} for all tests to pass.\n" ) endif() else() if ("${Z3_VERSION_STRING}" VERSION_LESS ${MINIMUM_Z3_VERSION}) message( FATAL_ERROR "Solidity requires Z3 ${MINIMUM_Z3_VERSION} or newer." ) endif() endif() else() message(FATAL_ERROR "Solidity requires Z3 for emscripten build.") endif() endif() add_subdirectory(libsolutil) add_subdirectory(liblangutil) add_subdirectory(libsmtutil) add_subdirectory(libevmasm) add_subdirectory(libyul) add_subdirectory(libsolidity) add_subdirectory(libsolc) add_subdirectory(libstdlib) if (NOT ONLY_BUILD_SOLIDITY_LIBRARIES) add_subdirectory(tools) if (NOT EMSCRIPTEN) add_subdirectory(solc) endif() if (TESTS AND NOT EMSCRIPTEN) add_subdirectory(test) endif() endif() ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at solidity@ethereum.org. To report an issue involving the Solidity team please email José Pedro Cabrita at zepedro@ethereum.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org ================================================ FILE: CODING_STYLE.md ================================================ ## 0. Formatting **GOLDEN RULE**: Follow the style of the existing code when you make changes. 1. Use tabs for leading indentation: - tab stops are every 4 characters (only relevant for line length). - one indentation level -> exactly one byte (i.e. a tab character) in the source file. 2. Line widths: - Lines should be at most 99 characters wide to make diff views readable and reduce merge conflicts. - Lines of comments should be formatted according to ease of viewing, but simplicity is to be preferred over beauty. 3. Single-statement blocks should not have braces, unless required for clarity. 4. Never place condition bodies on same line as condition. 5. Space between keyword and opening parenthesis, but not following opening parenthesis or before final parenthesis. 6. No spaces for unary operators, `->` or `.`. 7. No space before `:` but one after it, except in the ternary operator: one on both sides. 8. Add spaces around all other operators. 9. Braces, when used, always have their own lines and are at same indentation level as "parent" scope. 10. If lines are broken, a list of elements enclosed with parentheses (of any kind) and separated by a separator (of any kind) are formatted such that there is exactly one element per line, followed by the separator, the opening parenthesis is on the first line, followed by a line break and the closing parenthesis is on a line of its own unindented). See example below. Yes: ```cpp if (a == b[i]) printf("Hello\n"); // NOTE spaces used instead of tab here for clarity - first byte should be '\t'. foo->bar( someLongVariableName, anotherLongVariableName, anotherLongVariableName, anotherLongVariableName, anotherLongVariableName ); cout << "some very long string that contains completely irrelevant " << "text that talks about this and that and contains the words " << "\"lorem\" and \"ipsum\"" << endl; ``` No: ```cpp if( a==b[ i ] ) { printf ("Hello\n"); } foo->bar(someLongVariableName, anotherLongVariableName, anotherLongVariableName, anotherLongVariableName, anotherLongVariableName); cout << "some very long string that contains completely irrelevant text that talks about this and that and contains the words \"lorem\" and \"ipsum\"" << endl; ``` To set indentation and tab width settings uniformly, the repository contains an [EditorConfig](https://editorconfig.org/) [`.editorconfig`](https://github.com/argotorg/solidity/blob/develop/.editorconfig) file, which describes some of the styles used and which is recognized by many IDE's and editors. ## 1. Namespaces 1. No `using namespace` declarations in header files. 2. `using namespace solidity;` and other project local namespaces is fine in cpp files, and generally encouraged. 3. Avoid `using namespace` at file level for third party libraries, such as boost, ranges, etc. 4. All symbols should be declared in a namespace except for final applications. 5. Use anonymous namespaces for helpers whose scope is a cpp file only. 6. Preprocessor symbols should be prefixed with the namespace in all-caps and an underscore. Only in the header: ```cpp #include namespace myNamespace { std::tuple meanAndSigma(std::vector const& _v); } ``` ## 2. Preprocessor 1. File comment is always at top, and includes: - Copyright - License (e.g. see COPYING) 2. Never use `#ifdef`/`#define`/`#endif` file guards. Prefer `#pragma` once as first line below file comment. 3. Prefer static constexpr variables to value macros. 4. Prefer inline constexpr functions to function macros. 5. Split complex macro on multiple lines with `\`. ## 3. Capitalization **GOLDEN RULE**: Preprocessor: `ALL_CAPS`; C++: `camelCase`. 1. Use camelCase for splitting words in names, except where obviously extending STL/boost functionality in which case follow those naming conventions. 2. The following entities' first alpha is upper case: - Type names - Template parameters - Enum members - static const variables that form an external API. 3. All preprocessor symbols (macros, macro arguments) in full uppercase with underscore word separation. All other entities' first alpha is lower case. ## 4. Variable prefixes 1. Leading underscore "_" to parameter names: - Exception: "o_parameterName" when it is used exclusively for output. See 6(f). - Exception: "io_parameterName" when it is used for both input and output. See 6(f). 2. Leading "g_" to global (non-const) variables. 3. Leading "s_" to static (non-const, non-global) variables. ## 5. Assertions Use `solAssert` and `solUnimplementedAssert` generously to check assumptions that span across different parts of the code base, for example before dereferencing a pointer. ## 6. Declarations 1. {Typename} + {qualifiers} + {name}. 2. Only one per line. 3. Associate */& with type, not variable (at ends with parser, but more readable, and safe if in conjunction with (b)). 4. Favour declarations close to use; do not habitually declare at top of scope ala C. 5. Pass non-trivial parameters as const reference, unless the data is to be copied into the function, then either pass by const reference or by value and use std::move. 6. If a function returns multiple values, use std::tuple (std::pair acceptable) or better introduce a struct type. Do not use */& arguments. 7. Use parameters of pointer type only if `nullptr` is a valid argument, use references otherwise. Often, `std::optional` is better suited than a raw pointer. 8. Never use a macro where adequate non-preprocessor C++ can be written. 9. Only use `auto` if the type is very long and rather irrelevant. 10. Do not pass bools: prefer enumerations instead. 11. Prefer enum class to straight enum. 12. Always initialize POD variables, even if their value is overwritten later. Yes: ```cpp enum class Accuracy { Approximate, Exact }; struct MeanSigma { float mean = 0.0f; float standardDeviation = 1.0f; }; double const d = 0; int i = 0; int j = 0; char* s = nullptr; MeanAndSigma ms meanAndSigma(std::vector const& _v, Accuracy _a); Derived* x = dynamic_cast(base); for (auto i = x->begin(); i != x->end(); ++i) {} ``` No: ```cpp const double d = 0; int i, j; char *s; float meanAndSigma(std::vector _v, float* _sigma, bool _approximate); Derived* x(dynamic_cast(base)); for (map::iterator i = l.begin(); i != l.end(); ++l) {} ``` ## 7. Structs & classes 1. Structs to be used when all members public and no virtual functions: - In this case, members should be named naturally and not prefixed with `m_`. 2. Classes to be used in all other circumstances. ## 8. Members 1. One member per line only. 2. Private, non-static, non-const fields prefixed with `m_`. 3. Avoid public fields, except in structs. 4. Use override, final and const as much as possible. 5. No implementations with the class declaration, except: - template or force-inline method (though prefer implementation at bottom of header file). - one-line implementation (in which case include it in same line as declaration). 6. For a property `foo` - Member: `m_foo` - Getter: `foo()` [ also: for booleans, `isFoo()` ] - Setter: `setFoo()` ## 9. Naming 1. Avoid unpronounceable names. 2. Names should be shortened only if they are extremely common, but shortening should be generally avoided 3. Avoid prefixes of initials (e.g. do not use `IMyInterface`, `CMyImplementation`) 4. Find short, memorable & (at least semi-) descriptive names for commonly used classes or name-fragments: - A dictionary and thesaurus are your friends; - Spell correctly; - Think carefully about the class's purpose; - Imagine it as an isolated component to try to decontextualise it when considering its name; - Don't be trapped into naming it (purely) in terms of its implementation. ## 10. Type definitions 1. Prefer `using` to `typedef`. e.g. `using ints = std::vector;` rather than typedef `std::vector ints;` 2. Generally avoid shortening a standard form that already includes all important information: - e.g. stick to `shared_ptr` rather than shortening to `ptr`. 3. Where there are exceptions to this (due to excessive use and clear meaning), note the change prominently and use it consistently: - e.g. `using Guard = std::lock_guard;` ///< Guard is used throughout the codebase since it is clear in meaning and used commonly. 4. In general expressions should be roughly as important/semantically meaningful as the space they occupy. 5. Avoid introducing aliases for types unless they are very complicated. Consider the number of items a brain can keep track of at the same time. ## 11. Commenting 1. Comments should be doxygen-compilable, using @notation rather than \notation. 2. Document the interface, not the implementation: - Documentation should be able to remain completely unchanged, even if the method is reimplemented; - Comment in terms of the method properties and intended alteration to class state (or what aspects of the state it reports); - Be careful to scrutinise documentation that extends only to intended purpose and usage; - Reject documentation that is simply an English transaction of the implementation. 3. Avoid in-code comments. Instead, try to extract blocks of functionality into functions. This often already eliminates the need for an in-code comment. ## 12. Include Headers 1. Includes should go in increasing order of generality (`libsolidity` -> `libevmasm` -> `libsolutil` -> `boost` -> `STL`). 2. The corresponding `.h` file should be the first include in the respective `.cpp` file. 3. Insert empty lines between blocks of include files. Example: ```cpp #include #include #include #include #include #include #include #include #include #include #include #include ``` See [this issue](https://stackoverflow.com/questions/614302/c-header-order/614333#614333 "C header order") for the reason: this makes it easier to find missing includes in header files. ## 13. Recommended reading - Herb Sutter and Bjarne Stroustrup: - [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md) - Herb Sutter and Andrei Alexandrescu: - "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" - Scott Meyers: - "Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition)" - "More Effective C++: 35 New Ways to Improve Your Programs and Designs" - "Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14" ================================================ FILE: CONTRIBUTING.md ================================================ # Contribution Guidelines Please see our contribution guidelines in [the Solidity documentation](https://docs.soliditylang.org/en/latest/contributing.html). Thank you for your help! ================================================ FILE: Changelog.md ================================================ ### 0.8.35 (unreleased) Language Features: * General: Add a builtin that computes the base slot of a storage namespace using the `erc7201` formula from ERC-7201. Compiler Features: * Commandline Interface: Disallow selecting the deprecated assembly input mode that was only accessible via `--assemble` instead of treating it as equivalent to `--strict-assembly`. * Commandline Interface: Introduce `--experimental` flag required for enabling the experimental mode. * General: Introduce the SSA CFG codegen (experimental). * General: Restrict the existing experimental features (`generic-solidity`, `lsp`, `ethdebug`, `eof`, `evm`, `ast-import`, `evmasm-import`, `ir-ast`, `ssa-cfg`) to experimental mode. * Metadata: Store the state of the experimental mode in JSON and CBOR metadata. In CBOR this broadens the meaning of the existing `experimental` field, which used to indicate only the presence of certain experimental pragmas in the source. * Standard JSON Interface: Introduce `settings.experimental` setting required for enabling the experimental mode. * Yul Optimizer: Improve performance of control flow side effects collector and function references resolver. Bugfixes: * Yul: Fix incorrect serialization of Yul object names containing double quotes and escape sequences, producing output that could not be parsed as valid Yul. * Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue. ### 0.8.34 (2026-02-18) Important Bugfixes: * Yul IR Code Generation: Fix a bug that could result in clearing a storage variable instead of a transient storage variable at the same position in the layout (and vice-versa). Compiler Features: * Yul Optimizer: Remove redundant prerequisite steps from the default optimizer sequence. ### 0.8.33 (2025-12-18) Bugfixes: * TypeChecker: Fix internal error when accessing getters of constant variables. ### 0.8.32 (2025-12-18) Important Bugfixes: * Code Generator: Fix a bug in clearing/copying of arrays that straddle the end of storage, potentially resulting in assignment/initialization/`delete`/`push()`/`pop()` skipping some or all of the intended storage writes. Bugfixes: * Codegen: Fix internal compiler error when emitting events via module member access. * TypeChecker: Fix error and event selectors not being considered compile-time constant. * TypeChecker: Fix `string.concat` and `bytes.concat` with constant arguments not being considered compile-time constant. ### 0.8.31 (2025-12-03) Language Features: * Custom Storage Layout: Allow using `constant` state variables in the base slot expression. * DocString Parser: Warn about deprecation of inline assembly special comment `memory-safe-assembly`. * Syntax Checker: Warn about deprecation of ABI coder v1. * Syntax Checker: Warn about deprecation of virtual modifiers. * Type Checker: Warn about deprecation of `send` and `transfer` functions on instances of `address`. * Type Checker: Warn about deprecation of comparisons between variables of contract types. * Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word. Compiler Features: * ethdebug: Experimental support for instructions and source locations under EOF. * EVM: Set default EVM Version to `osaka`. Bugfixes: * Assembler: Fix not using a fixed-width type for IDs being assigned to subassemblies nested more than one level away, resulting in inconsistent `--asm-json` output between target architectures. * Yul Optimizer: Fix edge case in which invalid Yul code is produced by ExpressionSimplifier due to expressions being substituted that contain out-of-scope variables. Build System: * Enable Linux arm64 binaries for testing and releases. * Ubuntu PPA Packages: Discontinue the PPA as a binary distribution channel. * Update minimum version requirements of Boost to 1.83.0 for non-windows builds and of GCC and Clang to 13.3 and 18.1.3, respectively. Fixes infinite recursion on `boost::rational` comparison affecting compiler binaries built with GCC<14.0 and Boost<1.75. ### 0.8.30 (2025-05-07) Compiler Features: * EVM: Set default EVM Version to `prague`. * NatSpec: Capture Natspec documentation of `enum` values in the AST. Bugfixes: * SMTChecker: Do not consider loop conditions as constant-condition verification target as this could cause incorrect reports and internal compiler errors. * SMTChecker: Fix incorrect analysis when only a subset of contracts is selected with `--model-checker-contracts`. * SMTChecker: Fix internal compiler error when string literal is used to initialize user-defined type based on fixed bytes. ### 0.8.29 (2025-03-12) Language Features: * Allow relocating contract storage to an arbitrary location. Compiler Features: * Error Reporting: Errors reported during code generation now point at the location of the contract when more fine-grained location is not available. * ethdebug: Experimental support for instructions and source locations. * EVM: Support for the EVM version "Osaka". * EVM Assembly Import: Allow enabling opcode-based optimizer. * General: The experimental EOF backend implements a subset of EOF sufficient to compile arbitrary high-level Solidity syntax via IR with optimization enabled. * SMTChecker: Support ``block.blobbasefee`` and ``blobhash``. * SMTChecker: The option ``--model-checker-print-query`` no longer requires ``--model-checker-solvers smtlib2``. * SMTChecker: Z3 is now a runtime dependency, not a build dependency (except for emscripten build). * Yul Parser: Make name clash with a builtin a non-fatal error. Bugfixes: * Commandline Interface: Report StackTooDeep errors in compiler mode as proper errors instead of printing diagnostic information meant for internal compiler errors. * Error Reporting: Fix error locations not being shown for source files with empty names. * General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts. * Metadata: Fix custom cleanup sequence missing from metadata when other optimizer settings have default values. * SMTChecker: Fix internal compiler error when analyzing overflowing expressions or bitwise negation of unsigned types involving constants. * SMTChecker: Fix reporting on targets that are safe in the context of one contract but unsafe in the context of another contract. * SMTChecker: Fix SMT logic error when analyzing cross-contract getter call with BMC. * SMTChecker: Fix SMT logic error when contract deployment involves string literal to fixed bytes conversion. * SMTChecker: Fix SMT logic error when external call has extra effectless parentheses. * SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals. * SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations. * SMTChecker: Fix wrong encoding of string literals as arguments of ``ecrecover`` precompile. * Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested. * TypeChecker: Fix spurious compilation errors due to incorrect computation of contract storage size which erroneously included transient storage variables. * Yul: Fix internal compiler error when a code generation error should be reported instead. * Yul Optimizer: Fix failing debug assertion due to dereferencing of an empty ``optional`` value. Build system: * Linux release builds are fully static again and no longer depend on ``glibc``. * Switch from C++17 to C++20 as the target standard. Solc-Js: * The wrapper now requires at least nodejs v12. ### 0.8.28 (2024-10-09) Language Features: * Transient storage state variables of value types are now fully supported. Compiler Features: * General: Generate JSON representations of Yul ASTs only on demand to reduce memory usage. * Standard JSON Interface: Bytecode or IR can now be requested for a subset of all contracts without triggering unnecessary code generation for other contracts. Bugfixes: * SMTChecker: Fix SMT logic error when assigning to an array of addresses. * Yul AST: Fix shifted native source locations when debug info selection included code snippets. Build system: * Removed ``USE_LD_GOLD`` option and default to use the compiler default linker. For custom linkers, ``CMAKE_CXX_FLAGS`` can be used. ### 0.8.27 (2024-09-04) Language Features: * Accept declarations of state variables with ``transient`` data location (parser support only, no code generation yet). * Make ``require(bool, Error)`` available when using the legacy pipeline. * Yul: Parsing rules for source location comments have been relaxed: Whitespace between the location components as well as single-quoted code snippets are now allowed. Compiler Features: * Commandline Interface: Add ``--transient-storage-layout`` output. * Commandline Interface: Allow the use of ``--asm-json`` output option in assembler mode to export EVM assembly of the contracts in JSON format. * Commandline Interface: Do not perform IR optimization when only unoptimized IR is requested. * Constant Optimizer: Uses ``PUSH0`` if supported by the selected evm version. * Error Reporting: Unimplemented features are now properly reported as errors instead of being handled as if they were bugs. * EVM: Support for the EVM version "Prague". * Peephole Optimizer: ``PUSH0``, when supported, is duplicated explicitly instead of using ``DUP1``. * Peephole Optimizer: Remove identical code snippets that terminate the control flow if they occur one after another. * SMTChecker: Add CHC engine check for underflow and overflow in unary minus operation. * SMTChecker: Replace CVC4 as a possible BMC backend with cvc5. * Standard JSON Interface: Add ``transientStorageLayout`` output. * Standard JSON Interface: Do not perform IR optimization when only unoptimized IR is requested. * Yul: Drop the deprecated typed Yul dialect that was only accessible via ``--yul`` in the CLI. * Yul: The presence of types in untyped Yul dialects is now a parser error. * Yul Optimizer: Caching of optimized IR to speed up optimization of contracts with bytecode dependencies. * Yul Optimizer: The optimizer now treats some previously unrecognized identical literals as identical. Bugfixes: * Assembler: Fix ICE caused by imprecise calculation of required size of tags in bytecode when code size is above 255. * Parser: Fix spuriously emitted parser error for unary plus operations when used as binary operator in some cases. * SMTChecker: Fix error that reports invalid number of verified checks for BMC and CHC engines. * SMTChecker: Fix formatting of unary minus expressions in invariants. * SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine. * SMTChecker: Fix SMT logic error when assigning to an array of contracts or functions. * Standard JSON Interface: For Yul input, properly produce output artifacts in case of warnings. * TypeChecker: Fix segfault when assigning nested tuple to tuple. * Yul IR Code Generation: Deterministic order of Yul subobjects. * Yul Optimizer: Fix Yul source locations always referring to unoptimized source, even in optimized outputs. * Yul Optimizer: Fix warnings being generated twice when there are no errors. * Yul Optimizer: Name simplification could lead to forbidden identifiers with a leading and/or trailing dot, e.g., ``x._`` would get simplified into ``x.``. * Yul Parser: Fix segfault when parsing very long location comments. Build System: * Change build system to use git submodules for some dependencies (nlohmann-json, fmtlib & range-v3). ### 0.8.26 (2024-05-21) Language Features: * Introduce a new overload ``require(bool, Error)`` that allows usage of ``require`` functions with custom errors. This feature is available in the ``via-ir`` pipeline only. Compiler Features: * SMTChecker: Create balance check verification target for CHC engine. * Yul IR Code Generation: Cheaper code for reverting with errors of a small static encoding size. * Yul Optimizer: New, faster default optimizer step sequence. Bugfixes: * Commandline Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``--yul-optimizations`` sequence. * SMTChecker: Fix false positive when comparing hashes of same array or string literals. * SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain. * SMTChecker: Fix internal error when using an empty tuple in a conditional operator. * SMTChecker: Fix internal error when using bitwise operators with an array element as argument. * Standard JSON Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``optimizerSteps`` sequence. * StaticAnalyzer: Only raise a compile time error for division and modulo by zero when it's between literals. * TypeChecker: Fix compiler crash when the left-hand side of an assignment was a parenthesized non-tuple expression of a tuple type. * Yul Optimizer: Fix optimizer executing each repeating part of the step sequence at least twice, even if the code size already became stable after the first iteration. * Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline. Build System: * Replace internal JSON library jsoncpp with nlohmann::json. ### 0.8.25 (2024-03-14) Compiler Features: * Code Generator: Use ``MCOPY`` instead of ``MLOAD``/``MSTORE`` loop when copying byte arrays. * EVM: Set default EVM version to ``cancun``. * Yul Analyzer: Emit transient storage warning only for the first occurrence of ``tstore``. Bugfixes: * Assembler: Prevent incorrect calculation of tag sizes. * Commandline Interface: Do not run IR pipeline when ``--via-ir`` is used but no output that depends on the IR is requested. * EVM Assembly Import: Fix handling of missing source locations during import. * SMTChecker: Ensure query is properly flushed to a file before calling solver when using SMT-LIB interface. * SMTChecker: Fix internal error caused by not respecting the sign of an integer type when constructing zero-value SMT expressions. * SMTChecker: Run Eldarica only when explicitly requested with `--model-checker-solvers eld`, even when it is present on the system. ### 0.8.24 (2024-01-25) Language Features: * Introduce global ``block.blobbasefee`` for retrieving the blob base fee of the current block. * Introduce global function ``blobhash(uint)`` for retrieving versioned hashes of blobs, akin to the homonymous Yul builtin. * Yul: Introduce builtin ``blobbasefee()`` for retrieving the blob base fee of the current block. * Yul: Introduce builtin ``blobhash()`` for retrieving versioned hashes of blobs associated with the transaction. * Yul: Introduce builtin ``mcopy()`` for cheaply copying data between memory areas. * Yul: Introduce builtins ``tload()`` and ``tstore()`` for transient storage access. Compiler Features: * EVM: Support for the EVM Version "Cancun". * SMTChecker: Support `bytes.concat` except when string literals are passed as arguments. * SMTChecker: Print a message that function parameter name was used instead of a concrete value in a counterexample when the concrete value found by the solver is too long to print. * Standard JSON Interface: Add experimental support to import EVM assembly in the format used by ``--asm-json``. * TypeChecker: Comparison of internal function pointers now yields a warning, as it can produce unexpected results with the legacy pipeline enabled. Bugfixes: * AST import: Fix bug when importing inline assembly with empty ``let`` variable declaration. ### 0.8.23 (2023-11-08) Important Bugfixes: * Optimizer: Fix block deduplicator bug which led to blocks which are identical apart from the contents of ``verbatim`` instructions to be treated as equivalent and thus collapsed into a single one. Compiler Features: * Commandline Interface: An empty ``--yul-optimizations`` sequence can now be always provided. * Standard JSON Interface: An empty ``optimizerSteps`` sequence can now always be provided. ### 0.8.22 (2023-10-25) Language Features: * Allow defining events at file level. Compiler Features: * Code Generator: Remove redundant overflow checks of certain ``for`` loops when the counter variable cannot overflow. * Commandline Interface: Add ``--no-import-callback`` option that prevents the compiler from loading source files not given explicitly on the CLI or in Standard JSON input. * Commandline Interface: Add an experimental ``--import-asm-json`` option that can import EVM assembly in the format used by ``--asm-json``. * Commandline Interface: Use proper severity and coloring also for error messages produced outside of the compilation pipeline. * EVM: Deprecate support for "homestead", "tangerineWhistle", "spuriousDragon" and "byzantium" EVM versions. * Parser: Remove the experimental error recovery mode (``--error-recovery`` / ``settings.parserErrorRecovery``). * SMTChecker: Support user-defined operators. * Yul Optimizer: If ``PUSH0`` is supported, favor zero literals over storing zero values in variables. * Yul Optimizer: Run the ``Rematerializer`` and ``UnusedPruner`` steps at the end of the default clean-up sequence. Bugfixes: * AST: Fix wrong initial ID for Yul nodes in the AST. * Code Generator: Fix output from via-IR code generator being dependent on which files were discovered by import callback. In some cases, a different AST ID assignment would alter the order of functions in internal dispatch, resulting in superficially different but semantically equivalent bytecode. * NatSpec: Fix internal error when requesting userdoc or devdoc for a contract that emits an event defined in a foreign contract or interface. * SMTChecker: Fix encoding error that causes loops to unroll after completion. * SMTChecker: Fix inconsistency on constant condition checks when ``while`` or ``for`` loops are unrolled before the condition check. * Yul Optimizer: Fix replacement decisions during CSE being affected by Yul variable names generated by the compiler, resulting in different (but equivalent) bytecode in some situations. ### 0.8.21 (2023-07-19) Important Bugfixes: * Code Generator: Always generate code for the expression in ``.selector`` in the legacy code generation pipeline. * Yul Optimizer: Fix ``FullInliner`` step (``i``) not preserving the evaluation order of arguments passed into inlined functions in code that is not in expression-split form (i.e. when using a custom optimizer sequence in which the step not preceded by ``ExpressionSplitter`` (``x``)). Language Features: * Allow qualified access to events from other contracts. * Relax restrictions on initialization of immutable variables. Reads and writes may now happen at any point at construction time outside of functions and modifiers. Explicit initialization is no longer mandatory. Compiler Features: * Commandline Interface: Add ``--ast-compact-json`` output in assembler mode. * Commandline Interface: Add ``--ir-ast-json`` and ``--ir-optimized-ast-json`` outputs for Solidity input, providing AST in compact JSON format for IR and optimized IR. * Commandline Interface: Respect ``--optimize-yul`` and ``--no-optimize-yul`` in compiler mode and accept them in assembler mode as well. ``--optimize --no-optimize-yul`` combination now allows enabling EVM assembly optimizer without enabling Yul optimizer. * EWasm: Remove EWasm backend. * Parser: Introduce ``pragma experimental solidity``, which will enable an experimental language mode that in particular has no stability guarantees between non-breaking releases and is not suited for production use. * SMTChecker: Add ``--model-checker-print-query`` CLI option and ``settings.modelChecker.printQuery`` JSON option to output the SMTChecker queries in the SMTLIB2 format. This requires using ``smtlib2`` solver only. * Standard JSON Interface: Add ``ast`` file-level output for Yul input. * Standard JSON Interface: Add ``irAst`` and ``irOptimizedAst`` contract-level outputs for Solidity input, providing AST in compact JSON format for IR and optimized IR. * Yul Optimizer: Remove experimental ``ReasoningBasedSimplifier`` optimization step. * Yul Optimizer: Stack-to-memory mover is now enabled by default whenever possible for via IR code generation and pure Yul compilation. Bugfixes: * Code Generator: Disallow complex expressions whose results are types, built-ins, modules or some unassignable functions. The legacy code generation pipeline would not actually evaluate them, discarding any side-effects they might have. * Code Generator: Fix not entirely deterministic order of functions in unoptimized Yul output. The choice of C++ compiler in some cases would result in different (but equivalent) bytecode (especially from native binaries vs emscripten binaries). * Commandline Interface: Fix internal error when using ``--stop-after parsing`` and requesting some of the outputs that require full analysis or compilation. * Commandline Interface: It is no longer possible to specify both ``--optimize-yul`` and ``--no-optimize-yul`` at the same time. * SMTChecker: Fix encoding of side-effects inside ``if`` and ``ternary conditional``statements in the BMC engine. * SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function. * SMTChecker: Fix generation of invalid SMT-LIB2 scripts in BMC engine with trusted mode for external calls when CHC engine times out. * SMTChecker: Fix internal error caused by incorrectly classifying external function call using function pointer as a public getter. * SMTChecker: Fix internal error caused by using external identifier to encode member access to functions that take an internal function as a parameter. * Standard JSON Interface: Fix an incomplete AST being returned when analysis is interrupted by certain kinds of fatal errors. * Type Checker: Disallow using certain unassignable function types in complex expressions. * Type Checker: Function declaration types referring to different declarations are no longer convertible to each other. * Yul Optimizer: Ensure that the assignment of memory slots for variables moved to memory does not depend on AST IDs that may depend on whether additional files are included during compilation. * Yul Optimizer: Fix ``FullInliner`` step not ignoring code that is not in expression-split form. * Yul Optimizer: Fix optimized IR being unnecessarily passed through the Yul optimizer again before bytecode generation. AST Changes: * AST: Add the ``experimentalSolidity`` field to the ``SourceUnit`` nodes, which indicate whether the experimental parsing mode has been enabled via ``pragma experimental solidity``. ### 0.8.20 (2023-05-10) Compiler Features: * Assembler: Use ``push0`` for placing ``0`` on the stack for EVM versions starting from "Shanghai". This decreases the deployment and runtime costs. * EVM: Set default EVM version to "Shanghai". * EVM: Support for the EVM Version "Shanghai". * NatSpec: Add support for NatSpec documentation in ``enum`` definitions. * NatSpec: Add support for NatSpec documentation in ``struct`` definitions. * NatSpec: Include NatSpec from events that are emitted by a contract but defined outside of it in userdoc and devdoc output. * Optimizer: Re-implement simplified version of ``UnusedAssignEliminator`` and ``UnusedStoreEliminator``. It can correctly remove some unused assignments in deeply nested loops that were ignored by the old version. * Parser: Unary plus is no longer recognized as a unary operator in the AST and triggers an error at the parsing stage (rather than later during the analysis). * SMTChecker: Add CLI option ``--model-checker-bmc-loop-iterations`` and a JSON option ``settings.modelChecker.bmcLoopIterations`` that specify how many loop iterations the BMC engine should unroll. Note that false negatives are possible when unrolling loops. This is due to the possibility that bmc loop iteration setting is less than actual number of iterations needed to complete a loop. * SMTChecker: Group all messages about unsupported language features in a single warning. The CLI option ``--model-checker-show-unsupported`` and the JSON option ``settings.modelChecker.showUnsupported`` can be enabled to show the full list. * SMTChecker: Properties that are proved safe are now reported explicitly at the end of analysis. By default, only the number of safe properties is shown. The CLI option ``--model-checker-show-proved-safe`` and the JSON option ``settings.modelChecker.showProvedSafe`` can be enabled to show the full list of safe properties. * Standard JSON Interface: Add experimental support for importing ASTs via Standard JSON. * Yul EVM Code Transform: If available, use ``push0`` instead of ``codesize`` to produce an arbitrary value on stack in order to create equal stack heights between branches. Bugfixes: * ABI: Include events in the ABI that are emitted by a contract but defined outside of it. * Immutables: Disallow initialization of immutables in try/catch statements. * SMTChecker: Fix false positives in ternary operators that contain verification targets in its branches, directly or indirectly. AST Changes: * AST: Add the ``internalFunctionIDs`` field to the AST nodes of contracts containing IDs of functions that may be called via the internal dispatch. The field is a map from function AST IDs to internal dispatch function IDs. These IDs are always generated, but they are only used in via-IR code generation. * AST: Add the ``usedEvents`` field to ``ContractDefinition`` which contains the AST IDs of all events emitted by the contract as well as all events defined and inherited by the contract. ### 0.8.19 (2023-02-22) Language Features: * Allow defining custom operators for user-defined value types via ``using {f as +} for T global`` syntax. Compiler Features: * SMTChecker: New trusted mode that assumes that any compile-time available code is the actual used code even in external calls. This can be used via the CLI option ``--model-checker-ext-calls trusted`` or the JSON field ``settings.modelChecker.extCalls: "trusted"``. Bugfixes: * Assembler: Avoid duplicating subassembly bytecode where possible. * Code Generator: Avoid including references to the deployed label of referenced functions if they are called right away. * ContractLevelChecker: Properly distinguish the case of missing base constructor arguments from having an unimplemented base function. * SMTChecker: Fix internal error caused by unhandled ``z3`` expressions that come from the solver when bitwise operators are used. * SMTChecker: Fix internal error when using the custom NatSpec annotation to abstract free functions. * TypeChecker: Also allow external library functions in ``using for``. AST Changes: * AST: Add ``function`` field to ``UnaryOperation`` and ``BinaryOperation`` AST nodes. ``functionList`` in ``UsingForDirective`` AST nodes will now contain ``operator`` and ``definition`` members instead of ``function`` when the list entry defines an operator. ### 0.8.18 (2023-02-01) Language Features: * Allow named parameters in mapping types. Compiler Features: * Commandline Interface: Add ``--no-cbor-metadata`` that skips CBOR metadata from getting appended at the end of the bytecode. * Commandline Interface: Return exit code ``2`` on uncaught exceptions. * EVM: Deprecate ``block.difficulty`` and disallow ``difficulty()`` in inline assembly for EVM versions >= paris. The change is due to the renaming introduced by [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399). * EVM: Introduce ``block.prevrandao`` in Solidity and ``prevrandao()`` in inline assembly for EVM versions >= paris. * EVM: Set the default EVM version to "Paris". * EVM: Support for the EVM version "Paris". * Language Server: Add basic document hover support. * Natspec: Add event Natspec inheritance for devdoc. * Optimizer: Added optimization rule ``and(shl(X, Y), shl(X, Z)) => shl(X, and(Y, Z))``. * Parser: More detailed error messages about invalid version pragmas. * SMTChecker: Make ``z3`` the default solver for the BMC and CHC engines instead of all solvers. * SMTChecker: Support Eldarica as a Horn solver for the CHC engine when using the CLI option ``--model-checker-solvers eld``. The binary ``eld`` must be available in the system. * Solidity Upgrade Tool: Remove ``solidity-upgrade`` tool. * Standard JSON: Add a boolean field ``settings.metadata.appendCBOR`` that skips CBOR metadata from getting appended at the end of the bytecode. * TypeChecker: Warn when using deprecated builtin ``selfdestruct``. * Yul EVM Code Transform: Generate more optimal code for user-defined functions that always terminate a transaction. No return labels will be pushed for calls to functions that always terminate. * Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string. * Yul Optimizer: Eliminate ``keccak256`` calls if the value was already calculated by a previous call and can be reused. Bugfixes: * Parser: Disallow several ``indexed`` attributes for the same event parameter. * Parser: Disallow usage of the ``indexed`` attribute for modifier parameters. * SMTChecker: Fix display error for negative integers that are one more than powers of two. * SMTChecker: Fix internal error on chain assignments using static fully specified state variables. * SMTChecker: Fix internal error on multiple wrong SMTChecker natspec entries. * SMTChecker: Fix internal error when a public library function is called internally. * SMTChecker: Fix internal error when deleting struct member of function type. * SMTChecker: Fix internal error when using user-defined types as mapping indices or struct members. * SMTChecker: Improved readability for large integers that are powers of two or almost powers of two in error messages. * TypeChecker: Fix bug where private library functions could be attached with ``using for`` outside of their declaration scope. * Yul Optimizer: Hash hex and decimal literals according to their value instead of their representation, improving the detection of equivalent functions. ### 0.8.17 (2022-09-08) Important Bugfixes: * Yul Optimizer: Prevent the incorrect removal of storage writes before calls to Yul functions that conditionally terminate the external EVM call. Compiler Features: * Code Generator: More efficient overflow checks for multiplication. * Language Server: Analyze all files in a project by default (can be customized by setting ``'file-load-strategy'`` to ``'directly-opened-and-on-import'`` in LSP settings object). * Yul Optimizer: Simplify the starting offset of zero-length operations to zero. Bugfixes: * Type Checker: Fix internal compiler error on tuple assignments with invalid left-hand side. * Yul IR Code Generation: Fix internal compiler error when accessing the ``.slot`` member of a mapping through a storage reference in inline assembly. Build System: * Allow disabling pedantic warnings and do not treat warnings as errors during compiler build when ``-DPEDANTIC=OFF`` flag is passed to CMake. * Update emscripten to version 3.1.19. ### 0.8.16 (2022-08-08) Important Bugfixes: * Code Generation: Fix data corruption that affected ABI-encoding of calldata values represented by tuples: structs at any nesting level; argument lists of external functions, events and errors; return value lists of external functions. The 32 leading bytes of the first dynamically-encoded value in the tuple would get zeroed when the last component contained a statically-encoded array. Compiler Features: * Code Generator: More efficient code for checked addition and subtraction. * TypeChecker: Support using library constants in initializers of other constants. * Yul IR Code Generation: Improved copy routines for arrays with packed storage layout. * Yul Optimizer: Add rule to convert ``mod(add(X, Y), A)`` into ``addmod(X, Y, A)``, if ``A`` is a power of two. * Yul Optimizer: Add rule to convert ``mod(mul(X, Y), A)`` into ``mulmod(X, Y, A)``, if ``A`` is a power of two. Bugfixes: * Commandline Interface: Disallow the following options outside of the compiler mode: ``--via-ir``,``--metadata-literal``, ``--metadata-hash``, ``--model-checker-show-unproved``, ``--model-checker-div-mod-no-slacks``, ``--model-checker-engine``, ``--model-checker-invariants``, ``--model-checker-solvers``, ``--model-checker-timeout``, ``--model-checker-contracts``, ``--model-checker-targets``. * Type Checker: Fix compiler crash on tuple assignments involving certain patterns with unary tuples on the left-hand side. * Type Checker: Fix compiler crash when ``abi.encodeCall`` received a tuple expression instead of an inline tuple. * Type Checker: Fix null dereference in ``abi.encodeCall`` type checking of free function. ### 0.8.15 (2022-06-15) Important Bugfixes: * Code Generation: Avoid writing dirty bytes to storage when copying ``bytes`` arrays. * Yul Optimizer: Keep all memory side-effects of inline assembly blocks. Language Features: * Add `E.selector` for a non-anonymous event `E` to access the 32-byte selector topic. Compiler Features: * Language Server: Add rudimentary support for semantic highlighting. * Language Server: Adds support for configuring ``include-paths`` JSON settings object that can be passed during LSP configuration stage. * Language Server: Always add ``{project_root}/node_modules`` to include search paths. * Type Checker: Warn about assignments involving multiple pushes to storage ``bytes`` that may invalidate references. * Yul Optimizer: Improve inlining heuristics for via IR code generation and pure Yul compilation. Bugfixes: * ABI Encoder: When encoding an empty string coming from storage do not add a superfluous empty slot for data. * Common Subexpression Eliminator: Process assembly items in chunks with maximum size of 2000. It helps to avoid extremely time-consuming searches during code optimization. * DocString Parser: Fix ICE caused by an immutable struct with mapping. * Yul IR Code Generation: More robust cleanup in corner cases during memory to storage copies. * Yul Optimizer: Do not remove ``returndatacopy`` in cases in which it might perform out-of-bounds reads that unconditionally revert as out-of-gas. Previously, any ``returndatacopy`` that wrote to memory that was never read from was removed without accounting for the out-of-bounds condition. ### 0.8.14 (2022-05-17) Important Bugfixes: * ABI Encoder: When ABI-encoding values from calldata that contain nested arrays, correctly validate the nested array length against ``calldatasize()`` in all cases. * Override Checker: Allow changing data location for parameters only when overriding external functions. Compiler Features: * Assembly-Json Exporter: Include source list in `sourceList` field. * Commandline Interface: Option ``--pretty-json`` works also with the following options: ``--abi``, ``--asm-json``, ``--ast-compact-json``, ``--devdoc``, ``--storage-layout``, ``--userdoc``. * Language Server: Allow full filesystem access to language server. * Peephole Optimizer: Remove operations without side effects before simple terminations. * SMTChecker: Support ``abi.encodeCall`` taking into account the called selector. Bugfixes: * Assembly-Json Exporter: Fix assembly json export to store jump types of operations in `jumpType` field instead of `value`. * SMTChecker: Fix ABI compatibility with z3 >=4.8.16. * SMTChecker: Fix bug when z3 is selected but not available at runtime. * Type Checker: Properly check restrictions of ``using ... global`` in conjunction with libraries. * TypeChecker: Convert parameters of function type to how they would be called for ``abi.encodeCall``. ### 0.8.13 (2022-03-16) Important Bugfixes: * Code Generator: Correctly encode literals used in ``abi.encodeCall`` in place of fixed bytes arguments. Language Features: * General: Allow annotating inline assembly as memory-safe to allow optimizations and stack limit evasion that rely on respecting Solidity's memory model. * General: ``using M for Type;`` is allowed at file level and ``M`` can now also be a brace-enclosed list of free functions or library functions. * General: ``using ... for T global;`` is allowed at file level where the user-defined type ``T`` has been defined, resulting in the effect of the statement being available everywhere ``T`` is available. Compiler Features: * Commandline Interface: Allow the use of ``--via-ir`` in place of ``--experimental-via-ir``. * Compilation via Yul IR is no longer marked as experimental. * JSON-AST: Added selector field for errors and events. * Language Server: Implements goto-definition. * Peephole Optimizer: Optimize comparisons in front of conditional jumps and conditional jumps across a single unconditional jump. * Yul EVM Code Transform: Avoid unnecessary ``pop``s on terminating control flow. * Yul IR Code Generation: When the result of an external call is statically-sized, ignore any returndata past the size expected by the compiler. * Yul Optimizer: Remove ``sstore`` and ``mstore`` operations that are never read from. Bugfixes: * General: Fix internal error for locales with unusual capitalization rules. Locale set in the environment is now completely ignored. * Type Checker: Fix incorrect type checker errors when importing overloaded functions. * Yul IR Code Generation: Optimize embedded creation code with correct settings. This fixes potential mismatches between the constructor code of a contract compiled in isolation and the bytecode in ``type(C).creationCode``, resp. the bytecode used for ``new C(...)``. ### 0.8.12 (2022-02-16) Language Features: * General: Add equality-comparison operators for external function types. * General: Support ``ContractName.functionName`` for ``abi.encodeCall``, in addition to external function pointers. Compiler Features: * Commandline Interface: Event and error signatures are also returned when using ``--hashes``. * Yul Optimizer: Remove ``mstore`` and ``sstore`` operations if the slot already contains the same value. * Yul: Emit immutable references for pure yul code when requested. Bugfixes: * Antlr Grammar: Allow builtin names in ``yulPath`` to support ``.address`` in function pointers. * Code Generator: Fix internal error when accessing the members of external functions occupying more than two stack slots. * Code Generator: Fix internal error when doing an explicit conversion from ``string calldata`` to ``bytes``. * Control Flow Graph: Perform proper virtual lookup for modifiers for uninitialized variable and unreachable code analysis. * General: ``string.concat`` now properly takes strings as arguments and returns ``string memory``. It was accidentally introduced as a copy of ``bytes.concat`` before. * Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the derived contract contains immutable variables. * Inheritance: Consider functions in all ancestors during override analysis. * IR Generator: Add missing cleanup during the conversion of fixed bytes types to smaller fixed bytes types. * IR Generator: Add missing cleanup for indexed event arguments of value type. * IR Generator: Fix internal error when copying reference types in calldata and storage to struct or array members in memory. * IR Generator: Fix IR syntax error when copying storage arrays of structs containing functions. * Natspec: Fix internal error when overriding a struct getter with a Natspec-documented return value and the name in the struct is different. * Type Checker: Fix internal error when a constant variable declaration forward references a struct. * Yul EVM Code Transform: Improved stack shuffling in corner cases. Solc-Js: * The wrapper now requires at least nodejs v10. * The code has been ported to TypeScript. Build System: * Emscripten builds store the embedded WebAssembly binary in LZ4 compressed format and transparently decompress on loading. ### 0.8.11 (2021-12-20) Language Features: * General: New builtin function ``abi.encodeCall(functionPointer, (arg1, arg2, ...))`` that type-checks the arguments and returns the ABI-encoded function call data. Compiler Features: * Commandline Interface: Add ``--lsp`` option to get ``solc`` to act as a Language Server (LSP) communicating over stdio. Bugfixes: * Code Generator: Fix a crash when using ``@use-src`` and compiling from Yul to ewasm. * SMTChecker: Fix internal error when an unsafe target is solved more than once and the counterexample messages are different. * SMTChecker: Fix soundness of assigned storage/memory local pointers that were not erasing enough knowledge. * Fix internal error when a function has a calldata struct argument with an internal type inside. * IR Generator: Fix IR syntax error when copying storage arrays of functions. ### 0.8.10 (2021-11-09) Language Features: * Inline Assembly: Support ``.address`` and ``.selector`` on external function pointers to access their address and function selector. Compiler Features: * Code Generator: Skip existence check for external contract if return data is expected. In this case, the ABI decoder will revert if the contract does not exist. * Commandline Interface: Accept nested brackets in step sequences passed to ``--yul-optimizations``. * Commandline Interface: Add ``--debug-info`` option for selecting how much extra debug information should be included in the produced EVM assembly and Yul code. * Commandline Interface: Support ``--asm``, ``--bin``, ``--ir-optimized``, ``--ewasm`` and ``--ewasm-ir`` output selection options in assembler mode. * Commandline Interface: Use different colors when printing errors, warnings and infos. * JSON AST: Set absolute paths of imports earlier, in the ``parsing`` stage. * SMTChecker: Output values for ``block.*``, ``msg.*`` and ``tx.*`` variables that are present in the called functions. * SMTChecker: Report contract invariants and reentrancy properties. This can be enabled via the CLI option ``--model-checker-invariants`` or the Standard JSON option ``settings.modelChecker.invariants``. * Standard JSON: Accept nested brackets in step sequences passed to ``settings.optimizer.details.yulDetails.optimizerSteps``. * Standard JSON: Add ``settings.debug.debugInfo`` option for selecting how much extra debug information should be included in the produced EVM assembly and Yul code. * Yul EVM Code Transform: Switch to new optimized code transform when compiling via Yul with enabled optimizer. * Yul Optimizer: Take control-flow side-effects of user-defined functions into account in various optimizer steps. Bugfixes: * Code Generator: Fix constructor source mappings for immutables. * Commandline Interface: Disallow ``--error-recovery`` option outside of the compiler mode. * Commandline Interface: Don't return zero exit code when writing linked files to disk fails. * Commandline Interface: Fix extra newline character being appended to sources passed through standard input, affecting their hashes. * Commandline Interface: Report output selection options unsupported by the selected input mode instead of ignoring them. * Commandline Interface: When linking only accept exact matches for library names passed to the ``--libraries`` option. Library names not prefixed with a file name used to match any library with that name. * SMTChecker: Fix internal error in magic type access (``block``, ``msg``, ``tx``). * SMTChecker: Fix internal error in the CHC engine when passing gas in the function options. * TypeChecker: Fix internal error when using arrays and structs with user defined value types before declaration. * TypeChecker: Fix internal error when using user defined value types in public library functions. * TypeChecker: Improved error message for constant variables with (nested) mapping types. * Yul Assembler: Fix internal error when function names are not unique. * Yul IR Generator: Do not output empty switches/if-bodies for empty contracts. Important Bugfixes in Experimental Features: * Yul IR Generator: Changes to function return variables referenced in modifier invocation arguments were not properly forwarded if there was more than one return variable. Build System: * Pass linker-only emscripten options only when linking. * Remove obsolete compatibility workaround for emscripten builds. * Update emscripten to version 2.0.33. ### 0.8.9 (2021-09-29) Important Bugfixes: * Immutables: Properly perform sign extension on signed immutables. * User Defined Value Type: Fix storage layout of user defined value types for underlying types shorter than 32 bytes. Bugfixes: * AST: Export ``canonicalName`` for ``UserDefinedValueTypeDefinition`` and ``ContractDefinition``. ### 0.8.8 (2021-09-27) Language Features: * Inheritance: A function that overrides only a single interface function does not require the ``override`` specifier. * Type System: Support ``type(E).min`` and ``type(E).max`` for enums. * User Defined Value Type: allows creating a zero cost abstraction over a value type with stricter type requirements. Compiler Features: * Commandline Interface: Add ``--include-path`` option for specifying extra directories that may contain importable code (e.g. packaged third-party libraries). * Commandline Interface: Do not implicitly run evm bytecode generation unless needed for the requested output. * Commandline Interface: Normalize paths specified on the command line and make them relative for files located inside base path and/or include paths. * Immutable variables can be read at construction time once they are initialized. * SMTChecker: Add constraints to better correlate ``address(this).balance`` and ``msg.value``. * SMTChecker: Support constants via modules. * SMTChecker: Support low level ``call`` as external calls to unknown code. * SMTChecker: Support the ``value`` option for external function calls. * SMTChecker: Support user defined value types. Bugfixes: * Code Generator: Fix ICE on assigning to calldata structs and statically-sized calldata arrays in inline assembly. * Code Generator: Use stable source order for ABI functions. * Commandline Interface: Disallow the ``--experimental-via-ir`` option in Standard JSON, Assembler and Linker modes. * Commandline Interface: Fix resolution of paths whitelisted with ``--allowed-paths`` or implicitly due to base path, remappings and files being compiled. Correctly handle paths that do not match imports exactly due to being relative, non-normalized or empty. * Commandline Interface: Report optimizer options as invalid in Standard JSON and linker modes instead of ignoring them. * Name Resolver: Fix that when importing an aliased symbol using ``import {AliasedName} from "a.sol"`` it would use the original name of the symbol and not the aliased one. * Opcode Optimizer: Prevent the optimizer from running multiple times to avoid potential bytecode differences for referenced code. * Parser: Properly check for multiple SPDX license identifiers next to each other and validate them. * SMTChecker: Fix BMC's constraints regarding internal functions. * SMTChecker: Fix false negative caused by ``push`` on storage array references returned by internal functions. * SMTChecker: Fix false positive in external calls from constructors. * SMTChecker: Fix internal error on some multi-source uses of ``abi.*``, cryptographic functions and constants. * Standard JSON: Fix non-fatal errors in Yul mode being discarded if followed by a fatal error. * Type Checker: Correct wrong error message in inline assembly complaining about ``.slot`` or ``.offset`` not valid when actually ``.length`` was used. * Type Checker: Disallow modifier declarations and definitions in interfaces. * Yul Optimizer: Fix a crash in LoadResolver, when ``keccak256`` has particular non-identifier arguments. ### 0.8.7 (2021-08-11) Language Features: * Introduce global ``block.basefee`` for retrieving the base fee of the current block. * Yul: Introduce builtin ``basefee()`` for retrieving the base fee of the current block. Compiler Features: * AssemblyStack: Also run opcode-based optimizer when compiling Yul code. * Commandline Interface: option ``--pretty-json`` works also with ``--standard--json``. * EVM: Set the default EVM version to "London". * SMTChecker: Do not check underflow and overflow by default. * SMTChecker: Unproved targets are hidden by default, and the SMTChecker only states how many unproved targets there are. They can be listed using the command line option ``--model-checker-show-unproved`` or the JSON option ``settings.modelChecker.showUnproved``. * SMTChecker: new setting to enable/disable encoding of division and modulo with slack variables. The command line option is ``--model-checker-div-mod-slacks`` and the JSON option is ``settings.modelChecker.divModWithSlacks``. * Yul EVM Code Transform: Also pop unused argument slots for functions without return variables (under the same restrictions as for functions with return variables). * Yul EVM Code Transform: Do not reuse stack slots that immediately become unreachable. * Yul Optimizer: Move function arguments and return variables to memory with the experimental Stack Limit Evader (which is not enabled by default). Bugfixes: * Code Generator: Fix crash when passing an empty string literal to ``bytes.concat()``. * Code Generator: Fix internal compiler error when calling functions bound to calldata structs and arrays. * Code Generator: Fix internal compiler error when passing a 32-byte hex literal or a zero literal to ``bytes.concat()`` by disallowing such literals. * Commandline Interface: Apply ``--optimizer-runs`` option in assembly / yul mode. * Commandline Interface: Fix crash when a directory path is passed to ``--standard-json``. * Commandline Interface: Read JSON from standard input when ``--standard-json`` gets ``-`` as a file name. * Standard JSON: Include source location for errors in files with empty name. * Type Checker: Fix internal error and prevent static calls to unimplemented modifiers. * Yul Code Generator: Fix internal compiler error when using a long literal with bitwise negation. * Yul Code Generator: Fix source location references for calls to builtin functions. * Yul Parser: Fix source location references for ``if`` statements. ### 0.8.6 (2021-06-22) Language Features: * Yul: Special meaning of ``".metadata"`` data object in Yul object. Bugfixes: * Control Flow Graph: Fix incorrectly reported unreachable code. * Solc-Js: When running ``solcjs`` without the ``--optimize`` flag, use ``settings.optimizer.enabled=false`` in Standard JSON instead of omitting the key. * Standard JSON: Omitting ``settings.optimizer.enabled`` was not equivalent to setting it to ``false``. It meant disabling also the peephole optimizer and jumpdest remover which by default still run with ``enabled=false``. ### 0.8.5 (2021-06-10) Language Features: * Allowing conversion from ``bytes`` and ``bytes`` slices to ``bytes1``/.../``bytes32``. * Yul: Add ``verbatim`` builtin function to inject arbitrary bytecode. Compiler Features: * Code Generator: Insert helper functions for panic codes instead of inlining unconditionally. This can reduce costs if many panics (checks) are inserted, but can increase costs where few panics are used. * EVM: Set the default EVM version to "Berlin". * SMTChecker: Function definitions can be annotated with the custom Natspec tag ``custom:smtchecker abstract-function-nondet`` to be abstracted by a nondeterministic value when called. * Standard JSON / combined JSON: New artifact "functionDebugData" that contains bytecode offsets of entry points of functions and potentially more information in the future. * Yul Optimizer: Evaluate ``keccak256(a, c)``, when the value at memory location ``a`` is known at compile time and ``c`` is a constant ``<= 32``. Bugfixes: * AST: Do not output value of Yul literal if it is not a valid UTF-8 string. * Code Generator: Fix internal error when function arrays are assigned to storage variables and the function types can be implicitly converted but are not identical. * Code Generator: Fix internal error when super would have to skip an unimplemented function in the virtual resolution order. * Control Flow Graph: Assume unimplemented modifiers use a placeholder. * Control Flow Graph: Take internal calls to functions that always revert into account for reporting unused or unassigned variables. * Function Call Graph: Fix internal error connected with circular constant references. * Name Resolver: Do not issue shadowing warning if the shadowing name is not directly accessible. * Natspec: Allow multiple ``@return`` tags on public state variable documentation. * SMTChecker: Fix internal error on conversion from ``bytes`` to ``fixed bytes``. * SMTChecker: Fix internal error on external calls from the constructor. * SMTChecker: Fix internal error on struct constructor with fixed bytes member initialized with string literal. * Source Locations: Properly set source location of scoped blocks. * Standard JSON: Properly allow the ``inliner`` setting under ``settings.optimizer.details``. * Type Checker: Fix internal compiler error related to having mapping types in constructor parameter for abstract contracts. * Type Checker: Fix internal compiler error when attempting to use an invalid external function type on pre-byzantium EVMs. * Type Checker: Fix internal compiler error when overriding receive ether function with one having different parameters during inheritance. * Type Checker: Make errors about (nested) mapping type in event or error parameter into fatal type errors. * Type Checker: Fix internal compiler error when overriding an implemented modifier with an unimplemented one. AST Changes: * Add member `hexValue` for Yul string and hex literals. ### 0.8.4 (2021-04-21) Important Bugfixes: * ABI Decoder V2: For two-dimensional arrays and specially crafted data in memory, the result of ``abi.decode`` can depend on data elsewhere in memory. Calldata decoding is not affected. Language Features: * Assembly / Yul: Allow hex string literals. * Possibility to use ``bytes.concat`` with variable number of ``bytes`` and ``bytesNN`` arguments which behaves as a restricted version of `abi.encodePacked` with a more descriptive name. * Support custom errors via the ``error`` keyword and introduce the ``revert`` statement. Compiler Features: * Analysis: Properly detect circular references to the bytecode of other contracts across all function calls. * Commandline Interface: Model checker option ``--model-checker-targets`` also accepts ``outOfBounds``. * Commandline Interface: New model checker option ``--model-checker-contracts`` allows users to select which contracts should be analyzed as the most derived. * Low-Level Inliner: Inline ordinary jumps to small blocks and jumps to small blocks that terminate. * NatSpec: Allow ``@notice`` tag on non-public state variables and local variable declarations. The documentation will only be part of the AST, under the field ``documentation``. * SMTChecker: Deprecate ``pragma experimental SMTChecker;`` and set default model checker engine to ``none``. * SMTChecker: Report local variables in CHC counterexamples. * SMTChecker: Report out of bounds index access for arrays and fixed bytes. * SMTChecker: Support file level functions and constants. * Standard JSON: Model checker option ``settings.modelChecker.targets`` also accepts ``outOfBounds``. * Standard JSON: Model checker option ``settings.modelChecker.targets`` takes an array of string targets instead of string of comma separated targets. * Standard JSON: New model checker option ``settings.modelChecker.contracts`` allows users to select which contracts should be analyzed as the most derived. * Yul EVM Code Transform: Stack Optimization: Reuse slots of unused function arguments and defer allocating stack slots for return variables until after expression statements and assignments that do not reference them. * Yul Optimizer: Added a new step FunctionSpecializer, that specializes a function with its literal arguments. Bugfixes: * Antlr Grammar: Fix parsing of import paths involving properly distinguishing between empty and non-empty string literals in general. * AST Output: Fix ``kind`` field of ``ModifierInvocation`` for base constructor calls. * Commandline interface: Fix internal error when printing AST and using ``--base-path`` or ``file://`` prefix in imports. * Commandline interface: Fix standard input bypassing allowed path checks. * Natspec: Fix internal error related to the `@returns` documentation for a public state variable overriding a function. * SMTChecker: Fix false positive and false negative on ``push`` as LHS of a compound assignment. * SMTChecker: Fix false positive in contracts that cannot be deployed. * SMTChecker: Fix internal error on public getter returning dynamic data on older EVM versions where these are not available. * SMTChecker: Fix internal error on try-catch with function call in catch block. * Type Checker: Fix missing error when events are used without an emit statement. AST Changes: * New property for ``ContractDefinition`` nodes: ``usedErrors`` lists AST IDs of all errors used by the contract (even if defined outside). ### 0.8.3 (2021-03-23) Important Bugfixes: * Optimizer: Fix bug on incorrect caching of Keccak-256 hashes. Compiler Features: * Command Line Interface: Drop experimental support for ``--machine evm15``. * Optimizer: Try to move ``and`` with constant inside ``or`` to improve storage writes of small types. * Optimizer: Replace multiplications and divisions with powers of two by shifts. Bugfixes: * AST Import: For constructors, a public visibility is ignored during importing. * Error Reporter: Fix handling of carriage return. * SMTChecker: Fix internal error in BMC on resolving virtual functions inside branches. * SMTChecker: Fix internal error on ``array.pop`` nested inside 1-tuple. * SMTChecker: Fix internal error on ``FixedBytes`` constant initialized with string literal. * SMTChecker: Fix internal error on array slices. * SMTChecker: Fix internal error on calling public getter on a state variable of type array (possibly nested) of structs. * SMTChecker: Fix internal error on pushing to ``string`` casted to ``bytes``. * SMTChecker: Fix bug in virtual functions called by constructors. AST Changes: * ModifierInvocation: Add ``kind`` field which can be ``modifierInvocation`` or ``baseConstructorSpecifier``. ### 0.8.2 (2021-03-02) Compiler Features: * AST: Export NatSpec comments above each statement as their documentation. * Inline Assembly: Do not warn anymore about variables or functions being shadowed by EVM opcodes. * NatSpec: Provide source locations for parsing errors. * Optimizer: Simple inlining when jumping to small blocks that jump again after a few side-effect free opcodes. * NatSpec: Allow and export all tags that start with ``@custom:``. Bugfixes: * AST: Added ``referencedDeclaration`` for enum members. * Code Generator: Fix internal error when functions are passed as parameters of other callables, when the function types can be implicitly converted, but not identical. * Parser: Properly parse ``.address`` in some situations. * SMTChecker: Fix missing type constraints on block and transaction variables in the deployment phase. * Type Checker: Fix internal error when override specifier is not a contract. * Type Checker: Make function-hash collision errors into fatal type errors. AST Changes: * Adds ``nameLocation`` to declarations to represent the exact location of the symbolic name. * Removed the redundant function type "bytearraypush" - replaced by "arraypush". * Support field ``documentation`` to hold NatSpec comments above each statement. ### 0.8.1 (2021-01-27) Language Features: * Possibility to use ``catch Panic(uint code)`` to catch a panic failure from an external call. Compiler Features: * Code Generator: Reduce the cost of ``
.code.length`` by using ``extcodesize`` directly. * Command Line Interface: Allow ``=`` as separator between library name and address in ``--libraries`` commandline option. * Command Line Interface: New option ``--model-checker-targets`` allows specifying which targets should be checked. The valid options are ``all``, ``constantCondition``, ``underflow``, ``overflow``, ``divByZero``, ``balance``, ``assert``, ``popEmptyArray``, where the default is ``all``. Multiple targets can be chosen at the same time, separated by a comma without spaces: ``underflow,overflow,assert``. * Command Line Interface: Only accept library addresses with a prefix of ``0x`` in ``--libraries`` commandline option. * Optimizer: Add rule to replace ``iszero(sub(x,y))`` by ``eq(x,y)``. * Parser: Report meaningful error if parsing a version pragma failed. * SMTChecker: Output internal and trusted external function calls in a counterexample's transaction trace. * SMTChecker: Show ``msg.value`` in counterexample transaction traces when greater than 0. * SMTChecker: Show contract name in counterexample function call. * SMTChecker: Support ABI functions as uninterpreted functions. * SMTChecker: Support try/catch statements. * SMTChecker: Synthesize untrusted functions called externally. * SMTChecker: Use checked arithmetic by default and support ``unchecked`` blocks. * Standard JSON: New option ``modelCheckerSettings.targets`` allows specifying which targets should be checked. The valid options are ``all``, ``constantCondition``, ``underflow``, ``overflow``, ``divByZero``, ``balance``, ``assert``, ``popEmptyArray``, where the default is ``all``. Multiple targets can be chosen at the same time, separated by a comma without spaces: ``underflow,overflow,assert``. Bugfixes: * Code Generator: Fix length check when decoding malformed error data in catch clause. * Control Flow Graph: Fix missing error caused by read from/write to uninitialized variables. * SMTChecker: Fix false negatives in overriding modifiers and functions. * SMTChecker: Fix false negatives in the presence of inline assembly. * SMTChecker: Fix false negatives when analyzing external function calls. * SMTChecker: Fix internal error on ``block.chainid``. * SMTChecker: Fix internal error on pushing string literal to ``bytes`` array. * SMTChecker: Fix missing type constraints for block variables. * Type Checker: Fix infinite loop when accessing circular constants from inline assembly. * Type Checker: Fix internal error caused by constant structs containing mappings. * Type System: Disallow implicit conversion from ``uintN`` to ``intM`` when ``M > N``, and by extension, explicit conversion between the same types is also disallowed. Build System: * Update the soljson.js build to emscripten 2.0.12 and boost 1.75.0. ### 0.8.0 (2020-12-16) Breaking Changes: * Code Generator: All arithmetic is checked by default. These checks can be disabled using ``unchecked { ... }``. * Code Generator: Cause a panic if a byte array in storage is accessed whose length is encoded incorrectly. * Code Generator: Use ``revert`` with error signature ``Panic(uint256)`` and error codes instead of invalid opcode on failing assertions. * Command Line Interface: JSON fields `abi`, `devdoc`, `userdoc` and `storage-layout` are now sub-objects rather than strings. * Command Line Interface: Remove the ``--old-reporter`` option. * Command Line Interface: Remove the legacy ``--ast-json`` option. Only the ``--ast-compact-json`` option is supported now. * General: Enable ABI coder v2 by default. * General: Remove global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4``. * Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``. * Scanner: Remove support for the ``\b``, ``\f``, and ``\v`` escape sequences. * Standard JSON: Remove the ``legacyAST`` option. * Type Checker: Function call options can only be given once. * Type System: Declarations with the name ``this``, ``super`` and ``_`` are disallowed, with the exception of public functions and events. * Type System: Disallow ``msg.data`` in ``receive()`` function. * Type System: Disallow ``type(super)``. * Type System: Disallow enums with more than 256 members. * Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type. * Type System: Disallow the ``byte`` type. It was an alias to ``bytes1``. * Type System: Explicit conversion to ``address`` type always returns a non-payable ``address`` type. In particular, ``address(u)``, ``address(b)``, ``address(c)`` and ``address(this)`` have the type ``address`` instead of ``address payable`` (Here ``u``, ``b``, and ``c`` are arbitrary variables of type ``uint160``, ``bytes20`` and contract type respectively.) * Type System: Explicit conversions between two types are disallowed if it changes more than one of sign, width or kind at the same time. * Type System: Explicit conversions from literals to enums are only allowed if the value fits in the enum. * Type System: Explicit conversions from literals to integer type is as strict as implicit conversions. * Type System: Introduce ``address(...).code`` to retrieve the code as ``bytes memory``. The size can be obtained via ``address(...).code.length``, but it will currently always include copying the code. * Type System: Introduce ``block.chainid`` for retrieving the current chain id. * Type System: Support ``address(...).codehash`` to retrieve the codehash of an account. * Type System: The global variables ``tx.origin`` and ``msg.sender`` have type ``address`` instead of ``address payable``. * Type System: Unary negation can only be used on signed integers, not on unsigned integers. * View Pure Checker: Mark ``chainid`` as view. * Yul: Disallow the use of reserved identifiers, such as EVM instructions, even if they are not available in the given dialect / EVM version. * Yul: The ``assignimmutable`` builtin in the "EVM with objects" dialect takes the base offset of the code to modify as an additional argument. Language Features: * Super constructors can now be called using the member notation e.g. ``M.C(123)``. Bugfixes: * Type Checker: Perform proper truncating integer arithmetic when using constants in array length expressions. AST Changes: * New AST Node ``IdentifierPath`` replacing in many places the ``UserDefinedTypeName``. * New AST Node ``UncheckedBlock`` used for ``unchecked { ... }``. ### 0.7.6 (2020-12-16) Language Features: * Code generator: Support conversion from calldata slices to memory and storage arrays. * Code generator: Support copying dynamically encoded structs from calldata to memory. * Code generator: Support copying of nested arrays from calldata to memory. * Scanner: Generate a parser error when comments or unicode strings contain an unbalanced or underflowing set of unicode direction override markers (LRO, RLO, LRE, RLE, PDF). * The fallback function can now also have a single ``calldata`` argument (equaling ``msg.data``) and return ``bytes memory`` (which will not be ABI-encoded but returned as-is). * Wasm backend: Add ``i32.select`` and ``i64.select`` instructions. Compiler Features: * Build System: Optionally support dynamic loading of Z3 and use that mechanism for Linux release builds. * Code Generator: Avoid memory allocation for default value if it is not used. * SMTChecker: Apply constant evaluation on binary arithmetic expressions. * SMTChecker: Create underflow and overflow verification targets for increment/decrement in the CHC engine. * SMTChecker: Report struct values in counterexamples from CHC engine. * SMTChecker: Support early returns in the CHC engine. * SMTChecker: Support getters. * SMTChecker: Support named arguments in function calls. * SMTChecker: Support struct constructor. * Standard-Json: Move the recently introduced ``modelCheckerSettings`` key to ``settings.modelChecker``. * Standard-Json: Properly filter the requested output artifacts. Bugfixes: * Code generator: Do not pad empty string literals with a single 32-byte zero field in the ABI coder v1. * NatSpec: Fix segfault when inheriting return parameter documentation for modifiers with no parameters. * SMTChecker: Fix cast string literals to byte arrays. * SMTChecker: Fix internal compiler error when doing bitwise compound assignment with string literals. * SMTChecker: Fix internal error when trying to generate counterexamples with old z3. * SMTChecker: Fix segmentation fault that could occur on certain SMT-enabled sources when no SMT solver was available. * SMTChecker: Fix internal error when ``bytes.push()`` is used as the LHS of an assignment. * Type Checker: ``super`` is not available in libraries. * Type Checker: Disallow leading zeroes in sized-types (e.g. ``bytes000032``), but allow them to be treated as identifiers. * Yul Optimizer: Fix a bug in NameSimplifier where a new name created by NameSimplifier could also be created by NameDispenser. * Yul Optimizer: Removed NameSimplifier from optimization steps available to users. ### 0.7.5 (2020-11-18) Language Features: * Ability to select the abi coder using ``pragma abicoder v1`` and ``pragma abicoder v2``. * Inline Assembly: Use ``.offset`` and ``.length`` for calldata variables of dynamic array type to access their calldata offset and length (number of elements). Both of them can also be assigned to. * Immutable variables with literal number values are considered pure. Compiler Features: * Assembler: Perform linking in assembly mode when library addresses are provided. * Command Line Interface: New option ``--experimental-via-ir`` allows switching compilation process to go through the Yul intermediate representation. This is highly experimental and is used for development purposes. * Command Line Interface: New option ``--model-checker-timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker. * Command Line Interface: Report error if file could not be read in ``--standard-json`` mode. * Command Line interface: Report proper error for each output file which could not be written. Previously an exception was thrown, and execution aborted, on the first error. * SMTChecker: Add division by zero checks in the CHC engine. * SMTChecker: More precise analysis of external calls using ``this``. * SMTChecker: Support ``selector`` for expressions with value known at compile-time. * Standard JSON: New option ``modelCheckerSettings.timeout`` sets a timeout in milliseconds for each individual query performed by the SMTChecker. * Standard JSON: New option ``settings.viaIR`` allows the same switch as ``--experimental-via-ir`` on the commandline. Bugfixes: * Code generator: Fix missing creation dependency tracking for abstract contracts. * Command Line Interface: Fix write error when the directory passed to ``--output-dir`` ends with a slash. * Command Line Interface: Reject duplicate libraries in ``--libraries`` option instead of arbitrarily choosing one. * NatSpec: Fix internal error when inheriting return parameter documentation but the parameter names differ between base and inherited. * SMTChecker: Fix CHC false positives when branches are used inside modifiers. * SMTChecker: Fix false negative in modifier applied multiple times. * SMTChecker: Fix incorrect counterexamples reported by the CHC engine. * SMTChecker: Fix internal error in the BMC engine when inherited contract from a different source unit has private state variables. * SMTChecker: Fix internal error on conversion from string literal to byte. * SMTChecker: Fix internal error when ``array.push()`` is used as the LHS of an assignment. * SMTChecker: Fix internal error when assigning state variable via contract's name. * SMTChecker: Fix internal error when using tuples of rational literals inside the conditional operator. * SMTChecker: Fix lack of reporting potential violations when using only the CHC engine. * Standard JSON: Fix library addresses specified in ``libraries`` being used for linking even if the file names do not match. AST Changes: * New member ``suffix`` for inline assembly identifiers. Currently supported values are ``"slot"``, ``"offset"`` and ``"length"`` to access the components of a Solidity variable. ### 0.7.4 (2020-10-19) Important Bugfixes: * Code Generator: Fix data corruption bug when copying empty byte arrays from memory or calldata to storage. Language Features: * Constants can be defined at file level. Compiler Features: * Command Line Interface: New option ``--model-checker-engine`` allows to choose a specific SMTChecker engine. Options are ``all`` (default), ``bmc``, ``chc`` and ``none``. * Control Flow Graph: Print warning for non-empty functions with unnamed return parameters that are not assigned a value in all code paths. * SMTChecker: Support ``keccak256``, ``sha256``, ``ripemd160`` and ``ecrecover`` in the CHC engine. * SMTChecker: Support inline arrays. * SMTChecker: Support variables ``block``, ``msg`` and ``tx`` in the CHC engine. * Standard JSON: New option ``modelCheckerSettings.engine`` allows to choose a specific SMTChecker engine. Options are ``all`` (default), ``bmc``, ``chc`` and ``none``. Bugfixes: * Code generator: Fix ``ABIEncoderV2`` pragma from the current module affecting inherited functions and applied modifiers. * Code generator: Fix internal compiler error when referencing members via module name but not using the reference. * Code generator: Fix internal error on returning structs containing mappings from library function. * Code generator: Use revert instead of invalid opcode for out-of-bounds array index access in getter. * Contract Level Checker: Add missing check against inheriting functions with ABIEncoderV2 return types in ABIEncoderV1 contracts. * Name Resolver: Fix shadowing/same-name warnings for later declarations. * Type Checker: Allow arrays of contract types as type expressions and as arguments for ``abi.decode``. * Type Checker: Disallow invalid use of library names as type name. * Type Checker: Fix internal compiler error caused by storage parameters with nested mappings in libraries. ### 0.7.3 (2020-10-07) Important Bugfixes: * Code Generator: Properly cleanup after copying dynamic-array to storage for packed types. Compiler Features: * Code generator: Implemented events with function type as one of its indexed parameters. * General: Option to stop compilation after parsing stage. Can be used with ``solc --stop-after parsing`` * Optimizer: Optimize ``exp`` when base is ``-1``. * SMTChecker: Support ``addmod`` and ``mulmod``. * SMTChecker: Support array slices. * SMTChecker: Support type conversions. Bugfixes: * Fixed internal compiler errors for certain contracts involving the ``new`` expression. * JSON AST: Fix internal error when using ``--ast-json`` on a function with memory arguments in ABIEncoderV2 contracts. * Type Checker: Add missing checks for calls using types incompatible with ABIEncoderV1 in modules where ABIEncoderV2 is not enabled. * Type Checker: Fix internal compiler error when calling `.push()` for a storage array with a nested mapping. ### 0.7.2 (2020-09-28) Important Bugfixes: * Type Checker: Disallow two or more free functions with identical name (potentially imported and aliased) and parameter types. Compiler Features: * Export compiler-generated utility sources via standard-json or combined-json. * Optimizer: Optimize ``exp`` when base is 0, 1 or 2. * SMTChecker: Keep knowledge about string literals, even through assignment, and thus support the ``.length`` property properly. * SMTChecker: Support ``address`` type conversion with literals, e.g. ``address(0)``. * SMTChecker: Support ``revert()``. * SMTChecker: Support ``type(T).min``, ``type(T).max``, and ``type(I).interfaceId``. * SMTChecker: Support compound and, or, and xor operators. * SMTChecker: Support events and low-level logs. * SMTChecker: Support fixed bytes index access. * SMTChecker: Support memory allocation, e.g. ``new bytes(123)``. * SMTChecker: Support shifts. * SMTChecker: Support structs. * Type Checker: Explain why oversized hex string literals can not be explicitly converted to a shorter ``bytesNN`` type. * Type Checker: More detailed error messages why implicit conversions fail. * Type Checker: Report position of first invalid UTF-8 sequence in ``unicode""`` literals. * Yul IR Generator: Report source locations related to unimplemented features. * Yul Optimizer: Inline into functions further down in the call graph first. * Yul Optimizer: Prune unused parameters in functions. * Yul Optimizer: Try to simplify function names. Bugfixes: * Code generator: Fix internal error on stripping dynamic types from return parameters on EVM versions without ``RETURNDATACOPY``. * Type Checker: Add missing check against nested dynamic arrays in ABI encoding functions when ABIEncoderV2 is disabled. * Type Checker: Correct the error message for invalid named parameter in a call to refer to the right argument. * Type Checker: Disallow ``virtual`` for modifiers in libraries. * Name Resolver: Correct the warning for homonymous, but not shadowing declarations. * Type system: Fix internal error on implicit conversion of contract instance to the type of its ``super``. * Type system: Fix internal error on implicit conversion of string literal to a calldata string. * Type system: Fix named parameters in overloaded function and event calls being matched incorrectly if the order differs from the declaration. * ViewPureChecker: Prevent visibility check on constructors. ### 0.7.1 (2020-09-02) Language Features: * Allow function definitions outside of contracts, behaving much like internal library functions. * Code generator: Implementing copying structs from calldata to storage. Compiler Features: * SMTChecker: Add underflow and overflow as verification conditions in the CHC engine. * SMTChecker: Support bitwise or, xor and not operators. * SMTChecker: Support conditional operator. * Standard JSON Interface: Do not run EVM bytecode code generation, if only Yul IR or EWasm output is requested. * Yul Optimizer: LoopInvariantCodeMotion can move reading operations outside for-loops as long as the affected area is not modified inside the loop. * Yul: Report error when using non-string literals for ``datasize()``, ``dataoffset()``, ``linkersymbol()``, ``loadimmutable()``, ``setimmutable()``. Bugfixes: * AST: Remove ``null`` member values also when the compiler is used in standard-json-mode. * General: Allow `type(Contract).name` for abstract contracts and interfaces. * Immutables: Disallow assigning immutables more than once during their declaration. * Immutables: Properly treat complex assignment and increment/decrement as both reading and writing and thus disallow it everywhere for immutable variables. * Optimizer: Keep side-effects of ``x`` in ``byte(a, shr(b, x))`` even if the constants ``a`` and ``b`` would make the expression zero unconditionally. This optimizer rule is very hard if not impossible to trigger in a way that it can result in invalid code, though. * References Resolver: Fix internal bug when using constructor for library. * Scanner: Fix bug where whitespace would be allowed within the ``->`` token (e.g. ``function f() - > x {}`` becomes invalid in inline assembly and Yul). * SMTChecker: Fix internal error in BMC function inlining. * SMTChecker: Fix internal error on array implicit conversion. * SMTChecker: Fix internal error on fixed bytes index access. * SMTChecker: Fix internal error on lvalue unary operators with tuples. * SMTChecker: Fix internal error on tuple assignment. * SMTChecker: Fix internal error on tuples of one element that have tuple type. * SMTChecker: Fix internal error when using imported code. * SMTChecker: Fix soundness of array ``pop``. * Type Checker: Disallow ``using for`` directive inside interfaces. * Type Checker: Disallow signed literals as exponent in exponentiation operator. * Type Checker: Disallow structs containing nested mapping in memory as parameters for library functions. * Yul Optimizer: Ensure that Yul keywords are not mistakenly used by the NameDispenser and VarNameCleaners. The bug would manifest as uncompilable code. * Yul Optimizer: Make function inlining order more resilient to whether or not unrelated source files are present. ### 0.7.0 (2020-07-28) Breaking changes: * Inline Assembly: Disallow ``.`` in user-defined function and variable names. * Inline Assembly: Slot and offset of storage pointer variable ``x`` are accessed via ``x.slot`` and ``x.offset`` instead of ``x_slot`` and ``x_offset``. * JSON AST: Mark hex string literals with ``kind: "hexString"``. * JSON AST: Remove members with ``null`` value from JSON output. * Parser: Disallow ``gwei`` as identifier. * Parser: Disallow dot syntax for ``value`` and ``gas``. * Parser: Disallow non-printable characters in string literals. * Parser: Introduce Unicode string literals: ``unicode"😃"``. * Parser: NatSpec comments on variables are only allowed for public state variables. * Parser: Remove the ``finney`` and ``szabo`` denominations. * Parser: Remove the identifier ``now`` (replaced by ``block.timestamp``). * Reference Resolver: ``using A for B`` only affects the contract it is mentioned in and not all derived contracts * Type Checker: Disallow ``virtual`` for library functions. * Type Checker: Disallow assignments to state variables that contain nested mappings. * Type checker: Disallow events with same name and parameter types in inheritance hierarchy. * Type Checker: Disallow shifts by signed types. * Type Checker: Disallow structs and arrays in memory or calldata if they contain nested mappings. * Type Checker: Exponentiation and shifts of literals by non-literals will always use ``uint256`` or ``int256`` as a type. * Yul: Disallow consecutive and trailing dots in identifiers. Leading dots were already disallowed. * Yul: Disallow EVM instruction `pc()`. Language Features: * Inheritance: Allow overrides to have stricter state mutability: ``view`` can override ``nonpayable`` and ``pure`` can override ``view``. * Parser: Deprecate visibility for constructors. * State mutability: Do not issue recommendation for stricter mutability for virtual functions but do issue it for functions that override. Compiler Features: * SMTChecker: Report multi-transaction counterexamples including the function calls that initiate the transactions. This does not include concrete values for reference types and reentrant calls. * Variable declarations using the ``var`` keyword are not recognized anymore. Bugfixes: * Immutables: Fix internal compiler error when immutables are not assigned. * Inheritance: Disallow public state variables overwriting ``pure`` functions. * NatSpec: Constructors and functions have consistent userdoc output. * SMTChecker: Fix internal error when assigning to a 1-tuple. * SMTChecker: Fix internal error when tuples have extra effectless parenthesis. * State Mutability: Constant public state variables are considered ``pure`` functions. * Type Checker: Fixing deduction issues on function types when function call has named arguments. ### 0.6.12 (2020-07-22) Language Features: * NatSpec: Implement tag ``@inheritdoc`` to copy documentation from a specific base contract. * Wasm backend: Add ``i32.ctz``, ``i64.ctz``, ``i32.popcnt``, and ``i64.popcnt``. Compiler Features: * Code Generator: Avoid double cleanup when copying to memory. * Code Generator: Evaluate ``keccak256`` of string literals at compile-time. * Optimizer: Add rule to remove shifts inside the byte opcode. * Peephole Optimizer: Add rule to remove swap after dup. * Peephole Optimizer: Remove unnecessary masking of tags. * Yul EVM Code Transform: Free stack slots directly after visiting the right-hand-side of variable declarations instead of at the end of the statement only. Bugfixes: * SMTChecker: Fix error in events with indices of type static array. * SMTChecker: Fix internal error in sequential storage array pushes (``push().push()``). * SMTChecker: Fix internal error when using bitwise operators on fixed bytes type. * SMTChecker: Fix internal error when using compound bitwise operator assignments on array indices inside branches. * Type Checker: Fix internal compiler error related to oversized types. * Type Checker: Fix overload resolution in combination with ``{value: ...}``. Build System: * Update internal dependency of jsoncpp to 1.9.3. ### 0.6.11 (2020-07-07) Language Features: * General: Add unit denomination ``gwei`` * Yul: Support ``linkersymbol`` builtin in standalone assembly mode to refer to library addresses. * Yul: Support using string literals exceeding 32 bytes as literal arguments for builtins. Compiler Features: * NatSpec: Add fields ``kind`` and ``version`` to the JSON output. * NatSpec: Inherit tags from unique base functions if derived function does not provide any. * Commandline Interface: Prevent some incompatible commandline options from being used together. * NatSpec: Support NatSpec comments on events. * Yul Optimizer: Store knowledge about storage / memory after ``a := sload(x)`` / ``a := mload(x)``. * SMTChecker: Support external calls to unknown code. * Source Maps: Also tag jumps into and out of Yul functions as jumps into and out of functions. Bugfixes: * NatSpec: Do not consider ``////`` and ``/***`` as NatSpec comments. * Type Checker: Disallow constructor parameters with ``calldata`` data location. * Type Checker: Do not disallow assigning to calldata variables. * Type Checker: Fix internal error related to ``using for`` applied to non-libraries. * Wasm backend: Fix code generation for for-loops with pre statements. * Wasm backend: Properly support both ``i32.drop`` and ``i64.drop``, and remove ``drop``. * Yul: Disallow the same variable to occur multiple times on the left-hand side of an assignment. * Yul: Fix source location of variable multi-assignment. ### 0.6.10 (2020-06-11) Important Bugfixes: * Fixed a bug related to internal library functions with ``calldata`` parameters called via ``using for``. Compiler Features: * Commandline Interface: Re-group help screen. * Output compilation error codes in standard-json and when using ``--error-codes``. * Yul: Raise warning for switch statements that only have a default and no other cases. Bugfixes: * SMTChecker: Fix internal error when encoding tuples of tuples. * SMTChecker: Fix aliasing soundness after pushing to an array pointer. * Type system: Fix internal compiler error on calling externally a function that returns variables with calldata location. * Type system: Fix bug where a bound function was not found if ``using for`` is applied to explicit reference types. ### 0.6.9 (2020-06-04) Language Features: * Permit calldata location for all variables. * NatSpec: Support NatSpec comments on state variables. * Yul: EVM instruction `pc()` is marked deprecated and will be removed in the next breaking release. Compiler Features: * Build system: Update the soljson.js build to emscripten 1.39.15 and boost 1.73.0 and include Z3 for integrated SMTChecker support without the callback mechanism. * Build system: Switch the emscripten build from the fastcomp backend to the upstream backend. * Code Generator: Do not introduce new internal source references for small compiler routines. * Commandline Interface: Adds new option ``--base-path PATH`` to use the given path as the root of the source tree (defaults to the root of the filesystem). * SMTChecker: Support array ``length``. * SMTChecker: Support array ``push`` and ``pop``. * SMTChecker: General support to BitVectors and the bitwise ``and`` operator. Bugfixes: * Code Generator: Trigger proper unimplemented errors on certain array copy operations. * Commandline Interface: Fix internal error when using ``--assemble`` or ``--yul`` options with ``--machine ewasm`` but without specifying ``--yul-dialect``. * NatSpec: DocString block is terminated when encountering an empty line. * Optimizer: Fixed a bug in BlockDeDuplicator. * Scanner: Fix bug when two empty NatSpec comments lead to scanning past EOL. * SMTChecker: Fix internal error on try/catch clauses with parameters. * SMTChecker: Fix internal error when applying arithmetic operators to fixed point variables. * SMTChecker: Fix internal error when assigning to index access inside branches. * SMTChecker: Fix internal error when short circuiting Boolean expressions with function calls in state variable initialization. * Type Checker: Disallow assignments to storage variables of type ``mapping``. * Type Checker: Disallow inline arrays of non-nameable types. * Type Checker: Disallow usage of override with non-public state variables. * Type Checker: Fix internal compiler error when accessing members of array slices. * Type Checker: Fix internal compiler error when forward referencing non-literal constants from inline assembly. * Type Checker: Fix internal compiler error when trying to decode too large static arrays. * Type Checker: Fix wrong compiler error when referencing an overridden function without calling it. ### 0.6.8 (2020-05-14) Important Bugfixes: * Add missing callvalue check to the creation code of a contract that does not define a constructor but has a base that does define a constructor. * Disallow array slices of arrays with dynamically encoded base types. * String literals containing backslash characters can no longer cause incorrect code to be generated when passed directly to function calls or encoding functions when ABIEncoderV2 is active. Language Features: * Implemented ``type(T).min`` and ``type(T).max`` for every integer type ``T`` that returns the smallest and largest value representable by the type. Compiler Features: * Commandline Interface: Don't ignore `--yul-optimizations` in assembly mode. * Allow using abi encoding functions for calldata array slices without explicit casts. * Wasm binary output: Implement ``br`` and ``br_if``. Bugfixes: * ABI: Skip ``private`` or ``internal`` constructors. * Fixed an "Assembly Exception in Bytecode" error where requested functions were generated twice. * Natspec: Fixed a bug that ignored ``@return`` tag when no other developer-documentation tags were present. * Type Checker: Checks if a literal exponent in the ``**`` operation is too large or fractional. * Type Checker: Disallow accessing ``runtimeCode`` for contract types that contain immutable state variables. * Yul Assembler: Fix source location of variable declarations without value. ### 0.6.7 (2020-05-04) Language Features: * Add support for EIP 165 interface identifiers with `type(I).interfaceId`. * Allow virtual modifiers inside abstract contracts to have empty body. Compiler Features: * Optimizer: Simplify repeated AND and OR operations. * Standard Json Input: Support the prefix ``file://`` in the field ``urls``. * Add option to specify optimization steps to be performed by Yul optimizer with `--yul-optimizations` in the commandline interface or `optimizer.details.yulDetails.optimizerSteps` in standard-json. Bugfixes: * SMTChecker: Fix internal error when fixed points are used. * SMTChecker: Fix internal error when using array slices. * Type Checker: Disallow ``virtual`` and ``override`` for constructors. * Type Checker: Fix several internal errors by performing size and recursiveness checks of types before the full type checking. * Type Checker: Fix internal error when assigning to empty tuples. * Type Checker: Fix internal error when applying unary operators to tuples with empty components. * Type Checker: Perform recursiveness check on structs declared at the file level. Build System: * soltest.sh: ``SOLIDITY_BUILD_DIR`` is no longer relative to ``REPO_ROOT`` to allow for build directories outside of the source tree. ### 0.6.6 (2020-04-09) Important Bugfixes: * Fix tuple assignments with components occupying multiple stack slots and different stack size on left- and right-hand-side. Bugfixes: * AST export: Export `immutable` property in the field `mutability`. * SMTChecker: Fix internal error in the CHC engine when calling inherited functions internally. * Type Checker: Error when trying to encode functions with call options gas and value set. ### 0.6.5 (2020-04-06) Important Bugfixes: * Code Generator: Restrict the length of dynamic memory arrays to 64 bits during creation at runtime fixing a possible overflow. Language Features: * Allow local storage variables to be declared without initialization, as long as they are assigned before they are accessed. * State variables can be marked ``immutable`` which causes them to be read-only, but assignable in the constructor. The value will be stored directly in the code. Compiler Features: * Commandline Interface: Enable output of storage layout with `--storage-layout`. * Metadata: Added support for IPFS hashes of large files that need to be split in multiple chunks. Bugfixes: * Inheritance: Allow public state variables to override functions with dynamic memory types in their return values. * Inline Assembly: Fix internal error when accessing invalid constant variables. * Inline Assembly: Fix internal error when accessing functions. * JSON AST: Always add pointer suffix for memory reference types. * Reference Resolver: Fix internal error when accessing invalid struct members. * Type Checker: Fix internal errors when assigning nested tuples. ### 0.6.4 (2020-03-10) Language Features: * General: Deprecated `value(...)` and `gas(...)` in favor of `{value: ...}` and `{gas: ...}` * Inline Assembly: Allow assigning to `_slot` of local storage variable pointers. * Inline Assembly: Perform control flow analysis on inline assembly. Allows storage returns to be set in assembly only. Compiler Features: * AssemblyStack: Support for source locations (source mappings) and thus debugging Yul sources. * Commandline Interface: Enable output of experimental optimized IR via ``--ir-optimized``. Bugfixes: * Inheritance: Fix incorrect error on calling unimplemented base functions. * Reference Resolver: Fix scoping issue following try/catch statements. * Standard-JSON-Interface: Fix a bug related to empty filenames and imports. * SMTChecker: Fix internal errors when analysing tuples. * Yul AST Import: correctly import blocks as statements, switch statements and string literals. ### 0.6.3 (2020-02-18) Language Features: * Allow contract types and enums as keys for mappings. * Allow function selectors to be used as compile-time constants. * Report source locations for structured documentation errors. Compiler Features: * AST: Add a new node for doxygen-style, structured documentation that can be received by contract, function, event and modifier definitions. * Code Generator: Use ``calldatacopy`` instead of ``codecopy`` to zero out memory past input. * Debug: Provide reason strings for compiler-generated internal reverts when using the ``--revert-strings`` option or the ``settings.debug.revertStrings`` setting on ``debug`` mode. * Yul Optimizer: Prune functions that call each other but are otherwise unreferenced. * SMTChecker: CHC support to internal function calls. Bugfixes: * Assembly: Added missing `source` field to legacy assembly json output to complete the source reference. * Parser: Fix an internal error for ``abstract`` without ``contract``. * Type Checker: Make invalid calls to uncallable types fatal errors instead of regular. ### 0.6.2 (2020-01-27) Language Features: * Allow accessing external functions via contract and interface names to obtain their selector. * Allow interfaces to inherit from other interfaces * Allow gas and value to be set in external function calls using ``c.f{gas: 10000, value: 4 ether}()``. * Allow specifying the ``salt`` for contract creations and thus the ``create2`` opcode using ``new C{salt: 0x1234, value: 1 ether}(arg1, arg2)``. * Inline Assembly: Support literals ``true`` and ``false``. Compiler Features: * LLL: The LLL compiler has been removed. * General: Raise warning if runtime bytecode exceeds 24576 bytes (a limit introduced in Spurious Dragon). * General: Support compiling starting from an imported AST. Among others, this can be used for mutation testing. * Yul Optimizer: Apply penalty when trying to rematerialize into loops. Bugfixes: * Commandline interface: Only activate yul optimizer if ``--optimize`` is given. * Fixes internal compiler error on explicitly calling unimplemented base functions. Build System: * Switch to building soljson.js with an embedded base64-encoded wasm binary. ### 0.6.1 (2020-01-02) Bugfixes: * Yul Optimizer: Fix bug in redundant assignment remover in combination with break and continue statements. ### 0.6.0 (2019-12-17) Breaking changes: * ABI: Remove the deprecated ``constant`` and ``payable`` fields. * ABI: The ``type`` field is now required and no longer specified to default to ``function``. * AST: Inline assembly is exported as structured JSON instead of plain string. * C API (``libsolc``): Introduce context parameter to both ``solidity_compile`` and the callback. * C API (``libsolc``): The provided callback now takes two parameters, kind and data. The callback can then be used for multiple purposes, such has file imports and SMT queries. * C API (``libsolc``): ``solidity_free`` was renamed to ``solidity_reset``. Functions ``solidity_alloc`` and ``solidity_free`` were added. * C API (``libsolc``): ``solidity_compile`` now returns a string that must be explicitly freed via ``solidity_free()`` * Commandline Interface: Remove the text-based AST printer (``--ast``). * Commandline Interface: Switch to the new error reporter by default. ``--old-reporter`` falls back to the deprecated old error reporter. * Commandline Interface: Add option to disable or choose hash method between IPFS and Swarm for the bytecode metadata. * General: Disallow explicit conversions from external function types to ``address`` and add a member called ``address`` to them as replacement. * General: Enable Yul optimizer as part of standard optimization. * General: New reserved keywords: ``override``, ``receive``, and ``virtual``. * General: ``private`` cannot be used together with ``virtual``. * General: Split unnamed fallback functions into two cases defined using ``fallback()`` and ``receive()``. * Inheritance: State variable shadowing is now disallowed. * Inline Assembly: Only strict inline assembly is allowed. * Inline Assembly: Variable declarations cannot shadow declarations outside the assembly block. * JSON AST: Replace ``superFunction`` attribute by ``baseFunctions``. * Natspec JSON Interface: Properly support multiple ``@return`` statements in ``@dev`` documentation and enforce named return parameters to be mentioned documentation. * Source mappings: Add "modifier depth" as a fifth field in the source mappings. * Standard JSON Interface: Add option to disable or choose hash method between IPFS and Swarm for the bytecode metadata. * Syntax: ``push(element)`` for dynamic storage arrays do not return the new length anymore. * Syntax: Abstract contracts need to be marked explicitly as abstract by using the ``abstract`` keyword. * Syntax: ``length`` member of arrays is now always read-only, even for storage arrays. * Type Checker: Resulting type of exponentiation is equal to the type of the base. Also allow signed types for the base. Language Features: * Allow explicit conversions from ``address`` to ``address payable`` via ``payable(...)``. * Allow global enums and structs. * Allow public variables to override external functions. * Allow underscores as delimiters in hex strings. * Allow to react on failing external calls using ``try`` and ``catch``. * Introduce syntax for array slices and implement them for dynamic calldata arrays. * Introduce ``push()`` for dynamic storage arrays. It returns a reference to the newly allocated element, if applicable. * Introduce ``virtual`` and ``override`` keywords. * Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore. * Yul: Introduce ``leave`` statement that exits the current function. * JSON AST: Add the function selector of each externally-visible FunctionDefinition to the AST JSON export. Compiler Features: * Allow revert strings to be stripped from the binary using the ``--revert-strings`` option or the ``settings.debug.revertStrings`` setting. * ABIEncoderV2: Do not warn about enabled ABIEncoderV2 anymore (the pragma is still needed, though). ### 0.5.17 (2020-03-17) Bugfixes: * Type Checker: Disallow overriding of private functions. ### 0.5.16 (2020-01-02) Backported Bugfixes: * Yul Optimizer: Fix bug in redundant assignment remover in combination with break and continue statements. ### 0.5.15 (2019-12-17) Bugfixes: * Yul Optimizer: Fix incorrect redundant load optimization crossing user-defined functions that contain for-loops with memory / storage writes. ### 0.5.14 (2019-12-09) Language Features: * Allow to obtain the selector of public or external library functions via a member ``.selector``. * Inline Assembly: Support constants that reference other constants. * Parser: Allow splitting hexadecimal and regular string literals into multiple parts. Compiler Features: * Commandline Interface: Allow translation from yul / strict assembly to EWasm using ``solc --yul --yul-dialect evm --machine ewasm`` * Set the default EVM version to "Istanbul". * SMTChecker: Add support to constructors including constructor inheritance. * Yul: When compiling via Yul, string literals from the Solidity code are kept as string literals if every character is safely printable. * Yul Optimizer: Perform loop-invariant code motion. Bugfixes: * SMTChecker: Fix internal error when using ``abi.decode``. * SMTChecker: Fix internal error when using arrays or mappings of functions. * SMTChecker: Fix internal error in array of structs type. * Version Checker: ``^0`` should match ``0.5.0``, but no prerelease. * Yul: Consider infinite loops and recursion to be not removable. Build System: * Update to emscripten version 1.39.3. ### 0.5.13 (2019-11-14) Language Features: * Allow to obtain the address of a linked library with ``address(LibraryName)``. Compiler Features: * Code Generator: Use SELFBALANCE opcode for ``address(this).balance`` if using Istanbul EVM. * EWasm: Experimental EWasm binary output via ``--ewasm`` and as documented in standard-json. * SMTChecker: Add break/continue support to the CHC engine. * SMTChecker: Support assignments to multi-dimensional arrays and mappings. * SMTChecker: Support inheritance and function overriding. * Standard JSON Interface: Output the storage layout of a contract when artifact ``storageLayout`` is requested. * TypeChecker: List possible candidates when overload resolution fails. * TypeChecker: Disallow variables of library types. Bugfixes: * Code Generator: Fixed a faulty assert that would wrongly trigger for array sizes exceeding unsigned integer. * SMTChecker: Fix internal error when accessing indices of fixed bytes. * SMTChecker: Fix internal error when using function pointers as arguments. * SMTChecker: Fix internal error when implicitly converting string literals to fixed bytes. * Type Checker: Disallow constructor of the same class to be used as modifier. * Type Checker: Treat magic variables as unknown identifiers in inline assembly. * Code Generator: Fix internal error when trying to convert ``super`` to a different type ### 0.5.12 (2019-10-01) Language Features: * Type Checker: Allow assignment to external function arguments except for reference types. Compiler Features: * ABI Output: Change sorting order of functions from selector to kind, name. * Optimizer: Add rule that replaces the BYTE opcode by 0 if the first argument is larger than 31. * SMTChecker: Add loop support to the CHC engine. * Yul Optimizer: Take side-effect-freeness of user-defined functions into account. * Yul Optimizer: Remove redundant mload/sload operations. * Yul Optimizer: Use the fact that branch conditions have certain value inside the branch. Bugfixes: * Code Generator: Fix internal error when popping a dynamic storage array of mappings. * Name Resolver: Fix wrong source location when warning on shadowed aliases in import declarations. * Scanner: Fix multi-line natspec comment parsing with triple slashes when file is encoded with CRLF instead of LF. * Type System: Fix arrays of recursive structs. * Yul Optimizer: Fix reordering bug in connection with shifted one and mul/div-instructions in for loop conditions. ### 0.5.11 (2019-08-12) Language Features: * Inline Assembly: Support direct constants of value type in inline assembly. Compiler Features: * ABI: Additional internal type info in the field ``internalType``. * eWasm: Highly experimental eWasm output using ``--ewasm`` in the commandline interface or output selection of ``ewasm.wast`` in standard-json. * Metadata: Update the swarm hash to the current specification, changes ``bzzr0`` to ``bzzr1`` and urls to use ``bzz-raw://``. * Standard JSON Interface: Compile only selected sources and contracts. * Standard JSON Interface: Provide secondary error locations (e.g. the source position of other conflicting declarations). * SMTChecker: Do not erase knowledge about storage pointers if another storage pointer is assigned. * SMTChecker: Support string literal type. * SMTChecker: New Horn-based algorithm that proves assertions via multi-transaction contract invariants. * Standard JSON Interface: Provide AST even on errors if ``--error-recovery`` commandline switch or StandardCompiler `settings.parserErrorRecovery` is true. * Yul Optimizer: Do not inline function if it would result in expressions being duplicated that are not cheap. Bugfixes: * ABI decoder: Ensure that decoded arrays always point to distinct memory locations. * Code Generator: Treat dynamically encoded but statically sized arrays and structs in calldata properly. * SMTChecker: Fix internal error when inlining functions that contain tuple expressions. * SMTChecker: Fix pointer knowledge erasing in loops. * SMTChecker: Fix internal error when using compound bitwise assignment operators inside branches. * SMTChecker: Fix internal error when inlining a function that returns a tuple containing an unsupported type inside a branch. * SMTChecker: Fix internal error when inlining functions that use state variables and belong to a different source. * SMTChecker: Fix internal error when reporting counterexamples concerning state variables from different source files. * SMTChecker: Fix SMT sort mismatch when using string literals. * View/Pure Checker: Properly detect state variable access through base class. * Yul Analyzer: Check availability of data objects already in analysis phase. * Yul Optimizer: Fix an issue where memory-accessing code was removed even though ``msize`` was used in the program. ### 0.5.10 (2019-06-25) Important Bugfixes: * ABIEncoderV2: Fix incorrect abi encoding of storage array of data type that occupy multiple storage slots * Code Generator: Properly zero out higher order bits in elements of an array of negative numbers when assigning to storage and converting the type at the same time. Compiler Features: * Commandline Interface: Experimental parser error recovery via the ``--error-recovery`` commandline switch or StandardCompiler `settings.parserErrorRecovery` boolean. * Optimizer: Add rule to simplify ``SUB(~0, X)`` to ``NOT(X)``. * Yul Optimizer: Make the optimizer work for all dialects of Yul including eWasm. Bugfixes: * Type Checker: Set state mutability of the function type members ``gas`` and ``value`` to pure (while their return type inherits state mutability from the function type). * Yul / Inline Assembly Parser: Disallow trailing commas in function call arguments. Build System: * Attempt to use stock Z3 cmake files to find Z3 and only fall back to manual discovery. * CMake: use imported targets for boost. * Emscripten build: upgrade to boost 1.70. * Generate a cmake error for gcc versions older than 5.0. ### 0.5.9 (2019-05-28) Language Features: * Inline Assembly: Revert change introduced in 0.5.7: The ``callvalue()`` instruction does not require ``payable`` anymore. * Static Analyzer: Disallow libraries calling themselves externally. Compiler Features: * Assembler: Encode the compiler version in the deployed bytecode. * Code Generator: Fix handling of structs of dynamic size as constructor parameters. * Inline Assembly: Disallow the combination of ``msize()`` and the Yul optimizer. * Metadata: Add IPFS hashes of source files. * Optimizer: Add rule to simplify SHL/SHR combinations. * Optimizer: Add rules for multiplication and division by left-shifted one. * SMTChecker: Support inherited state variables. * SMTChecker: Support tuples and function calls with multiple return values. * SMTChecker: Support ``delete``. * SMTChecker: Inline external function calls to ``this``. * Yul Optimizer: Simplify single-run ``for`` loops to ``if`` statements. * Yul Optimizer: Optimize representation of numbers. * Yul Optimizer: Do not inline recursive functions. * Yul Optimizer: Do not remove instructions that affect ``msize()`` if ``msize()`` is used. Bugfixes: * Code Generator: Explicitly turn uninitialized internal function pointers into invalid functions when loaded from storage. * Code Generator: Fix assertion failure when assigning structs containing array of mapping. * Compiler Internals: Reset the Yul string repository before each compilation, freeing up memory. * SMTChecker: Fix bad cast in base constructor modifier. * SMTChecker: Fix internal error when visiting state variable inherited from base class. * SMTChecker: Fix internal error in fixed point operations. * SMTChecker: Fix internal error in assignment to unsupported type. * SMTChecker: Fix internal error in branching when inlining function calls that modify local variables. ### 0.5.8 (2019-04-30) Important Bugfixes: * Code Generator: Fix initialization routine of uninitialized internal function pointers in constructor context. * Yul Optimizer: Fix SSA transform for multi-assignments. Language Features: * ABIEncoderV2: Implement encoding of calldata arrays and structs. * Code Generation: Implement copying recursive structs from storage to memory. * Yul: Disallow function definitions inside for-loop init blocks. Compiler Features: * ABI Decoder: Raise a runtime error on dirty inputs when using the experimental decoder. * Optimizer: Add rule for shifts by constants larger than 255 for Constantinople. * Optimizer: Add rule to simplify certain ANDs and SHL combinations * SMTChecker: Support arithmetic compound assignment operators. * SMTChecker: Support unary increment and decrement for array and mapping access. * SMTChecker: Show unsupported warning for inline assembly blocks. * SMTChecker: Support mod. * SMTChecker: Support ``contract`` type. * SMTChecker: Support ``this`` as address. * SMTChecker: Support address members. * Standard JSON Interface: Metadata settings now re-produce the original ``"useLiteralContent"`` setting from the compilation input. * Yul: Adds break and continue keywords to for-loop syntax. * Yul: Support ``.`` as part of identifiers. * Yul Optimizer: Adds steps for detecting and removing of dead code. * Yul Code Generator: Directly jump over a series of function definitions (instead of jumping over each one) Bugfixes: * SMTChecker: Implement Boolean short-circuiting. * SMTChecker: SSA control-flow did not take into account state variables that were modified inside inlined functions that were called inside branches. * Type System: Use correct type name for contracts in event parameters when used in libraries. This affected code generation. * Type System: Allow direct call to base class functions that have overloads. * Type System: Warn about shadowing builtin variables if user variables are named ``this`` or ``super``. * Yul: Properly register functions and disallow shadowing between function variables and variables in the outside scope. Build System: * Soltest: Add commandline option `--test` / `-t` to isoltest which takes a string that allows filtering unit tests. * soltest.sh: allow environment variable ``SOLIDITY_BUILD_DIR`` to specify build folder and add ``--help`` usage. ### 0.5.7 (2019-03-26) Important Bugfixes: * ABIEncoderV2: Fix bugs related to loading short value types from storage when encoding an array or struct from storage. * ABIEncoderV2: Fix buffer overflow problem when encoding packed array from storage. * Optimizer: Fix wrong ordering of arguments in byte optimization rule for constants. Language Features: * Function calls with named arguments now work with overloaded functions. Compiler Features: * Inline Assembly: Issue error when using ``callvalue()`` inside nonpayable function (in the same way that ``msg.value`` already does). * Standard JSON Interface: Support "Yul" as input language. * SMTChecker: Show callstack together with model if applicable. * SMTChecker: Support modifiers. * Yul Optimizer: Enable stack allocation optimization by default if Yul optimizer is active (disable in ``yulDetails``). Bugfixes: * Code Generator: Defensively pad memory for ``type(Contract).name`` to multiples of 32. * Type System: Detect and disallow internal function pointers as parameters for public/external library functions, even when they are nested/wrapped in structs, arrays or other types. * Yul Optimizer: Properly determine whether a variable can be eliminated during stack compression pass. * Yul / Inline Assembly Parser: Disallow more than one case statement with the same label inside a switch based on the label's integer value. Build System: * Install scripts: Fix boost repository URL for CentOS 6. * Soltest: Fix hex string update in soltest. ### 0.5.6 (2019-03-13) Important Bugfixes: * Yul Optimizer: Fix visitation order bug for the structural simplifier. * Optimizer: Fix overflow in optimization rule that simplifies double shift by constant. Language Features: * Allow calldata arrays with dynamically encoded base types with ABIEncoderV2. * Allow dynamically encoded calldata structs with ABIEncoderV2. Compiler Features: * Optimizer: Add rules for ``lt``-comparisons with constants. * Peephole Optimizer: Remove double ``iszero`` before ``jumpi``. * SMTChecker: Support enums without typecast. * SMTChecker: Support one-dimensional arrays. * Type Checker: Provide better error messages for some literal conversions. * Yul Optimizer: Add rule to remove empty default switch cases. * Yul Optimizer: Add rule to remove empty cases if no default exists. * Yul Optimizer: Add rule to replace a switch with no cases with ``pop(expression)``. Bugfixes: * JSON ABI: Json description of library ABIs no longer contains functions with internal types like storage structs. * SMTChecker: Fix internal compiler error when contract contains too large rational number. * Type system: Detect if a contract's base uses types that require the experimental abi encoder while the contract still uses the old encoder. Build System: * Soltest: Add support for arrays in function signatures. * Soltest: Add support for struct arrays in function signatures. * Soltest: Add support for left-aligned, unpadded hex string literals. ### 0.5.5 (2019-03-05) Language Features: * Add support for getters of mappings with ``string`` or ``bytes`` key types. * Meta programming: Provide access to the name of contracts via ``type(C).name``. Compiler Features: * Support ``petersburg`` as ``evmVersion`` and set as default. * Commandline Interface: Option to activate the experimental yul optimizer using ``-optimize-yul``. * Inline Assembly: Consider ``extcodehash`` as part of Constantinople. * Inline Assembly: Instructions unavailable to the currently configured EVM are errors now. * SMTChecker: Do not report underflow/overflow if they always revert. This removes false positives when using ``SafeMath``. * Standard JSON Interface: Allow retrieving metadata without triggering bytecode generation. * Standard JSON Interface: Provide fine-grained control over the optimizer via the settings. * Static Analyzer: Warn about expressions with custom types when they have no effect. * Optimizer: Add new rules with constants including ``LT``, ``GT``, ``AND`` and ``BYTE``. * Optimizer: Add rule for shifts with constants for Constantinople. * Optimizer: Combine multiple shifts with constant shift-by values into one. * Optimizer: Do not mask with 160-bits after ``CREATE`` and ``CREATE2`` as they are guaranteed to return an address or 0. * Optimizer: Support shifts in the constant optimiser for Constantinople. * Yul Optimizer: Add rule to replace switch statements with literals by matching case body. Bugfixes: * ABIEncoderV2: Fix internal error related to bare delegatecall. * ABIEncoderV2: Fix internal error related to ecrecover. * ABIEncoderV2: Fix internal error related to mappings as library parameters. * ABIEncoderV2: Fix invalid signature for events containing structs emitted in libraries. * Inline Assembly: Proper error message for missing variables. * Optimizer: Fix internal error related to unused tag removal across assemblies. This never generated any invalid code. * SMTChecker: Fix crash related to statically-sized arrays. * TypeChecker: Fix internal error and disallow index access on contracts and libraries. * Yul: Properly detect name clashes with functions before their declaration. * Yul: Take built-in functions into account in the compilability checker. * Yul Optimizer: Properly take reassignments to variables in sub-expressions into account when replacing in the ExpressionSimplifier. Build System: * Soltest: Add support for left-aligned, padded hex literals. * Soltest: Add support for right-aligned, padded boolean literals. ### 0.5.4 (2019-02-12) Language Features: * Allow calldata structs without dynamically encoded members with ABIEncoderV2. Compiler Features: * ABIEncoderV2: Implement packed encoding. * C API (``libsolc`` / raw ``soljson.js``): Introduce ``solidity_free`` method which releases all internal buffers to save memory. * Commandline Interface: Adds new option ``--new-reporter`` for improved diagnostics formatting along with ``--color`` and ``--no-color`` for colorized output to be forced (or explicitly disabled). Bugfixes: * Code Generator: Defensively pad allocation of creationCode and runtimeCode to multiples of 32 bytes. * Commandline Interface: Allow yul optimizer only for strict assembly. * Parser: Disallow empty import statements. * Type Checker: Disallow mappings with data locations other than ``storage``. * Type Checker: Fix internal error when a struct array index does not fit into a uint256. * Type System: Properly report packed encoded size for arrays and structs (mostly unused until now). Build System: * Add support for continuous fuzzing via Google oss-fuzz * SMT: If using Z3, require version 4.6.0 or newer. * Soltest: Add parser that is used in the file-based unit test environment. * Ubuntu PPA Packages: Use CVC4 as SMT solver instead of Z3 ### 0.5.3 (2019-01-22) Language Features: * Provide access to creation and runtime code of contracts via ``type(C).creationCode`` / ``type(C).runtimeCode``. Compiler Features: * Control Flow Graph: Warn about unreachable code. * SMTChecker: Support basic typecasts without truncation. * SMTChecker: Support external function calls and erase all knowledge regarding storage variables and references. Bugfixes: * Emscripten: Split simplification rule initialization up further to work around issues with soljson.js in some browsers. * Type Checker: Disallow calldata structs until implemented. * Type Checker: Return type error if fixed point encoding is attempted instead of throwing ``UnimplementedFeatureError``. * Yul: Check that arguments to ``dataoffset`` and ``datasize`` are literals at parse time and properly take this into account in the optimizer. * Yul: Parse number literals for detecting duplicate switch cases. * Yul: Require switch cases to have the same type. Build System: * Emscripten: Upgrade to emscripten 1.38.8 on travis and circleci. ### 0.5.2 (2018-12-19) Language Features: * Control Flow Graph: Detect every access to uninitialized storage pointers. Compiler Features: * Inline Assembly: Improve error messages around invalid function argument count. * Code Generator: Only check callvalue once if all functions are non-payable. * Code Generator: Use codecopy for string constants more aggressively. * Code Generator: Use binary search for dispatch function if more efficient. The size/speed tradeoff can be tuned using ``--optimize-runs``. * SMTChecker: Support mathematical and cryptographic functions in an uninterpreted way. * SMTChecker: Support one-dimensional mappings. * Standard JSON Interface: Disallow unknown keys in standard JSON input. * Standard JSON Interface: Only run code generation if it has been requested. This could lead to unsupported feature errors only being reported at the point where you request bytecode. * Static Analyzer: Do not warn about unused variables or state mutability for functions with an empty body. * Type Checker: Add an additional reason to be displayed when type conversion fails. * Yul: Support object access via ``datasize``, ``dataoffset`` and ``datacopy`` in standalone assembly mode. Bugfixes: * Standard JSON Interface: Report specific error message for json input errors instead of internal compiler error. Build System: * Replace the trusty PPA build by a static build on cosmic that is used for the trusty package instead. * Remove support for Visual Studio 2015. ### 0.5.1 (2018-12-03) Language Features: * Allow mapping type for parameters and return variables of public and external library functions. * Allow public functions to override external functions. Compiler Features: * Code generator: Do not perform redundant double cleanup on unsigned integers when loading from calldata. * Commandline interface: Experimental ``--optimize`` option for assembly mode (``--strict-assembly`` and ``--yul``). * SMTChecker: SMTLib2 queries and responses passed via standard JSON compiler interface. * SMTChecker: Support ``msg``, ``tx`` and ``block`` member variables. * SMTChecker: Support ``gasleft()`` and ``blockhash()`` functions. * SMTChecker: Support internal bound function calls. * Yul: Support Yul objects in ``--assemble``, ``--strict-assembly`` and ``--yul`` commandline options. Bugfixes: * Assembly output: Do not mix in/out jump annotations with arguments. * Commandline interface: Fix crash when using ``--ast`` on empty runtime code. * Code Generator: Annotate jump from calldata decoder to function as "jump in". * Code Generator: Fix internal error related to state variables of function type access via base contract name. * Optimizer: Fix nondeterminism bug related to the boost version and constants representation. The bug only resulted in less optimal but still correct code because the generated routine is always verified to be correct. * Type Checker: Properly detect different return types when overriding an external interface function with a public contract function. * Type Checker: Disallow struct return types for getters of public state variables unless the new ABI encoder is active. * Type Checker: Fix internal compiler error when a field of a struct used as a parameter in a function type has a non-existent type. * Type Checker: Disallow functions ``sha3`` and ``suicide`` also without a function call. * Type Checker: Fix internal compiler error with ``super`` when base contract function is not implemented. * Type Checker: Fixed internal error when trying to create abstract contract in some cases. * Type Checker: Fixed internal error related to double declaration of events. * Type Checker: Disallow inline arrays of mapping type. * Type Checker: Consider abstract function to be implemented by public state variable. Build System: * CMake: LLL is not built anymore by default. Must configure it with CMake as `-DLLL=ON`. * Docker: Includes both Scratch and Alpine images. * Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67. Solc-Js: * Fix handling of standard-json in the commandline executable. * Remove support of nodejs 4. ### 0.5.0 (2018-11-13) How to update your code: * Change every ``.call()`` to a ``.call("")`` and every ``.call(signature, a, b, c)`` to use ``.call(abi.encodeWithSignature(signature, a, b, c))`` (the last one only works for value types). * Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``. * Add ``public`` to every function and ``external`` to every fallback or interface function that does not specify its visibility already. * Make your fallback functions ``external``. * Explicitly state the data location for all variables of struct, array or mapping types (including function parameters), e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``. Note that ``external`` functions require parameters with a data location of ``calldata``. * Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``. * Declare variables and especially function arguments as ``address payable``, if you want to call ``transfer`` on them. Breaking Changes: * ABI Encoder: Properly pad data from calldata (``msg.data`` and external function parameters). Use ``abi.encodePacked`` for unpadded encoding. * C API (``libsolc`` / raw ``soljson.js``): Removed the ``version``, ``license``, ``compileSingle``, ``compileJSON``, ``compileJSONCallback`` methods and replaced them with the ``solidity_license``, ``solidity_version`` and ``solidity_compile`` methods. * Code Generator: Signed right shift uses proper arithmetic shift, i.e. rounding towards negative infinity. Warning: this may silently change the semantics of existing code! * Code Generator: Revert at runtime if calldata is too short or points out of bounds. This is done inside the ``ABI decoder`` and therefore also applies to ``abi.decode()``. * Code Generator: Use ``STATICCALL`` for ``pure`` and ``view`` functions. This was already the case in the experimental 0.5.0 mode. * Commandline interface: Remove obsolete ``--formal`` option. * Commandline interface: Rename the ``--julia`` option to ``--yul``. * Commandline interface: Require ``-`` if standard input is used as source. * Commandline interface: Use hash of library name for link placeholder instead of name itself. * Compiler interface: Disallow remappings with empty prefix. * Control Flow Analyzer: Consider mappings as well when checking for uninitialized return values. * Control Flow Analyzer: Turn warning about returning uninitialized storage pointers into an error. * General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code. * General: Disallow declaring empty structs. * General: Disallow raw ``callcode`` (was already deprecated in 0.4.12). It is still possible to use it via inline assembly. * General: Disallow ``var`` keyword. * General: Disallow ``sha3`` and ``suicide`` aliases. * General: Disallow the ``throw`` statement. This was already the case in the experimental 0.5.0 mode. * General: Disallow the ``years`` unit denomination (was already deprecated in 0.4.24) * General: Introduce ``emit`` as a keyword instead of parsing it as identifier. * General: New keywords: ``calldata`` and ``constructor`` * General: New reserved keywords: ``alias``, ``apply``, ``auto``, ``copyof``, ``define``, ``immutable``, ``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. * General: Remove assembly instruction aliases ``sha3`` and ``suicide`` * General: C99-style scoping rules are enforced now. This was already the case in the experimental 0.5.0 mode. * General: Disallow combining hex numbers with unit denominations (e.g. ``0x1e wei``). This was already the case in the experimental 0.5.0 mode. * JSON AST: Remove ``constant`` and ``payable`` fields (the information is encoded in the ``stateMutability`` field). * JSON AST: Replace the ``isConstructor`` field by a new ``kind`` field, which can be ``constructor``, ``fallback`` or ``function``. * Interface: Remove "clone contract" feature. The ``--clone-bin`` and ``--combined-json clone-bin`` commandline options are not available anymore. * Name Resolver: Do not exclude public state variables when looking for conflicting declarations. * Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence. * Parser: Disallow trailing dots that are not followed by a number. * Parser: Remove ``constant`` as function state mutability modifier. * Parser: Disallow uppercase X in hex number literals * Type Checker: Disallow assignments between tuples with different numbers of components. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow values for constants that are not compile-time constants. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow arithmetic operations for boolean variables. * Type Checker: Disallow tight packing of literals. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow calling base constructors without parentheses. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size. * Type Checker: Disallow conversions between unrelated contract types. Explicit conversion via ``address`` can still achieve it. * Type Checker: Disallow empty return statements for functions with one or more return values. * Type Checker: Disallow empty tuple components. This was partly already the case in the experimental 0.5.0 mode. * Type Checker: Disallow multi-variable declarations with mismatching number of values. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow specifying base constructor arguments multiple times in the same inheritance hierarchy. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow calling constructor with wrong argument count. This was already the case in the experimental 0.5.0 mode. * Type Checker: Disallow uninitialized storage variables. This was already the case in the experimental 0.5.0 mode. * Type Checker: Detecting cyclic dependencies in variables and structs is limited in recursion to 256. * Type Checker: Require explicit data location for all variables, including function parameters. This was partly already the case in the experimental 0.5.0 mode. * Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``. * Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode. * Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode. * Type Checker: Address members are not included in contract types anymore. An explicit conversion is now required before invoking an ``address`` member from a contract. * Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore. * Type System: Disallow explicit and implicit conversions from decimal literals to ``bytesXX`` types. * Type System: Disallow explicit and implicit conversions from hex literals to ``bytesXX`` types of different size. * Type System: Distinguish between payable and non-payable address types. * View Pure Checker: Disallow ``msg.value`` in (or introducing it via a modifier to) a non-payable function. * Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/solidity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible. * References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Disallow functions without implementation to use modifiers. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Named return values in function types are an error. * Syntax Checker: Strictly require visibility specifier for functions. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Disallow unary ``+``. This was already the case in the experimental 0.5.0 mode. * Syntax Checker: Disallow single statement variable declaration inside if/while/for bodies that are not blocks. * View Pure Checker: Strictly enforce state mutability. This was already the case in the experimental 0.5.0 mode. Language Features: * General: Add ``staticcall`` to ``address``. * General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions. * General: Support ``pop()`` for storage arrays. * General: Scoping rules now follow the C99-style. * General: Allow ``enum``s in interfaces. * General: Allow ``mapping`` storage pointers as arguments and return values in all internal functions. * General: Allow ``struct``s in interfaces. * General: Provide access to the ABI decoder through ``abi.decode(bytes memory data, (...))``. * General: Disallow zero length for fixed-size arrays. * Parser: Accept the ``address payable`` type during parsing. Compiler Features: * Build System: Support for Mojave version of macOS added. * Code Generator: ``CREATE2`` instruction has been updated to match EIP1014 (aka "Skinny CREATE2"). It also is accepted as part of Constantinople. * Code Generator: ``EXTCODEHASH`` instruction has been added based on EIP1052. * Type Checker: Nicer error message when trying to reference overloaded identifiers in inline assembly. * Type Checker: Show named argument in case of error. * Type System: IntegerType is split into IntegerType and AddressType internally. * Tests: Determine transaction status during IPC calls. * Code Generator: Allocate and free local variables according to their scope. * Removed ``pragma experimental "v0.5.0";``. * Syntax Checker: Improved error message for lookup in function types. * Name Resolver: Updated name suggestion look up function to take into account length of the identifier: 1: no search, 2-3: at most one change, 4-: at most two changes * SMTChecker: Support calls to internal functions that return none or a single value. Bugfixes: * Build System: Support versions of CVC4 linked against CLN instead of GMP. In case of compilation issues due to the experimental SMT solver support, the solvers can be disabled when configuring the project with CMake using ``-DUSE_CVC4=OFF`` or ``-DUSE_Z3=OFF``. * Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum. * Code Generator: Fix allocation of byte arrays (zeroed out too much memory). * Code Generator: Properly handle negative number literals in ABIEncoderV2. * Code Generator: Do not crash on using a length of zero for multidimensional fixed-size arrays. * Commandline Interface: Correctly handle paths with backslashes on windows. * Control Flow Analyzer: Ignore unimplemented functions when detecting uninitialized storage pointer returns. * Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions. * Optimizer: Correctly estimate gas costs of constants for special cases. * Optimizer: Fix simplification rule initialization bug that appeared on some emscripten platforms. * References Resolver: Do not crash on using ``_slot`` and ``_offset`` suffixes on their own. * References Resolver: Enforce ``storage`` as data location for mappings. * References Resolver: Properly handle invalid references used together with ``_slot`` and ``_offset``. * References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter. * References Resolver: Fix high CPU usage when using large variable names issue. Only suggest similar name if identifiers shorter than 80 characters. * Type Checker: Default data location for type conversions (e.g. from literals) is memory and not storage. * Type Checker: Disallow assignments to mappings within tuple assignments as well. * Type Checker: Disallow packed encoding of arrays of structs. * Type Checker: Allow assignments to local variables of mapping types. * Type Checker: Consider fixed size arrays when checking for recursive structs. * Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined. * Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``. * Type Checker: Dynamic types as key for public mappings return error instead of assertion fail. * Type Checker: Fix internal error when array index value is too large. * Type Checker: Fix internal error when fixed-size array is too large to be encoded. * Type Checker: Fix internal error for array type conversions. * Type Checker: Fix internal error when array index is not an unsigned. * Type System: Allow arbitrary exponents for literals with a mantissa of zero. * Parser: Fix incorrect source location for nameless parameters. * Command Line Interface: Fix internal error when compiling stdin with no content and --ast option. ### 0.4.26 (2019-04-29) Important Bugfixes: * Code Generator: Fix initialization routine of uninitialized internal function pointers in constructor context. * Type System: Use correct type name for contracts in event parameters when used in libraries. This affected code generation. Bugfixes: * ABIEncoderV2: Refuse to generate code that is known to be potentially buggy. * General: Split rule list such that JavaScript environments with small stacks can use the compiler. Note: The above changes are not included in 0.5.0, because they were backported. ### 0.4.25 (2018-09-12) Important Bugfixes: * Code Generator: Properly perform cleanup for exponentiation and non-256 bit types. * Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values. * Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values. * Parser: Consider all unicode line terminators (LF, VF, FF, CR, NEL, LS, PS) for single-line comments and string literals. They are invalid in strings and will end comments. * Parser: Disallow unterminated multi-line comments at the end of input. * Parser: Treat ``/** /`` as unterminated multi-line comment. ### 0.4.24 (2018-05-16) Language Features: * Code Generator: Use native shift instructions on target Constantinople. * General: Allow multiple variables to be declared as part of a tuple assignment, e.g. ``(uint a, uint b) = ...``. * General: Remove deprecated ``constant`` as function state modifier from documentation and tests (but still leave it as a valid feature). * Type Checker: Deprecate the ``years`` unit denomination and raise a warning for it (or an error as experimental 0.5.0 feature). * Type Checker: Make literals (without explicit type casting) an error for tight packing as experimental 0.5.0 feature. * Type Checker: Warn about wildcard tuple assignments (this will turn into an error with version 0.5.0). * Type Checker: Warn when ``keccak256``, ``sha256`` and ``ripemd160`` are not used with a single bytes argument (suggest to use ``abi.encodePacked(...)``). This will turn into an error with version 0.5.0. Compiler Features: * Build System: Update internal dependency of jsoncpp to 1.8.4, which introduces more strictness and reduces memory usage. * Control Flow Graph: Add Control Flow Graph as analysis structure. * Control Flow Graph: Warn about returning uninitialized storage pointers. * Gas Estimator: Only explore paths with higher gas costs. This reduces accuracy but greatly improves the speed of gas estimation. * Optimizer: Remove unnecessary masking of the result of known short instructions (``ADDRESS``, ``CALLER``, ``ORIGIN`` and ``COINBASE``). * Parser: Display nicer error messages by showing the actual tokens and not internal names. * Parser: Use the entire location of the token instead of only its starting position as source location for parser errors. * SMT Checker: Support state variables of integer and bool type. Bugfixes: * Code Generator: Fix ``revert`` with reason coming from a state or local string variable. * Type Checker: Show proper error when trying to ``emit`` a non-event. * Type Checker: Warn about empty tuple components (this will turn into an error with version 0.5.0). * Type Checker: The ABI encoding functions are pure and thus can be used for constants. ### 0.4.23 (2018-04-19) Features: * Build system: Support Ubuntu Bionic. * SMTChecker: Integration with CVC4 SMT solver * Syntax Checker: Warn about functions named "constructor". Bugfixes: * Type Checker: Improve error message for failed function overload resolution. * Type Checker: Do not complain about new-style constructor and fallback function to have the same name. * Type Checker: Detect multiple constructor declarations in the new syntax and old syntax. * Type Checker: Explicit conversion of ``bytesXX`` to ``contract`` is properly disallowed. ### 0.4.22 (2018-04-16) Features: * Code Generator: Initialize arrays without using ``msize()``. * Code Generator: More specialized and thus optimized implementation for ``x.push(...)`` * Commandline interface: Error when missing or inaccessible file detected. Suppress it with the ``--ignore-missing`` flag. * Constant Evaluator: Fix evaluation of single element tuples. * General: Add encoding routines ``abi.encodePacked``, ``abi.encode``, ``abi.encodeWithSelector`` and ``abi.encodeWithSignature``. * General: Add global function ``gasleft()`` and deprecate ``msg.gas``. * General: Add global function ``blockhash(uint)`` and deprecate ``block.hash(uint)``. * General: Allow providing reason string for ``revert()`` and ``require()``. * General: Introduce new constructor syntax using the ``constructor`` keyword as experimental 0.5.0 feature. * General: Limit the number of errors output in a single run to 256. * General: Support accessing dynamic return data in post-byzantium EVMs. * General: Allow underscores in numeric and hex literals to separate thousands and quads. * Inheritance: Error when using empty parentheses for base class constructors that require arguments as experimental 0.5.0 feature. * Inheritance: Error when using no parentheses in modifier-style constructor calls as experimental 0.5.0 feature. * Interfaces: Allow overriding external functions in interfaces with public in an implementing contract. * Optimizer: Optimize ``SHL`` and ``SHR`` only involving constants (Constantinople only). * Optimizer: Remove useless ``SWAP1`` instruction preceding a commutative instruction (such as ``ADD``, ``MUL``, etc). * Optimizer: Replace comparison operators (``LT``, ``GT``, etc) with opposites if preceded by ``SWAP1``, e.g. ``SWAP1 LT`` is replaced with ``GT``. * Optimizer: Optimize across ``mload`` if ``msize()`` is not used. * Static Analyzer: Error on duplicated super constructor calls as experimental 0.5.0 feature. * Syntax Checker: Issue warning for empty structs (or error as experimental 0.5.0 feature). * Syntax Checker: Warn about modifiers on functions without implementation (this will turn into an error with version 0.5.0). * Syntax Tests: Add source locations to syntax test expectations. * Type Checker: Improve documentation and warnings for accessing contract members inherited from ``address``. Bugfixes: * Code Generator: Allow ``block.blockhash`` without being called. * Code Generator: Do not include internal functions in the runtime bytecode which are only referenced in the constructor. * Code Generator: Properly skip unneeded storage array cleanup when not reducing length. * Code Generator: Bugfix in modifier lookup in libraries. * Code Generator: Implement packed encoding of external function types. * Code Generator: Treat empty base constructor argument list as not provided. * Code Generator: Properly force-clean bytesXX types for shortening conversions. * Commandline interface: Fix error messages for imported files that do not exist. * Commandline interface: Support ``--evm-version constantinople`` properly. * DocString Parser: Fix error message for empty descriptions. * Gas Estimator: Correctly ignore costs of fallback function for other functions. * JSON AST: Remove storage qualifier for type name strings. * Parser: Fix internal compiler error when parsing ``var`` declaration without identifier. * Parser: Fix parsing of getters for function type variables. * Standard JSON: Support ``constantinople`` as ``evmVersion`` properly. * Static Analyzer: Fix non-deterministic order of unused variable warnings. * Static Analyzer: Invalid arithmetic with constant expressions causes errors. * Type Checker: Fix detection of recursive structs. * Type Checker: Fix asymmetry bug when comparing with literal numbers. * Type System: Improve error message when attempting to shift by a fractional amount. * Type System: Make external library functions accessible. * Type System: Prevent encoding of weird types. * Type System: Restrict rational numbers to 4096 bits. ### 0.4.21 (2018-03-07) Features: * Code Generator: Assert that ``k != 0`` for ``mulmod(a, b, k)`` and ``addmod(a, b, k)`` as experimental 0.5.0 feature. * Code Generator: Do not retain any gas in calls (except if EVM version is set to homestead). * Code Generator: Use ``STATICCALL`` opcode for calling ``view`` and ``pure`` functions as experimental 0.5.0 feature. * General: C99/C++-style scoping rules (instead of JavaScript function scoping) take effect as experimental v0.5.0 feature. * General: Improved messaging when error spans multiple lines of a sourcefile * General: Support and recommend using ``emit EventName();`` to call events explicitly. * Inline Assembly: Enforce strict mode as experimental 0.5.0 feature. * Interface: Provide ability to select target EVM version (homestead or byzantium, with byzantium being the default). * Standard JSON: Reject badly formatted invalid JSON inputs. * Type Checker: Disallow uninitialized storage pointers as experimental 0.5.0 feature. * Syntax Analyser: Do not warn about experimental features if they do not concern code generation. * Syntax Analyser: Do not warn about ``pragma experimental "v0.5.0"`` and do not set the experimental flag in the bytecode for this. * Syntax Checker: Mark ``throw`` as an error as experimental 0.5.0 feature. * Syntax Checker: Issue error if no visibility is specified on contract functions as experimental 0.5.0 feature. * Syntax Checker: Issue warning when using overloads of ``address`` on contract instances. * Type Checker: disallow combining hex numbers and unit denominations as experimental 0.5.0 feature. Bugfixes: * Assembly: Raise error on oversized number literals in assembly. * JSON-AST: Add "documentation" property to function, event and modifier definition. * Resolver: Properly determine shadowing for imports with aliases. * Standalone Assembly: Do not ignore input after closing brace of top level block. * Standard JSON: Catch errors properly when invalid "sources" are passed. * Standard JSON: Ensure that library addresses supplied are of correct length and hex prefixed. * Type Checker: Properly detect which array and struct types are unsupported by the old ABI encoder. * Type Checker: Properly warn when using ``_offset`` and ``_slot`` for constants in inline assembly. * Commandline interface: throw error if option is unknown ### 0.4.20 (2018-02-14) Features: * Code Generator: Prevent non-view functions in libraries from being called directly (as opposed to via delegatecall). * Commandline interface: Support strict mode of assembly (disallowing jumps, instructional opcodes, etc) with the ``--strict-assembly`` switch. * Inline Assembly: Issue warning for using jump labels (already existed for jump instructions). * Inline Assembly: Support some restricted tokens (return, byte, address) as identifiers in Iulia mode. * Optimiser: Replace ``x % 2**i`` by ``x & (2**i-1)``. * Resolver: Continue resolving references after the first error. * Resolver: Suggest alternative identifiers if a given identifier is not found. * SMT Checker: Take if-else branch conditions into account in the SMT encoding of the program variables. * Syntax Checker: Deprecate the ``var`` keyword (and mark it an error as experimental 0.5.0 feature). * Type Checker: Allow `this.f.selector` to be a pure expression. * Type Checker: Issue warning for using ``public`` visibility for interface functions. * Type Checker: Limit the number of warnings raised for creating abstract contracts. Bugfixes: * Error Output: Truncate huge number literals in the middle to avoid output blow-up. * Parser: Disallow event declarations with no parameter list. * Standard JSON: Populate the ``sourceLocation`` field in the error list. * Standard JSON: Properly support contract and library file names containing a colon (such as URLs). * Type Checker: Suggest the experimental ABI encoder if using ``struct``s as function parameters (instead of an internal compiler error). * Type Checker: Improve error message for wrong struct initialization. ### 0.4.19 (2017-11-30) Features: * Code Generator: New ABI decoder which supports structs and arbitrarily nested arrays and checks input size (activate using ``pragma experimental ABIEncoderV2;``). * General: Allow constant variables to be used as array length. * Inline Assembly: ``if`` statement. * Standard JSON: Support the ``outputSelection`` field for selective compilation of target artifacts. * Syntax Checker: Turn the usage of ``callcode`` into an error as experimental 0.5.0 feature. * Type Checker: Improve address checksum warning. * Type Checker: More detailed errors for invalid array lengths (such as division by zero). Bugfixes: ### 0.4.18 (2017-10-18) Features: * Code Generator: Always use all available gas for calls as experimental 0.5.0 feature (previously, some amount was retained in order to work in pre-Tangerine-Whistle EVM versions) * Parser: Better error message for unexpected trailing comma in parameter lists. * Standard JSON: Support the ``outputSelection`` field for selective compilation of supplied sources. * Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature. * Type Checker: Disallow non-pure constant state variables as experimental 0.5.0 feature. * Type Checker: Do not add members of ``address`` to contracts as experimental 0.5.0 feature. * Type Checker: Force interface functions to be external as experimental 0.5.0 feature. * Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature. * Compiler Interface: Better formatted error message for long source snippets Bugfixes: * Code Generator: Allocate one byte per memory byte array element instead of 32. * Code Generator: Do not accept data with less than four bytes (truncated function signature) for regular function calls - fallback function is invoked instead. * Optimizer: Remove unused stack computation results. * Parser: Fix source location of VariableDeclarationStatement. * Type Checker: Allow ``gas`` in view functions. * Type Checker: Do not mark event parameters as shadowing state variables. * Type Checker: Prevent duplicate event declarations. * Type Checker: Properly check array length and don't rely on an assertion in code generation. * Type Checker: Properly support overwriting members inherited from ``address`` in a contract (such as ``balance``, ``transfer``, etc.) * Type Checker: Validate each number literal in tuple expressions even if they are not assigned from. ### 0.4.17 (2017-09-21) Features: * Assembly Parser: Support multiple assignment (``x, y := f()``). * Code Generator: Keep a single copy of encoding functions when using the experimental "ABIEncoderV2". * Code Generator: Partial support for passing ``structs`` as arguments and return parameters (requires ``pragma experimental ABIEncoderV2;`` for now). * General: Support ``pragma experimental "v0.5.0";`` to activate upcoming breaking changes. * General: Added ``.selector`` member on external function types to retrieve their signature. * Optimizer: Add new optimization step to remove unused ``JUMPDEST``s. * Static Analyzer: Warn when using deprecated builtins ``sha3`` and ``suicide`` (replaced by ``keccak256`` and ``selfdestruct``, introduced in 0.4.2 and 0.2.0, respectively). * Syntax Checker: Warn if no visibility is specified on contract functions. * Type Checker: Display helpful warning for unused function arguments/return parameters. * Type Checker: Do not show the same error multiple times for events. * Type Checker: Greatly reduce the number of duplicate errors shown for duplicate constructors and functions. * Type Checker: Warn on using literals as tight packing parameters in ``keccak256``, ``sha3``, ``sha256`` and ``ripemd160``. * Type Checker: Enforce ``view`` and ``pure``. * Type Checker: Enforce ``view`` / ``constant`` with error as experimental 0.5.0 feature. * Type Checker: Enforce fallback functions to be ``external`` as experimental 0.5.0 feature. Bugfixes: * ABI JSON: Include all overloaded events. * Parser: Crash fix related to parseTypeName. * Type Checker: Allow constant byte arrays. ### 0.4.16 (2017-08-24) Features: * ABI JSON: Include new field ``stateMutability`` with values ``pure``, ``view``, ``nonpayable`` and ``payable``. * Analyzer: Experimental partial support for Z3 SMT checker ("SMTChecker"). * Build System: Shared libraries (``libsolutil``, ``libevmasm``, ``libsolidity`` and ``liblll``) are no longer produced during the build process. * Code generator: Experimental new implementation of ABI encoder that can encode arbitrarily nested arrays ("ABIEncoderV2") * Metadata: Store experimental flag in metadata CBOR. * Parser: Display previous visibility specifier in error if multiple are found. * Parser: Introduce ``pure`` and ``view`` keyword for functions, ``constant`` remains an alias for ``view`` and pureness is not enforced yet, so use with care. * Static Analyzer: Warn about large storage structures. * Syntax Checker: Support ``pragma experimental ;`` to turn on experimental features. * Type Checker: More detailed error message for invalid overrides. * Type Checker: Warn about shifting a literal. Bugfixes: * Assembly Parser: Be more strict about number literals. * Assembly Parser: Limit maximum recursion depth. * Parser: Enforce commas between array and tuple elements. * Parser: Limit maximum recursion depth. * Type Checker: Crash fix related to ``using``. * Type Checker: Disallow constructors in libraries. * Type Checker: Reject the creation of interface contracts using the ``new`` statement. ### 0.4.15 (2017-08-08) Features: * Type Checker: Show unimplemented function if trying to instantiate an abstract class. Bugfixes: * Code Generator: ``.delegatecall()`` should always return execution outcome. * Code Generator: Provide "new account gas" for low-level ``callcode`` and ``delegatecall``. * Type Checker: Constructors must be implemented if declared. * Type Checker: Disallow the ``.gas()`` modifier on ``ecrecover``, ``sha256`` and ``ripemd160``. * Type Checker: Do not mark overloaded functions as shadowing other functions. * Type Checker: Internal library functions must be implemented if declared. ### 0.4.14 (2017-07-31) Features: * C API (``jsonCompiler``): Export the ``license`` method. * Code Generator: Optimise the fallback function, by removing a useless jump. * Inline Assembly: Show useful error message if trying to access calldata variables. * Inline Assembly: Support variable declaration without initial value (defaults to 0). * Metadata: Only include files which were used to compile the given contract. * Type Checker: Disallow value transfers to contracts without a payable fallback function. * Type Checker: Include types in explicit conversion error message. * Type Checker: Raise proper error for arrays too large for ABI encoding. * Type checker: Warn if using ``this`` in a constructor. * Type checker: Warn when existing symbols, including builtins, are overwritten. Bugfixes: * Code Generator: Properly clear return memory area for ecrecover. * Type Checker: Fix crash for some assignment to non-lvalue. * Type Checker: Fix invalid "specify storage keyword" warning for reference members of structs. * Type Checker: Mark modifiers as internal. * Type Checker: Re-allow multiple mentions of the same modifier per function. ### 0.4.13 (2017-07-06) Features: * Syntax Checker: Deprecated "throw" in favour of require(), assert() and revert(). * Type Checker: Warn if a local storage reference variable does not explicitly use the keyword ``storage``. Bugfixes: * Code Generator: Correctly unregister modifier variables. * Compiler Interface: Only output AST if analysis was successful. * Error Output: Do not omit the error type. ### 0.4.12 (2017-07-03) Features: * Assembly: Add ``CREATE2`` (EIP86), ``STATICCALL`` (EIP214), ``RETURNDATASIZE`` and ``RETURNDATACOPY`` (EIP211) instructions. * Assembly: Display auxiliary data in the assembly output. * Assembly: Renamed ``SHA3`` to ``KECCAK256``. * AST: export all attributes to JSON format. * C API (``jsonCompiler``): Use the Standard JSON I/O internally. * Code Generator: Added the Whiskers template system. * Inline Assembly: ``for`` and ``switch`` statements. * Inline Assembly: Function definitions and function calls. * Inline Assembly: Introduce ``keccak256`` as an opcode. ``sha3`` is still a valid alias. * Inline Assembly: Present proper error message when not supplying enough arguments to a functional instruction. * Inline Assembly: Warn when instructions shadow Solidity variables. * Inline Assembly: Warn when using ``jump``s. * Remove obsolete Why3 output. * Type Checker: Enforce strict UTF-8 validation. * Type Checker: Warn about copies in storage that might overwrite unexpectedly. * Type Checker: Warn about type inference from literal numbers. * Static Analyzer: Warn about deprecation of ``callcode``. Bugfixes: * Assembly: mark ``MLOAD`` to have side effects in the optimiser. * Code Generator: Fix ABI encoding of empty literal string. * Code Generator: Fix negative stack size checks. * Code generator: Use ``REVERT`` instead of ``INVALID`` for generated input validation routines. * Inline Assembly: Enforce function arguments when parsing functional instructions. * Optimizer: Disallow optimizations involving ``MLOAD`` because it changes ``MSIZE``. * Static Analyzer: Unused variable warnings no longer issued for variables used inside inline assembly. * Type Checker: Fix address literals not being treated as compile-time constants. * Type Checker: Fixed crash concerning non-callable types. * Type Checker: Fixed segfault with constant function parameters * Type Checker: Disallow comparisons between mapping and non-internal function types. * Type Checker: Disallow invoking the same modifier multiple times. * Type Checker: Do not treat strings that look like addresses as addresses. * Type Checker: Support valid, but incorrectly rejected UTF-8 sequences. ### 0.4.11 (2017-05-03) Features: * Implement the Standard JSON Input / Output API * Support ``interface`` contracts. * C API (``jsonCompiler``): Add the ``compileStandard()`` method to process a Standard JSON I/O. * Commandline interface: Add the ``--standard-json`` parameter to process a Standard JSON I/O. * Commandline interface: Support ``--allow-paths`` to define trusted import paths. Note: the path(s) of the supplied source file(s) is always trusted. * Inline Assembly: Storage variable access using ``_slot`` and ``_offset`` suffixes. * Inline Assembly: Disallow blocks with unbalanced stack. * Static analyzer: Warn about statements without effects. * Static analyzer: Warn about unused local variables, parameters, and return parameters. * Syntax checker: issue deprecation warning for unary '+' Bugfixes: * Assembly output: Implement missing AssemblyItem types. * Compiler interface: Fix a bug where source indexes could be inconsistent between Solidity compiled with different compilers (clang vs. gcc) or compiler settings. The bug was visible in AST and source mappings. * Gas Estimator: Reflect the most recent fee schedule. * Type system: Contract inheriting from base with unimplemented constructor should be abstract. * Optimizer: Number representation bug in the constant optimizer fixed. ### 0.4.10 (2017-03-15) Features: * Add ``assert(condition)``, which throws if condition is false (meant for internal errors). * Add ``require(condition)``, which throws if condition is false (meant for invalid input). * Commandline interface: Do not overwrite files unless forced. * Introduce ``.transfer(value)`` for sending Ether. * Code generator: Support ``revert()`` to abort with rolling back, but not consuming all gas. * Inline assembly: Support ``revert`` (EIP140) as an opcode. * Parser: Support scientific notation in numbers (e.g. ``2e8`` and ``200e-2``). * Type system: Support explicit conversion of external function to address. * Type system: Warn if base of exponentiation is literal (result type might be unexpected). * Type system: Warn if constant state variables are not compile-time constants. Bugfixes: * Commandline interface: Always escape filenames (replace ``/``, ``:`` and ``.`` with ``_``). * Commandline interface: Do not try creating paths ``.`` and ``..``. * Commandline interface: Allow long library names. * Parser: Disallow octal literals. * Type system: Fix a crash caused by continuing on fatal errors in the code. * Type system: Disallow compound assignment for tuples. * Type system: Detect cyclic dependencies between constants. * Type system: Disallow arrays with negative length. * Type system: Fix a crash related to invalid binary operators. * Type system: Disallow ``var`` declaration with empty tuple type. * Type system: Correctly convert function argument types to pointers for member functions. * Type system: Move privateness of constructor into AST itself. * Inline assembly: Charge one stack slot for non-value types during analysis. * Assembly output: Print source location before the operation it refers to instead of after. * Optimizer: Stop trying to optimize tricky constants after a while. ### 0.4.9 (2017-01-31) Features: * Compiler interface: Contracts and libraries can be referenced with a ``file:`` prefix to make them unique. * Compiler interface: Report source location for "stack too deep" errors. * AST: Use deterministic node identifiers. * Inline assembly: introduce ``invalid`` (EIP141) as an opcode. * Type system: Introduce type identifier strings. * Type checker: Warn about invalid checksum for addresses and deduce type from valid ones. * Metadata: Do not include platform in the version number. * Metadata: Add option to store sources as literal content. * Code generator: Extract array utils into low-level functions. * Code generator: Internal errors (array out of bounds, etc.) now cause a reversion by using an invalid instruction (0xfe - EIP141) instead of an invalid jump. Invalid jump is still kept for explicit throws. Bugfixes: * Code generator: Allow recursive structs. * Inline assembly: Disallow variables named like opcodes. * Type checker: Allow multiple events of the same name (but with different arities or argument types) * Natspec parser: Fix error with ``@param`` parsing and whitespace. ### 0.4.8 (2017-01-13) Features: * Optimiser: Performance improvements. * Output: Print assembly in new standardized Solidity assembly format. Bugfixes: * Remappings: Prefer longer context over longer prefix. * Type checker, code generator: enable access to events of base contracts' names. * Imports: ``import ".dir/a"`` is not a relative path. Relative paths begin with directory ``.`` or ``..``. * Type checker, disallow inheritances of different kinds (e.g. a function and a modifier) of members of the same name ### 0.4.7 (2016-12-15) Features: * Bitshift operators. * Type checker: Warn when ``msg.value`` is used in non-payable function. * Code generator: Inject the Swarm hash of a metadata file into the bytecode. * Code generator: Replace expensive memcpy precompile by simple assembly loop. * Optimizer: Some dead code elimination. Bugfixes: * Code generator: throw if calling the identity precompile failed during memory (array) copying. * Type checker: string literals that are not valid UTF-8 cannot be converted to string type * Code generator: any non-zero value given as a boolean argument is now converted into 1. * AST Json Converter: replace ``VariableDefinitionStatement`` nodes with ``VariableDeclarationStatement`` * AST Json Converter: fix the camel case in ``ElementaryTypeNameExpression`` * AST Json Converter: replace ``public`` field with ``visibility`` in the function definition nodes ### 0.4.6 (2016-11-22) Bugfixes: * Optimizer: Knowledge about state was not correctly cleared for JUMPDESTs (introduced in 0.4.5) ### 0.4.5 (2016-11-21) Features: * Function types * Do-while loops: support for a ``do while ();`` control structure * Inline assembly: support ``invalidJumpLabel`` as a jump label. * Type checker: now more eagerly searches for a common type of an inline array with mixed types * Code generator: generates a runtime error when an out-of-range value is converted into an enum type. Bugfixes: * Inline assembly: calculate stack height warning correctly even when local variables are used. * Code generator: check for value transfer in non-payable constructors. * Parser: disallow empty enum definitions. * Type checker: disallow conversion between different enum types. * Interface JSON: do not include trailing new line. ### 0.4.4 (2016-10-31) Bugfixes: * Type checker: forbid signed exponential that led to an incorrect use of EXP opcode. * Code generator: properly clean higher order bytes before storing in storage. ### 0.4.3 (2016-10-25) Features: * Inline assembly: support both ``suicide`` and ``selfdestruct`` opcodes (note: ``suicide`` is deprecated). * Inline assembly: issue warning if stack is not balanced after block. * Include ``keccak256()`` as an alias to ``sha3()``. * Support shifting constant numbers. Bugfixes: * Commandline interface: Disallow unknown options in ``solc``. * Name resolver: Allow inheritance of ``enum`` definitions. * Type checker: Proper type checking for bound functions. * Type checker: fixed crash related to invalid fixed point constants * Type checker: fixed crash related to invalid literal numbers. * Type checker: ``super.x`` does not look up ``x`` in the current contract. * Code generator: expect zero stack increase after ``super`` as an expression. * Code generator: fix an internal compiler error for ``L.Foo`` for ``enum Foo`` defined in library ``L``. * Code generator: allow inheritance of ``enum`` definitions. * Inline assembly: support the ``address`` opcode. * Inline assembly: fix parsing of assignment after a label. * Inline assembly: external variables of unsupported type (such as ``this``, ``super``, etc.) are properly detected as unusable. * Inline assembly: support variables within modifiers. * Optimizer: fix related to stale knowledge about SHA3 operations ### 0.4.2 (2016-09-17) Bugfixes: * Code Generator: Fix library functions being called from payable functions. * Type Checker: Fixed a crash about invalid array types. * Code Generator: Fixed a call gas bug that became visible after version 0.4.0 for calls where the output is larger than the input. ### 0.4.1 (2016-09-09) * Build System: Fixes to allow library compilation. ### 0.4.0 (2016-09-08) This release deliberately breaks backwards compatibility mostly to enforce some safety features. The most important change is that you have to explicitly specify if functions can receive ether via the ``payable`` modifier. Furthermore, more situations cause exceptions to be thrown. Minimal changes to be made for upgrade: - Add ``payable`` to all functions that want to receive Ether (including the constructor and the fallback function). - Change ``_`` to ``_;`` in modifiers. - Add version pragma to each file: ``pragma solidity ^0.4.0;`` Breaking Changes: * Source files have to specify the compiler version they are compatible with using e.g. ``pragma solidity ^0.4.0;`` or ``pragma solidity >=0.4.0 <0.4.8;`` * Functions that want to receive Ether have to specify the new ``payable`` modifier (otherwise they throw). * Contracts that want to receive Ether with a plain "send" have to implement a fallback function with the ``payable`` modifier. Contracts now throw if no payable fallback function is defined and no function matches the signature. * Failing contract creation through "new" throws. * Division / modulus by zero throws. * Function call throws if target contract does not have code * Modifiers are required to contain ``_`` (use ``if (false) _`` as a workaround if needed). * Modifiers: return does not skip part in modifier after ``_``. * Placeholder statement `_` in modifier now requires explicit `;`. * ``ecrecover`` now returns zero if the input is malformed (it previously returned garbage). * The ``constant`` keyword cannot be used for constructors or the fallback function. * Removed ``--interface`` (Solidity interface) output option * JSON AST: General cleanup, renamed many nodes to match their C++ names. * JSON output: ``srcmap-runtime`` renamed to ``srcmapRuntime``. * Moved (and reworked) standard library contracts from inside the compiler to github.com/ethereum/solidity/std (``import "std";`` or ``import owned;`` do not work anymore). * Confusing and undocumented keyword ``after`` was removed. * New reserved words: ``abstract``, ``hex``, ``interface``, ``payable``, ``pure``, ``static``, ``view``. Features: * Hexadecimal string literals: ``hex"ab1248fe"`` * Internal: Inline assembly usable by the code generator. * Commandline interface: Using ``-`` as filename allows reading from stdin. * Interface JSON: Fallback function is now part of the ABI. * Interface: Version string now *SemVer* compatible. * Code generator: Do not provide "new account gas" if we know the called account exists. Bugfixes: * JSON AST: Nodes were added at wrong parent * Why3 translator: Crash fix for exponentiation * Commandline Interface: linking libraries with underscores in their name. * Type Checker: Fallback function cannot return data anymore. * Code Generator: Fix crash when ``sha3()`` was used on unsupported types. * Code Generator: Manually set gas stipend for ``.send(0)``. Lots of changes to the documentation mainly by voluntary external contributors. ### 0.3.6 (2016-08-10) Features: * Formal verification: Take external effects on a contract into account. * Type Checker: Warning about unused return value of low-level calls and send. * Output: Source location and node id as part of AST output * Output: Source location mappings for bytecode * Output: Formal verification as part of json compiler output. Bugfixes: * Commandline Interface: Do not crash if input is taken from stdin. * Scanner: Correctly support unicode escape codes in strings. * JSON output: Fix error about relative / absolute source file names. * JSON output: Fix error about invalid utf8 strings. * Code Generator: Dynamic allocation of empty array caused infinite loop. * Code Generator: Correctly calculate gas requirements for memcpy precompile. * Optimizer: Clear known state if two code paths are joined. ### 0.3.5 (2016-06-10) Features: * Context-dependent path remappings (different modules can use the same library in different versions) Bugfixes: * Type Checking: Dynamic return types were removed when fetching data from external calls, now they are replaced by an "unusable" type. * Type Checking: Overrides by constructors were considered making a function non-abstract. ### 0.3.4 (2016-05-31) No change outside documentation. ### 0.3.3 (2016-05-27) * Allow internal library functions to be called (by "inlining") * Fractional/rational constants (only usable with fixed point types, which are still in progress) * Inline assembly has access to internal functions (as jump labels) * Running `solc` without arguments on a terminal will print help. * Bugfix: Remove some non-determinism in code generation. * Bugfix: Corrected usage of not / bnot / iszero in inline assembly * Bugfix: Correctly clean bytesNN types before comparison ### 0.3.2 (2016-04-18) * Bugfix: Inline assembly parser: `byte` opcode was unusable * Bugfix: Error reporting: tokens for variably-sized types were not converted to string properly * Bugfix: Dynamic arrays of structs were not deleted correctly. * Bugfix: Static arrays in constructor parameter list were not decoded correctly. ### 0.3.1 (2016-03-31) * Inline assembly * Bugfix: Code generation: array access with narrow types did not clean higher order bits * Bugfix: Error reporting: error reporting with unknown source location caused a crash ### 0.3.0 (2016-03-11) BREAKING CHANGES: * Added new keywords `assembly`, `foreign`, `fixed`, `ufixed`, `fixedNxM`, `ufixedNxM` (for various values of M and N), `timestamp` * Number constant division does not round to integer, but to a fixed point type (e.g. `1 / 2 != 1`, but `1 / 2 == 0.5`). * Library calls now default to use DELEGATECALL (e.g. called library functions see the same value as the calling function for `msg.value` and `msg.sender`). * `
.delegatecall` as a low-level calling interface Bugfixes: * Fixed a bug in the optimizer that resulted in comparisons being wrong. ### 0.2.2 (2016-02-17) * Index access for types `bytes1`, ..., `bytes32` (only read access for now). * Bugfix: Type checker crash for wrong number of base constructor parameters. ### 0.2.1 (2016-01-30) * Inline arrays, i.e. `var y = [1,x,f()];` if there is a common type for `1`, `x` and `f()`. Note that the result is always a fixed-length memory array and conversion to dynamic-length memory arrays is not yet possible. * Import similar to ECMAScript6 import (`import "abc.sol" as d` and `import {x, y} from "abc.sol"`). * Commandline compiler solc automatically resolves missing imports and allows for "include directories". * Conditional: `x ? y : z` * Bugfix: Fixed several bugs where the optimizer generated invalid code. * Bugfix: Enums and structs were not accessible to other contracts. * Bugfix: Fixed segfault connected to function parameter types, appeared during gas estimation. * Bugfix: Type checker crash for wrong number of base constructor parameters. * Bugfix: Allow function overloads with different array types. * Bugfix: Allow assignments of type `(x) = 7`. * Bugfix: Type `uint176` was not available. * Bugfix: Fixed crash during type checking concerning constructor calls. * Bugfix: Fixed crash during code generation concerning invalid accessors for struct types. * Bugfix: Fixed crash during code generating concerning computing a hash of a struct type. ### 0.2.0 (2015-12-02) * **Breaking Change**: `new ContractName.value(10)()` has to be written as `(new ContractName).value(10)()` * Added `selfdestruct` as an alias for `suicide`. * Allocation of memory arrays using `new`. * Binding library functions to types via `using x for y` * `addmod` and `mulmod` (modular addition and modular multiplication with arbitrary intermediate precision) * Bugfix: Constructor arguments of fixed array type were not read correctly. * Bugfix: Memory allocation of structs containing arrays or strings. * Bugfix: Data location for explicit memory parameters in libraries was set to storage. ### 0.1.7 (2015-11-17) * Improved error messages for unexpected tokens. * Proof-of-concept transcompilation to why3 for formal verification of contracts. * Bugfix: Arrays (also strings) as indexed parameters of events. * Bugfix: Writing to elements of `bytes` or `string` overwrite others. * Bugfix: "Successor block not found" on Windows. * Bugfix: Using string literals in tuples. * Bugfix: Cope with invalid commit hash in version for libraries. * Bugfix: Some test framework fixes on windows. ### 0.1.6 (2015-10-16) * `.push()` for dynamic storage arrays. * Tuple expressions (`(1,2,3)` or `return (1,2,3);`) * Declaration and assignment of multiple variables (`var (x,y,) = (1,2,3,4,5);` or `var (x,y) = f();`) * Destructuring assignment (`(x,y,) = (1,2,3)`) * Bugfix: Internal error about usage of library function with invalid types. * Bugfix: Correctly parse `Library.structType a` at statement level. * Bugfix: Correctly report source locations of parenthesized expressions (as part of "tuple" story). ### 0.1.5 (2015-10-07) * Breaking change in storage encoding: Encode short byte arrays and strings together with their length in storage. * Report warnings * Allow storage reference types for public library functions. * Access to types declared in other contracts and libraries via `.`. * Version stamp at beginning of runtime bytecode of libraries. * Bugfix: Problem with initialized string state variables and dynamic data in constructor. * Bugfix: Resolve dependencies concerning `new` automatically. * Bugfix: Allow four indexed arguments for anonymous events. * Bugfix: Detect too large integer constants in functions that accept arbitrary parameters. ### 0.1.4 (2015-09-30) * Bugfix: Returning fixed-size arrays. * Bugfix: combined-json output of solc. * Bugfix: Accessing fixed-size array return values. * Bugfix: Disallow assignment from literal strings to storage pointers. * Refactoring: Move type checking into its own module. ### 0.1.3 (2015-09-25) * `throw` statement. * Libraries that contain functions which are called via CALLCODE. * Linker stage for compiler to insert other contract's addresses (used for libraries). * Compiler option to output runtime part of contracts. * Compile-time out of bounds check for access to fixed-size arrays by integer constants. * Version string includes libevmasm/libethereum's version (contains the optimizer). * Bugfix: Accessors for constant public state variables. * Bugfix: Propagate exceptions in clone contracts. * Bugfix: Empty single-line comments are now treated properly. * Bugfix: Properly check the number of indexed arguments for events. * Bugfix: Strings in struct constructors. ### 0.1.2 (2015-08-20) * Improved commandline interface. * Explicit conversion between `bytes` and `string`. * Bugfix: Value transfer used in clone contracts. * Bugfix: Problem with strings as mapping keys. * Bugfix: Prevent usage of some operators. ### 0.1.1 (2015-08-04) * Strings can be used as mapping keys. * Clone contracts. * Mapping members are skipped for structs in memory. * Use only a single stack slot for storage references. * Improved error message for wrong argument count. (#2456) * Bugfix: Fix comparison between `bytesXX` types. (#2087) * Bugfix: Do not allow floats for integer literals. (#2078) * Bugfix: Some problem with many local variables. (#2478) * Bugfix: Correctly initialise `string` and `bytes` state variables. * Bugfix: Correctly compute gas requirements for callcode. ### 0.1.0 (2015-07-10) ================================================ FILE: LICENSE.txt ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: README.md ================================================ # The Solidity Contract-Oriented Programming Language [![Matrix Chat](https://img.shields.io/badge/Matrix%20-chat-brightgreen?style=plastic&logo=matrix)](https://matrix.to/#/#ethereum_solidity:gitter.im) [![Gitter Chat](https://img.shields.io/badge/Gitter%20-chat-brightgreen?style=plastic&logo=gitter)](https://gitter.im/ethereum/solidity) [![Solidity Forum](https://img.shields.io/badge/Solidity_Forum%20-discuss-brightgreen?style=plastic&logo=discourse)](https://forum.soliditylang.org/) [![X Follow](https://img.shields.io/twitter/follow/solidity_lang?style=plastic&logo=x)](https://X.com/solidity_lang) [![Mastodon Follow](https://img.shields.io/mastodon/follow/000335908?domain=https%3A%2F%2Ffosstodon.org%2F&logo=mastodon&style=plastic)](https://fosstodon.org/@solidity) You can talk to us on Gitter and Matrix, tweet at us on X (previously Twitter) or create a new topic in the Solidity forum. Questions, feedback, and suggestions are welcome! Solidity is a statically-typed, contract-oriented, high-level language for implementing smart contracts on the Ethereum platform. For a good overview and starting point, please check out the official [Solidity Language Portal](https://soliditylang.org). ## Table of Contents - [Background](#background) - [Build and Install](#build-and-install) - [Example](#example) - [Documentation](#documentation) - [Development](#development) - [Maintainers](#maintainers) - [License](#license) - [Security](#security) ## Background Solidity is a statically-typed curly-braces programming language designed for developing smart contracts that run on the Ethereum Virtual Machine. Smart contracts are programs that are executed inside a peer-to-peer network where nobody has special authority over the execution, and thus they allow anyone to implement tokens of value, ownership, voting, and other kinds of logic. When deploying contracts, you should use the latest released version of Solidity. This is because breaking changes, as well as new features and bug fixes, are introduced regularly. We currently use a 0.x version number [to indicate this fast pace of change](https://semver.org/#spec-item-4). ## Build and Install Instructions about how to build and install the Solidity compiler can be found in the [Solidity documentation](https://docs.soliditylang.org/en/latest/installing-solidity.html#building-from-source). ## Example A "Hello World" program in Solidity is of even less use than in other languages, but still: ```solidity // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.9.0; contract HelloWorld { function helloWorld() external pure returns (string memory) { return "Hello, World!"; } } ``` To get started with Solidity, you can use [Remix](https://remix.ethereum.org/), which is a browser-based IDE. Here are some example contracts: 1. [Voting](https://docs.soliditylang.org/en/latest/solidity-by-example.html#voting) 2. [Blind Auction](https://docs.soliditylang.org/en/latest/solidity-by-example.html#blind-auction) 3. [Safe remote purchase](https://docs.soliditylang.org/en/latest/solidity-by-example.html#safe-remote-purchase) 4. [Micropayment Channel](https://docs.soliditylang.org/en/latest/solidity-by-example.html#micropayment-channel) ## Documentation The Solidity documentation is hosted using [Read the Docs](https://docs.soliditylang.org). ## Development Solidity is still under development. Contributions are always welcome! Please follow the [Developer's Guide](https://docs.soliditylang.org/en/latest/contributing.html) if you want to help. You can find our current feature and bug priorities for forthcoming releases in the [projects section](https://github.com/argotorg/solidity/projects). ## Maintainers The Solidity programming language and compiler are open-source community projects governed by a core team. The core team is sponsored by the [Ethereum Foundation](https://ethereum.foundation/). ## License Solidity is licensed under [GNU General Public License v3.0](LICENSE.txt). Some third-party code has its [own licensing terms](cmake/templates/license.h.in). ## Security The security policy may be [found here](SECURITY.md). ================================================ FILE: ReleaseChecklist.md ================================================ # Checklist for making a Solidity release ## Requirements - GitHub account with access to [solidity](https://github.com/argotorg/solidity), [solc-js](https://github.com/argotorg/solc-js), [solc-bin](https://github.com/argotorg/solc-bin), [solidity-website](https://github.com/argotorg/solidity-website). - Personal Access Token (PAT) with `write:packages` scope to access Github's container registry. You can generate one by visiting https://github.com/settings/tokens/new?scopes=write:packages. - Ubuntu/Debian dependencies of the Docker script: `docker-buildx`. - [npm Registry](https://www.npmjs.com) account added as a collaborator for the [`solc` package](https://www.npmjs.com/package/solc). - Access to the [solidity_lang Twitter account](https://twitter.com/solidity_lang). - [Reddit](https://www.reddit.com) account that is at least 10 days old with a minimum of 20 comment karma (`/r/ethereum` requirements). ## Full release ### Pre-flight checks At least a day before the release: - [ ] Run `make linkcheck` from within `docs/` and fix any broken links it finds. Ignore false positives caused by `href` anchors and dummy links not meant to work. **Note**: In order to run the link check, make sure you've built the docs first via `docs.sh`. - [ ] Double-check that [the most recent docs builds at readthedocs](https://readthedocs.org/projects/solidity/builds/) succeeded. - [ ] Make sure that all merged PRs that should have changelog entries do have them. - [ ] Rerun CI on the top commits of main branches in all repositories that do not have daily activity by creating a test branch or PR: - [ ] `solc-js` - [ ] `solc-bin` (make sure the bytecode comparison check did run) - [ ] Verify that the release tarball of `solc-js` works. Bump version locally, add `soljson.js` from CI, build it, compare the file structure with the previous version, install it locally and try to use it. - [ ] Review [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes) to make sure you don't repeat the same mistakes. ### Drafts At least a day before the release: - [ ] Create a draft PR to sort the changelog. - [ ] Create draft PRs to bump version in `solidity` and `solc-js`. **Note**: The `solc-js` PR won't pass CI checks yet because it depends on the soljson binary from `solc-bin`. - [ ] Create a draft of the release on github. - [ ] Create a draft PR to update soliditylang.org. - [ ] Create drafts of blog posts. - [ ] Prepare drafts of Twitter, Reddit and Solidity Forum announcements. ### Website/Blog Updates - [ ] Create a post on [solidity-website](https://github.com/argotorg/solidity-website/tree/main/src/posts) in the `Releases` category and explain some of the new features or concepts. - [ ] Create a post on [solidity-website](https://github.com/argotorg/solidity-website/tree/main/src/posts) in the `Security Alerts` category in case of important bug(s). - [ ] Update the release information section [in the source of soliditylang.org](https://github.com/argotorg/solidity-website/blob/main/src/pages/index.tsx). - [ ] Get the PR(s) for the above reviewed and approved **before the release starts**, but don't merge them yet. ### Changelog - [ ] Ensure that all changelog entries are correctly classified as language or compiler features. - [ ] Sort the changelog entries alphabetically and correct any errors you notice. Commit it. - [ ] Update the changelog to include a release date. - [ ] Run `scripts/update_bugs_by_version.py` to regenerate `bugs_by_version.json` from the changelog and `bugs.json`. Make sure that the resulting `bugs_by_version.json` has a new, empty entry for the new version. - [ ] Commit changes, create a pull request and wait for the tests. Then merge it. - [ ] Copy the changelog into the release blog post. ### Create the Release - [ ] Create a [release on GitHub](https://github.com/argotorg/solidity/releases/new). Set the target to the `develop` branch and the tag to the new version, e.g. `v0.8.5`. Include the following warning: `**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**`. Do not publish it yet - click the `Save draft` button instead. - [ ] Thank voluntary contributors in the GitHub release notes. Use `scripts/list_contributors.sh v` to get initial list of names. Remove different variants of the same name manually before using the output. - [ ] Check that all tests on the latest commit on `develop` are green. - [ ] Click the `Publish release` button on the release page, creating the tag. **Important: Must not be done before all the PRs, including changelog cleanup and date, are merged.** - [ ] Wait for the CI runs on the tag itself. ### Upload Release Artifacts and Publish Binaries - [ ] Take the source tarball (`solidity_x.x.x.tar.gz`) from `c_source_tarball` run of the tagged commit on Circle CI and upload it to the release page. - [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. Make sure it contains five binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux`, `solc-static-linux-arm`, and `soljson.js`. - [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. - [ ] Run `npm install` if you've got a clean checkout of the solc-bin repo. - [ ] Run `npm run update -- --reuse-hashes` in `solc-bin` and verify that the script has updated `list.js`, `list.txt` and `list.json` files correctly and that symlinks to the new release have been added in `solc-bin/wasm/` and `solc-bin/emscripten-wasm32/`. - [ ] Create a pull request in solc-bin and merge. ### Homebrew and MacOS - [ ] Update the version and the hash (`sha256sum solidity_$VERSION.tar.gz`) in the [`solidity` formula in Homebrew core repository](https://github.com/Homebrew/homebrew-core/blob/master/Formula/s/solidity.rb). ### Docker - [ ] Make sure `docker-buildx` is installed. - [ ] Run `echo $GHCR_TOKEN | docker login ghcr.io --username $GH_USERNAME --password-stdin` where `$GH_USERNAME` is your GitHub username and `$GHCR_TOKEN` is a PAT with `write:packages` scope. - [ ] Run `./scripts/docker_deploy_manual.sh v$VERSION`. ### Release solc-js - [ ] Wait until solc-bin was properly deployed. You can test this via remix - a test run through remix is advisable anyway. - [ ] Increment the version number, create a pull request for that, merge it after tests succeeded. - [ ] Create a tag using `git tag --annotate v$VERSION` and push it with `git push --tags`. - [ ] Wait for the CI runs on the tag itself. - [ ] Take the `solc-x.y.z.tgz` artifact from `build-package` run on the tagged commit on Circle CI. Inspect the tarball to ensure that it contains an up-to-date compiler binary (`soljson.js`). - [ ] Run `npm publish solc-x.y.z.tgz` to publish the newly created tarball. ### Documentation - [ ] Make sure the documentation for the new release has been published successfully. Go to the [documentation status page at ReadTheDocs](https://readthedocs.org/projects/solidity/) and verify that the new version is listed, works and is marked as default. - [ ] Remove "still in progress" warning from the [release notes](https://github.com/argotorg/solidity/releases). ### Comms - [ ] Merge the blog posts and website updates prepared for the release. - [ ] Verify that the link to the blog post in [release notes](https://github.com/argotorg/solidity/releases) is not broken. - [ ] Announce on [Twitter](https://twitter.com/solidity_lang), including links to the release and the blog post. - [ ] Announce on [Fosstodon](https://fosstodon.org/@solidity/), including links to the release and the blog post. - [ ] Share the announcement on Reddit in [`/r/ethdev`](https://reddit.com/r/ethdev/), cross-posted to [`/r/ethereum`](https://reddit.com/r/ethereum/). - [ ] Share the announcement on the [Solidity forum](https://forum.soliditylang.org) in the `Announcements` category. - [ ] Share the announcement on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im). - [ ] Share the announcement on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org). ### Post-release - [ ] Create a commit to increase the version number on `develop` in `CMakeLists.txt` and add a new skeleton changelog entry. - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). - [ ] Bump vendored dependencies. - [ ] Lean back, wait for bug reports and repeat from step 1 :). ## Prerelease - [ ] Check that all tests on the latest commit on `develop` or `breaking` branch (whichever was chosen for the prerelease) are green. - [ ] Create a [release on GitHub](https://github.com/argotorg/solidity/releases/new). - Set the target to the `develop` or `breaking` branch and the tag to the new version with a prerelease suffix, e.g. `v0.8.5-pre.6`. Version matches the next release (`develop`) or the next breaking release (`breaking`). The prerelease number in the suffix is 1-based, sequential, resets after a full release and is counted separately for `develop` and `breaking`. - Include the following warning: `**The release is still in progress. You may see broken links and binaries may not yet be available from all sources.**`. - Include the current, incomplete changelog. - Check the `Set as a pre-release` box. - Click the `Publish release` button on the release page, creating the tag. - [ ] Wait for the CI runs on the tag itself. - [ ] Take the source tarball (`solidity_x.x.x-pre.N.tar.gz`) from `c_source_tarball` run of the tagged commit on Circle CI and upload it to the release page. - [ ] Take the `github-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to the release page. Make sure it contains five binaries: `solc-windows.exe`, `solc-macos`, `solc-static-linux`, `solc-static-linux-arm` and `soljson.js`. - [ ] Take the `solc-bin-binaries.tar` tarball from `c_release_binaries` run of the tagged commit on Circle CI and add all binaries from it to solc-bin. - [ ] Run `npm install` if you've got a clean checkout of the solc-bin repo. - [ ] Run `npm run update -- --reuse-hashes` in `solc-bin` and verify that the script has updated `list.js`, `list.txt` and `list.json` files correctly and that symlinks to the new release have been added in `solc-bin/wasm/` and `solc-bin/emscripten-wasm32/`. - [ ] Create a pull request in solc-bin and merge. - [ ] Remove "still in progress" warning from the [release notes](https://github.com/argotorg/solidity/releases). - [ ] Mention it on [Twitter](https://twitter.com/solidity_lang). - [ ] Mention it on [Fosstodon](https://fosstodon.org/@solidity/). - [ ] Mention it on [`#solidity` channel on Matrix](https://matrix.to/#/#ethereum_solidity:gitter.im). - [ ] Mention it on [`#solc-tooling`](https://matrix.to/#/#solc-tooling:matrix.org). - [ ] If anything went wrong this time, mention it in [Learning from Past Releases](https://notes.argot.org/@solidity-release-mistakes). - [ ] Lean back, wait for bug reports and repeat from step 1 :). ================================================ FILE: ReviewChecklist.md ================================================ # PR Review Checklist The Solidity compiler is a critical piece of infrastructure in the Ethereum ecosystem. For this reason, our review process is quite strict and all PRs have to fulfill certain quality expectations and guidelines. The list below is meant to reduce the workload on the core team by helping contributors self-identify and solve common issues before they are pointed out in the review. It is also meant to serve as a final checklist for reviewers to go through before approving a PR. ## Before You Submit a PR - [ ] **Do you have any other open PRs?** Work on a PR is not done until it is merged or closed. Our reviewing capacity is limited, so we require that external contributors work on **no more than one PR at a time**. - If your PR is not getting reviewed, feel free to bring it to our attention on the [#solidity-dev](https://gitter.im/ethereum/solidity-dev) channel. - Unless they were requested, we are going to close any excess PRs, leaving only the earliest one open. You may reopen them, one at a time, when your current PR is done. - [ ] **Is the issue ready to be worked on?** - If the issue does not have a desirability label (`nice to have`, `should have`, `must have eventually`, `must have`, `roadmap`) we have not yet decided whether to implement it. - If the issue has the `needs design` label, we have not yet decided how it should be implemented. - `good first issue candidate` means that the issue will potentially be a `good first issue` eventually but at the moment it is not yet ready to be worked on. - [ ] **Is this a breaking change?** Breaking changes should be based on the `breaking` branch rather than on the `develop` branch. - [ ] **Does the PR actually address the issue?** - [ ] Mention the issue number in the PR description. If the PR solves it completely, use the `Fixes #` form so that Github will close the issue automatically. - [ ] Do not include the issue number in the PR title, branch name or commit description. - [ ] When submitting a PR from a fork **create a branch and give it a descriptive name.** E.g. `fix-array-abi-encoding-bug`. Do not submit PRs directly from the `develop` branch of your fork since it makes rebasing and fetching new changes harder. - [ ] **Does the PR depend on other PRs?** - [ ] If the PR has dependencies, mention them in bold in the description. - [ ] Avoid basing PRs from forks on branches other than `develop` or `breaking` because GitHub closes them when the base branch gets merged. Do this only for PRs created directly in the main repo. - [ ] **Does the PR update test expectations to match the modified code?** If not, your PR will not pass some of the `_soltest_`, jobs in CI. In many cases the expectations can be updated automatically: - `cmdlineTests.sh --update` for command-line tests. - `isoltest --enforce-gas-cost --accept-updates` for soltest-based tests. - If your PR affects gas costs, an extra run of `isoltest --enforce-gas-cost --optimize --accept-updates` is needed to update gas expectations with optimizer enabled. - Review updated files before committing them. **Are expectations correct and do updated tests still serve their purpose?** ## Abandoned PRs - [ ] **Is the submitter still responsive?** - If the PR had no activity from the submitter in the last 2 weeks (despite receiving reviews and our prompts) we consider it abandoned. - [ ] **Is the abandoned PR easy to finish or relevant?** - Apply the `takeover` label if the PR can be finished without significant effort or is something that actually needs to be done right now. Otherwise close it. It can still be taken over later or reopened by the submitter but until then we should not be getting sidetracked by it. ## Light Review Before an in-depth review, it is recommended to give new PRs a quick, superficial review, which is not meant to provide complete and detailed feedback, but instead give the submitter a rough idea if the PR is even on the right track and let them solve the obvious problems on their own. Light review should focus on the following three areas: - [ ] **Are there any obvious mistakes?** Style issues, bad practices, easy to identify bugs, etc. - [ ] **Is there anything missing?** Tests (of the right kind), documentation, etc. Does it address the whole issue? - [ ] **Is it the right solution?** Are there better ways to do this? Is the change even necessary? If the answers above are "Yes, Yes, No", thank the contributor for their effort and **close the PR**. ## Coding Style and Good Practices - [ ] Does the PR follow our [coding style](CODING_STYLE.md)? ### Reliability - [ ] **Use assertions liberally.** If you are certain your assumption will not be broken, prove it with `solAssert()`. - [ ] **Validate inputs and handle errors**. Note that assertions are **not** validation. ### Readability - [ ] **Choose good names.** - [ ] Is the name straightforward to understand? Do you feel the need to jump back to the definition and remind yourself what it was whenever you see it? - [ ] Is the name unambiguous in the context where it is used? - [ ] Avoid abbreviations. - [ ] **Source files, classes and public functions should have docstrings.** - [ ] **Avoid code duplication.** But not fanatically. Minimal amounts of duplication are acceptable if it aids readability. - [ ] **Do not leave dead or commented-out code behind.** You can still see old code in history. If you really have a good reason to do it, always leave a comment explaining what it is and why it is there. - [ ] **Mark hacks as such.** If you have to leave behind a temporary workaround, make sure to include a comment that explains why and in what circumstances it can be removed. Preferably link to an issue you reported upstream. - [ ] **Avoid obvious comments.** - [ ] **Do include comments when the reader may need extra context to understand the code.** ### Commits and PRs - [ ] **Avoid hiding functional changes inside refactors.** E.g. when fixing a small bug, or changing user-visible behavior, put the change in a separate commit. Do not mix it with another change that renames things or reformats the code around, making the fix itself hard to identify. - [ ] **Whenever possible, split off refactors or unrelated changes into separate PRs.** Smaller PRs are easier and quicker to review. Splitting off refactors helps focus on the main point of the PR. ### Common Pitfalls The following points are all covered by the coding style but come up so often that it is worth singling them out here: - [ ] **Always initialize value types in the definition,** even if you are sure you will assign them later. - [ ] **Use "east const" style.** I.e. `T const*`, not `const T *`. - [ ] **Keep indentation consistent.** See our [`.editorconfig`](.editorconfig). - [ ] Tabs for C++. But use them for indentation only. Any whitespace later on the line must consist of spaces. - [ ] 4 spaces for most other file types. - [ ] **Use `auto` sparingly.** Only use it when the actual type is very long and complicated or when it is already used elsewhere in the same expression. - [ ] **Indent braces and parentheses in a way that makes nesting clear.** - [ ] **Use `using namespace` only in `.cpp` files.** Use it for `std` and our own modules. Avoid unnecessary `std::` prefix in `.cpp` files (except for `std::move` and `std::forward`). - [ ] **Use range-based loops and destructuring.** - [ ] **Include any headers you use directly,** even if they are implicitly included through other headers. ## Documentation - [ ] **Does the PR update relevant documentation?** ### Documentation Style and Good Practices - [ ] **Use double backticks in RST (``` ``x`` ```). Prefer single backticks in Markdown (`` `x` ``),** but note that double backticks are valid too and we use them in some cases for legacy reasons. - [ ] **Always start a new sentence on a new line.** This way you do not have to rewrap the surrounding text when you rewrite the sentence. This also makes changes actually easier to spot in the diff. ## Testing ### What to Test - [ ] **Is newly added code adequately covered by tests?** Have you considered all the important corner cases? - If it is a bugfix: - [ ] **The PR must include tests that reproduce the bug.** - [ ] **Are there gaps in test coverage of the buggy feature?** Fill them by adding more tests. - [ ] **Try to break it.** Can you think of any similar features that could also be buggy? Play with the repro and include prominent variants as separate test cases, even if they don't trigger a bug. - [ ] **Positive cases (code that compiles) should have a semantic test.** - [ ] **Negative cases (code with compilation errors) should have a syntax test.** - [ ] **Avoid mixing positive and negative cases in the same syntax test.** If the test produces an error, we stop at the analysis stage and we will not detect problems that only occur in code generation, optimizer or assembler. - [ ] If you have to do it, at least mark positive cases inside the file with a short comment. - This way, when the test is updated, it is easier to verify that these cases still do not trigger an error. - [ ] New syntax: **does it have an [`ASTJSON`](test/libsolidity/ASTJSON/) test?** - [ ] New CLI or StandardJSON option: - [ ] **Does it have a [command-line test](test/cmdlineTests/)?** - [ ] **Is the option listed for every input mode in [`CommandLineParser` tests](test/solc/CommandLineParser.cpp)?** - [ ] **Did you consider interactions with other language features?** - [ ] Are all types covered? Structs? Enums? Contracts/libraries/interfaces? User-defined value types? Value types: integers, fixed bytes, `address`, `address payable`, `bool`? Function pointers? Static and dynamic arrays? `string` and `bytes`? Mappings? Values of types that cannot be named: literals, tuples, array slices, storage references? - [ ] If it accepts a function, does it also accept an event or an error? These have function types but are not functions. - [ ] If it affects free functions, what about internal library functions? - [ ] Attached library functions? Functions attached with `using for`? - [ ] Possible combinations of `storage`, `memory`, `calldata`, `immutable`, `constant`? Remember that internal functions can take `storage` arguments. - [ ] Does it work at construction time as well? What if you store it at construction time and read after deployment? - [ ] What about importing it from a different module or inheriting it? - [ ] Have you tested it with the ternary operator? ### Test Style and Good Practices - [ ] **Make test case file names long and specific enough** so that it is easy to guess what is inside. When checking if we have the case already covered the name is usually the only clue we see. - [ ] Place them in the right subdirectory. - [ ] **Avoid simply appending numbers to the name to distinguish similar cases.** Coming up with good names is hard but figuring out if any of hundreds of tests with names that match your search actually fits your case is even harder. - [ ] **Do not include version pragma and the SPDX comment in semantic and syntax test cases**. In other test types include them if necessary to suppress warnings. - [ ] **If you have to use a version pragma, avoid hard-coding version.** Use `pragma solidity *`. - [ ] **When writing StandardJSON command-line tests, use `urls` instead of `content`** and put the Solidity or Yul code in a separate file. ## Compiler-specific - [ ] **Are error messages sensible and understandable to users?** - [ ] **Are error codes consistent?** - [ ] Avoid randomly changing or reassigning error codes. - [ ] Avoid defining separate codes for trivial variants of the same issue. Make it easy for tools to consistently refer to the same error with the same code. - [ ] **Error messages should end with a full stop.** - [ ] **Prefer Ranges v3 to Boost where possible.** ## Take a Step Back - [ ] **Do you fully understand what the PR does and why?** - [ ] **Are you confident that the code works and does not break unrelated functionality?** - [ ] **Is this a reasonable way to achieve the goal stated in the issue?** - [ ] **Is the code simple?** Does the PR achieve its objective at the cost of significant complexity that may be a source of future bugs? - [ ] **Is the code efficient?** Does the PR introduce any major performance bottlenecks? - [ ] **Does the PR introduce any breaking changes beyond what was agreed in the issue?** ## Final Checks Before Merging - [ ] **Is the PR rebased on top of the `develop` branch** (or `breaking` if it is a breaking change)? - [ ] **Did all CI checks pass?** - Note that we have a few jobs that tend to randomly fail due to outside factors, especially external tests (with `_ext_` in the name). If these fail, rebase on latest `develop` (or `breaking`) and try rerunning them. Note also that not all of these checks are required for the PR to be merged. - [ ] If the change is visible to users, **does the PR have a [changelog](Changelog.md) entry?** - [ ] Is the changelog entry in the right section? Make sure to move it up if there was a release recently. - [ ] **Is commit history simple and understandable?** - [ ] Each commit should be a self-contained, logical step leading the goal of the PR, without going back and forth. In particular, review fixups should be squashed into the commits they fix. - [ ] Do not include any merge commits in your branch. Please use rebase to keep up to date with the base branch. - [ ] **Is the PR properly labeled?** - Use `external contribution` label to mark PRs not coming from the core team. - If the PR depends on other PRs, use `has dependencies` and set the base branch accordingly. - Labels like `documentation` or `optimizer` are helpful for filtering PRs. ================================================ FILE: SECURITY.md ================================================ # Security Policy The Solidity team and community take all security bugs in Solidity seriously. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions. ## Scope Bugs in the Solidity repository are in scope. Bugs in third-party dependencies e.g., jsoncpp, boost etc. are not in scope unless they result in a Solidity specific bug. Only bugs that have a demonstrable security impact on smart contracts are in scope. For example, a Solidity program whose optimization is incorrect (e.g., leads to an incorrect output) qualifies as a security bug. Please note that the [rules][2] of the [Ethereum bounty program][1] have precedence over this security policy. ## Supported Versions As a general rule, only the latest release gets security updates. Exceptions may be made when the current breaking release is relatively new, e.g. less than three months old. If you are reporting a bug, please state clearly the Solidity version(s) it affects. Example 1: Assuming the current release is `0.6.3` and a security bug has been found in it that affects both `0.5.x` and `0.6.x` trees, we may not only patch `0.6.3` (the bug-fix release numbered `0.6.4`) but `0.5.x` as well (the bug-fix release numbered `0.5.(x+1)`). Example 2: Assuming the current release is `0.6.25` and a security bug has been found in it, we may only patch `0.6.25` (in the bug-fix release numbered `0.6.26`) even if the bug affects a previous tree such as `0.5.x`. ## Reporting a Vulnerability To report a vulnerability, please follow the instructions stated in the [Ethereum bounty program][1]. In the bug report, please include all details necessary to reproduce the vulnerability such as: - Input program that triggers the bug - Compiler version affected - Target EVM version - Framework/IDE if applicable - EVM execution environment/client if applicable - Operating system Please include steps to reproduce the bug you have found in as much detail as possible. Once we have received your bug report, we will try to reproduce it and provide a more detailed response. Once the reported bug has been successfully reproduced, the Solidity team will work on a fix. The Solidity team maintains the following JSON-formatted lists of patched security vulnerabilities: - [Summary of known security vulnerabilities][3] - [List of security vulnerabilities affecting a specific version of the compiler][4]. [1]: https://bounty.ethereum.org/ [2]: https://bounty.ethereum.org/#rules [3]: https://docs.soliditylang.org/en/develop/bugs.html [4]: https://github.com/argotorg/solidity/blob/develop/docs/bugs_by_version.json ================================================ FILE: cmake/EthBuildInfo.cmake ================================================ function(create_build_info NAME) # Set build platform; to be written to BuildInfo.h set(ETH_BUILD_OS "${CMAKE_SYSTEM_NAME}") if (CMAKE_COMPILER_IS_MINGW) set(ETH_BUILD_COMPILER "mingw") elseif (CMAKE_COMPILER_IS_MSYS) set(ETH_BUILD_COMPILER "msys") elseif (CMAKE_COMPILER_IS_GNUCXX) set(ETH_BUILD_COMPILER "g++") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(ETH_BUILD_COMPILER "msvc") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(ETH_BUILD_COMPILER "clang") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") set(ETH_BUILD_COMPILER "appleclang") else () set(ETH_BUILD_COMPILER "unknown") endif () set(ETH_BUILD_PLATFORM "${ETH_BUILD_OS}.${ETH_BUILD_COMPILER}") #cmake build type may be not speCified when using msvc if (CMAKE_BUILD_TYPE) set(_cmake_build_type ${CMAKE_BUILD_TYPE}) else() set(_cmake_build_type "${CMAKE_CFG_INTDIR}") endif() # Generate header file containing useful build information add_custom_target(${NAME}_BuildInfo.h ALL WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${CMAKE_COMMAND} -DETH_SOURCE_DIR=${PROJECT_SOURCE_DIR} -DETH_BUILDINFO_IN=${ETH_CMAKE_DIR}/templates/BuildInfo.h.in -DETH_DST_DIR=${PROJECT_BINARY_DIR}/include/${PROJECT_NAME} -DETH_CMAKE_DIR=${ETH_CMAKE_DIR} -DETH_BUILD_TYPE="${_cmake_build_type}" -DETH_BUILD_OS="${ETH_BUILD_OS}" -DETH_BUILD_COMPILER="${ETH_BUILD_COMPILER}" -DETH_BUILD_PLATFORM="${ETH_BUILD_PLATFORM}" -DPROJECT_VERSION="${PROJECT_VERSION}" -DPROJECT_VERSION_MAJOR="${PROJECT_VERSION_MAJOR}" -DPROJECT_VERSION_MINOR="${PROJECT_VERSION_MINOR}" -DPROJECT_VERSION_PATCH="${PROJECT_VERSION_PATCH}" -P "${ETH_SCRIPTS_DIR}/buildinfo.cmake" ) include_directories("${PROJECT_BINARY_DIR}/include") endfunction() ================================================ FILE: cmake/EthCcache.cmake ================================================ # Setup ccache. # # The ccache is auto-enabled if the tool is found. # To disable set -DCCACHE=OFF option. if(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER) find_program(CCACHE ccache DOC "ccache tool path; set to OFF to disable") if(CCACHE) set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) if(COMMAND cotire) # Change ccache config to meet cotire requirements. set(ENV{CCACHE_SLOPPINESS} pch_defines,time_macros) endif() message(STATUS "[ccache] Enabled: ${CCACHE}") endif() endif() ================================================ FILE: cmake/EthCheckCXXCompilerFlag.cmake ================================================ include(CheckCXXCompilerFlag) # Adds CXX compiler flag if the flag is supported by the compiler. # # This is effectively a combination of CMake's check_cxx_compiler_flag() # and add_compile_options(): # # if(check_cxx_compiler_flag(flag)) # add_compile_options(flag) # function(eth_add_cxx_compiler_flag_if_supported FLAG) # Remove leading - or / from the flag name. string(REGEX REPLACE "^[-/]" "" name ${FLAG}) # Deletes any ':' because it's invalid variable names. string(REGEX REPLACE ":" "" name ${name}) check_cxx_compiler_flag(${FLAG} ${name}) if(${name}) add_compile_options(${FLAG}) endif() # If the optional argument passed, store the result there. if(ARGV1) set(${ARGV1} ${name} PARENT_SCOPE) endif() endfunction() ================================================ FILE: cmake/EthCompilerSettings.cmake ================================================ #------------------------------------------------------------------------------ # EthCompilerSettings.cmake # # CMake file for cpp-ethereum project which specifies our compiler settings # for each supported platform and build configuration. # # The documentation for cpp-ethereum is hosted at http://cpp-ethereum.org # # Copyright (c) 2014-2016 cpp-ethereum contributors. #------------------------------------------------------------------------------ # Clang seeks to be command-line compatible with GCC as much as possible, so # most of our compiler settings are common between GCC and Clang. # # These settings then end up spanning all POSIX platforms (Linux, OS X, BSD, etc) include(EthCheckCXXCompilerFlag) if(NOT EMSCRIPTEN) eth_add_cxx_compiler_flag_if_supported(-fstack-protector-strong have_stack_protector_strong_support) if(NOT have_stack_protector_strong_support) eth_add_cxx_compiler_flag_if_supported(-fstack-protector) endif() endif() if(PEDANTIC) eth_add_cxx_compiler_flag_if_supported(-Wimplicit-fallthrough) endif() # Prevent the path of the source directory from ending up in the binary via __FILE__ macros. eth_add_cxx_compiler_flag_if_supported("-fmacro-prefix-map=${PROJECT_SOURCE_DIR}=/solidity") # -Wpessimizing-move warns when a call to std::move would prevent copy elision # if the argument was not wrapped in a call. This happens when moving a local # variable in a return statement when the variable is the same type as the # return type or using a move to create a new object from a temporary object. if(PEDANTIC) eth_add_cxx_compiler_flag_if_supported(-Wpessimizing-move) endif() # -Wredundant-move warns when an implicit move would already be made, so the # std::move call is not needed, such as when moving a local variable in a return # that is different from the return type. if(PEDANTIC) eth_add_cxx_compiler_flag_if_supported(-Wredundant-move) endif() if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) # Enables all the warnings about constructions that some users consider questionable, # and that are easy to avoid. Also enable some extra warning flags that are not # enabled by -Wall. Finally, treat at warnings-as-errors, which forces developers # to fix warnings as they arise, so they don't accumulate "to be fixed later". if(PEDANTIC) add_compile_options(-Wall) add_compile_options(-Wextra) add_compile_options(-Werror) add_compile_options(-pedantic) add_compile_options(-Wmissing-declarations) add_compile_options(-Wno-unknown-pragmas) add_compile_options(-Wimplicit-fallthrough) add_compile_options(-Wsign-conversion) add_compile_options(-Wconversion) check_cxx_compiler_flag(-Wextra-semi WEXTRA_SEMI) if(WEXTRA_SEMI) add_compile_options($<$:-Wextra-semi>) endif() # See https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=6b927b1297e66e26e62e722bf15c921dcbbd25b9 check_cxx_compiler_flag(-Wno-dangling-reference WNO_DANGLING_REFERENCE) if (WNO_DANGLING_REFERENCE) add_compile_options($<$:-Wno-dangling-reference>) endif() eth_add_cxx_compiler_flag_if_supported(-Wfinal-dtor-non-final-class) eth_add_cxx_compiler_flag_if_supported(-Wnewline-eof) eth_add_cxx_compiler_flag_if_supported(-Wsuggest-destructor-override) eth_add_cxx_compiler_flag_if_supported(-Wduplicated-cond) eth_add_cxx_compiler_flag_if_supported(-Wduplicate-enum) eth_add_cxx_compiler_flag_if_supported(-Wlogical-op) eth_add_cxx_compiler_flag_if_supported(-Wno-unknown-attributes) endif() # Configuration-specific compiler settings. set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3 -DETH_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g3") # Additional GCC-specific compiler settings. if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") # Check that we've got GCC 11.0 or newer. if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)) message(FATAL_ERROR "${PROJECT_NAME} requires g++ 11.0 or greater.") endif () # GCC 12 emits warnings for string concatenations with operator+ under O3 # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105651 if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.0) add_compile_options(-Wno-error=restrict) endif () # Use fancy colors in the compiler diagnostics add_compile_options(-fdiagnostics-color) # Additional Clang-specific compiler settings. elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # Check that we've got clang 14.0 or newer. if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0)) message(FATAL_ERROR "${PROJECT_NAME} requires clang++ 14.0 or greater.") endif () # use std::invoke_result, superseding std::result_of which has been removed in c++20 add_compile_definitions(BOOST_ASIO_HAS_STD_INVOKE_RESULT) if ("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") # Set stack size to 32MB - by default Apple's clang defines a stack size of 8MB. # Normally 16MB is enough to run all tests, but it will exceed the stack, if -DSANITIZE=address is used. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size -Wl,0x2000000") # Boost libraries use visibility=hidden to reduce unnecessary DWARF entries. # Unless we match visibility, ld will give a warning message like: # ld: warning: direct access in function 'boost::filesystem... from file ... # means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") endif() # Some Linux-specific Clang settings. We don't want these for OS X. if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") # Use fancy colors in the compiler diagnostics add_compile_options(-fcolor-diagnostics) # See "How to silence unused command line argument error with clang without disabling it?" # When using -Werror with clang, it transforms "warning: argument unused during compilation" messages # into errors, which makes sense. # http://stackoverflow.com/questions/21617158/how-to-silence-unused-command-line-argument-error-with-clang-without-disabling-i add_compile_options(-Qunused-arguments) elseif(EMSCRIPTEN) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --memory-init-file 0") # Leave only exported symbols as public and aggressively remove others set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -fvisibility=hidden") # Optimisation level set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") # Re-enable exception catching (optimisations above -O1 disable it) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0") # Remove any code related to exit (such as atexit) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXIT_RUNTIME=0") # Remove any code related to filesystem access set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s FILESYSTEM=0") # Allow memory growth, but disable some optimisations set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_MEMORY_GROWTH=1") # Disable eval() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s DYNAMIC_EXECUTION=0") # Disable greedy exception catcher set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s NODEJS_CATCH_EXIT=0") # Abort if linking results in any undefined symbols # Note: this is on by default in the CMake Emscripten module which we aren't using set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ERROR_ON_UNDEFINED_SYMBOLS=1") # Disallow deprecated emscripten build options. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s STRICT=1") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s STRICT=1") # Export the Emscripten-generated auxiliary methods which are needed by solc-js. # Which methods of libsolc itself are exported is specified in libsolc/CMakeLists.txt. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap','addFunction','removeFunction','UTF8ToString','lengthBytesUTF8','stringToUTF8','setValue']") # Build for webassembly target. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM=1") # Set webassembly build to synchronous loading. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM_ASYNC_COMPILATION=0") # Allow new functions to be added to the wasm module via addFunction. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_TABLE_GROWTH=1") # Disable warnings about not being pure asm.js due to memory growth. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-almost-asm") # Increase stack size from 5MB to 16MB to prevent stack overflow issues. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_STACK=16mb") # Increase memory size from 16MB to 32MB since the stack size is now 16MB. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s INITIAL_MEMORY=32mb") endif() endif() # The major alternative compiler to GCC/Clang is Microsoft's Visual C++ compiler, only available on Windows. elseif (DEFINED MSVC) # Remove NDEBUG from RELWITHDEBINFO (to enable asserts) # CMAKE_CXX_FLAGS_RELWITHDEBINFO for GCC/Clang does not include NDEBUG string(REPLACE "/DNDEBUG" " " CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") add_compile_options(/MP) # enable parallel compilation add_compile_options(/EHsc) # specify Exception Handling Model in msvc if(PEDANTIC) add_compile_options(/WX) # enable warnings-as-errors endif() add_compile_options(/wd4068) # disable unknown pragma warning (4068) add_compile_options(/wd4996) # disable unsafe function warning (4996) add_compile_options(/wd4503) # disable decorated name length exceeded, name was truncated (4503) add_compile_options(/wd4267) # disable conversion from 'size_t' to 'type', possible loss of data (4267) add_compile_options(/wd4180) # disable qualifier applied to function type has no meaning; ignored (4180) add_compile_options(/wd4290) # disable C++ exception specification ignored except to indicate a function is not __declspec(nothrow) (4290) add_compile_options(/wd4244) # disable conversion from 'type1' to 'type2', possible loss of data (4244) add_compile_options(/wd4800) # disable forcing value to bool 'true' or 'false' (performance warning) (4800) add_compile_options(-D_WIN32_WINNT=0x0600) # declare Windows Vista API requirement add_compile_options(-DNOMINMAX) # undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions add_compile_options(/utf-8) # enable utf-8 encoding (solves warning 4819) add_compile_options(-DBOOST_REGEX_NO_LIB) # disable automatic boost::regex library selection add_compile_options(-D_REGEX_MAX_STACK_COUNT=200000L) # increase std::regex recursion depth limit add_compile_options(/permissive-) # specify standards conformance mode to the compiler # disable empty object file warning set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") # warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification # warning LNK4099: pdb was not found with lib # stack size 16MB set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075 /STACK:16777216") # If you don't have GCC, Clang or VC++ then you are on your own. Good luck! else () message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") endif () if (SANITIZE) # Perform case-insensitive string compare string(TOLOWER "${SANITIZE}" sanitizer) # -fno-omit-frame-pointer gives more informative stack trace in case of an error # -fsanitize-address-use-after-scope throws an error when a variable is used beyond its scope if (sanitizer STREQUAL "address") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=address -fsanitize-address-use-after-scope") elseif (sanitizer STREQUAL "undefined") # The following flags not used by fuzzer but used by us may create problems, so consider # disabling them: alignment, pointer-overflow. # The following flag is not used by us to reduce terminal noise # i.e., warnings printed on stderr: unsigned-integer-overflow # Note: The C++ standard does not officially consider unsigned integer overflows # to be undefined behavior since they are implementation independent. # Flags are alphabetically sorted and are for clang v10.0 list(APPEND undefinedSanitizerChecks alignment array-bounds bool builtin enum float-divide-by-zero function integer-divide-by-zero null object-size pointer-overflow return returns-nonnull-attribute shift signed-integer-overflow unreachable vla-bound vptr ) list(JOIN undefinedSanitizerChecks "," sanitizerChecks) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=${sanitizerChecks} -fno-sanitize-recover=${sanitizerChecks}") endif() endif() # Code coverage support. # Copied from Cable: # https://github.com/ethereum/cable/blob/v0.2.4/CableCompilerSettings.cmake#L118-L132 option(COVERAGE "Build with code coverage support" OFF) if(COVERAGE) # Set the linker flags first, they are required to properly test the compiler flag. set(CMAKE_SHARED_LINKER_FLAGS "--coverage ${CMAKE_SHARED_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "--coverage ${CMAKE_EXE_LINKER_FLAGS}") set(CMAKE_REQUIRED_LIBRARIES "--coverage ${CMAKE_REQUIRED_LIBRARIES}") check_cxx_compiler_flag(--coverage have_coverage) string(REPLACE "--coverage " "" CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) if(NOT have_coverage) message(FATAL_ERROR "Coverage not supported") endif() add_compile_options(-g --coverage) endif() ================================================ FILE: cmake/EthDependencies.cmake ================================================ # all dependencies that are not directly included in the cpp-ethereum distribution are defined here # for this to work, download the dependency via the cmake script in extdep or install them manually! if (DEFINED MSVC) # by defining CMAKE_PREFIX_PATH variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.0) set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_LIST_DIR}/../extdep/install/windows/x64") else() get_filename_component(DEPS_DIR "${CMAKE_CURRENT_LIST_DIR}/../deps/install" ABSOLUTE) set(ETH_DEPENDENCY_INSTALL_DIR "${DEPS_DIR}/x64" # Old location for deps. "${DEPS_DIR}/win64" # New location for deps. "${DEPS_DIR}/win64/Release/share" # LLVM shared cmake files. ) endif() set (CMAKE_PREFIX_PATH ${ETH_DEPENDENCY_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) endif() # custom cmake scripts set(ETH_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}) set(ETH_SCRIPTS_DIR ${ETH_CMAKE_DIR}/scripts) ## use multithreaded boost libraries, with -mt suffix set(Boost_USE_MULTITHREADED ON) option(Boost_USE_STATIC_LIBS "Link Boost statically" ON) if (WIN32) option(Boost_USE_STATIC_RUNTIME "Link Boost against static C++ runtime libraries" ON) endif() set(BOOST_COMPONENTS "filesystem;unit_test_framework;program_options") # CMake >= 3.30 should not use the vendored boost if(POLICY CMP0167) cmake_policy(SET CMP0167 NEW) endif() if (WIN32) # Boost 1.77 fixes a bug that causes crashes on Windows for some relative paths in --allow-paths. # See https://github.com/boostorg/filesystem/issues/201 find_package(Boost 1.77.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) else() # Boost 1.65 is the first to also provide boost::get for rvalue-references (#5787). # Boost 1.67 moved container_hash into is own module. # Boost 1.69 boost::system is header-only and no longer needs to be fetched as component # Boost 1.70 comes with its own BoostConfig.cmake and is the new (non-deprecated) behavior # Boost 1.75 fixes infinite recursion on `boost::rational` comparison with GCC<14.0 under C++20 # Boost 1.83 is the version that comes with Ubuntu 24.04. find_package(Boost 1.83.0 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS}) endif() # If cmake is older than boost and boost is older than 1.70, # find_package does not define imported targets, so we have to # define them manually. if (NOT TARGET Boost::boost) # header only target add_library(Boost::boost INTERFACE IMPORTED) set_property(TARGET Boost::boost APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) endif() message(STATUS "Found Boost ${Boost_VERSION} headers in ${Boost_INCLUDE_DIRS}") foreach (BOOST_COMPONENT IN LISTS BOOST_COMPONENTS) if (NOT TARGET Boost::${BOOST_COMPONENT}) add_library(Boost::${BOOST_COMPONENT} UNKNOWN IMPORTED) string(TOUPPER ${BOOST_COMPONENT} BOOST_COMPONENT_UPPER) set_property(TARGET Boost::${BOOST_COMPONENT} PROPERTY IMPORTED_LOCATION ${Boost_${BOOST_COMPONENT_UPPER}_LIBRARY}) set_property(TARGET Boost::${BOOST_COMPONENT} PROPERTY INTERFACE_LINK_LIBRARIES ${Boost_${BOOST_COMPONENT_UPPER}_LIBRARIES}) set_property(TARGET Boost::${BOOST_COMPONENT} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) endif() get_property(LOCATION TARGET Boost::${BOOST_COMPONENT} PROPERTY IMPORTED_LOCATION) message(STATUS "Found Boost::${BOOST_COMPONENT} at ${LOCATION}") endforeach() ================================================ FILE: cmake/EthOptions.cmake ================================================ # CMAKE macros to set default CMAKE options and to show the # resulting configuration. macro(configure_project) set(NAME ${PROJECT_NAME}) # features eth_default_option(COVERAGE OFF) eth_default_option(OSSFUZZ OFF) # components eth_default_option(TESTS ON) eth_default_option(TOOLS ON) # Define a matching property name of each of the "features". foreach(FEATURE ${ARGN}) set(SUPPORT_${FEATURE} TRUE) endforeach() include(EthBuildInfo) create_build_info(${NAME}) print_config(${NAME}) endmacro() macro(print_config NAME) message("") message("------------------------------------------------------------------------") message("-- Configuring ${NAME} ${PROJECT_VERSION}") message("------------------------------------------------------------------------") message("-- CMake Version ${CMAKE_VERSION}") message("-- CMAKE_BUILD_TYPE Build type ${CMAKE_BUILD_TYPE}") message("-- TARGET_PLATFORM Target platform ${CMAKE_SYSTEM_NAME}") message("--------------------------------------------------------------- features") message("-- COVERAGE Coverage support ${COVERAGE}") message("------------------------------------------------------------- components") if (SUPPORT_TESTS) message("-- TESTS Build tests ${TESTS}") endif() if (SUPPORT_TOOLS) message("-- TOOLS Build tools ${TOOLS}") endif() message("------------------------------------------------------------------ flags") message("-- OSSFUZZ ${OSSFUZZ}") message("------------------------------------------------------------------------") message("") endmacro() ================================================ FILE: cmake/EthPolicy.cmake ================================================ # it must be a macro cause policies have scopes # http://www.cmake.org/cmake/help/v3.0/command/cmake_policy.html macro (eth_policy) # link_directories() treats paths relative to the source dir. cmake_policy(SET CMP0015 NEW) # Avoid warnings in CMake 3.0.2: cmake_policy(SET CMP0042 NEW) cmake_policy(SET CMP0043 NEW) # allow VERSION argument in project() cmake_policy(SET CMP0048 NEW) if (POLICY CMP0054) # do not interpret if() arguments as variables! cmake_policy(SET CMP0054 NEW) endif() if (POLICY CMP0091) # Allow selecting MSVC runtime library using CMAKE_MSVC_RUNTIME_LIBRARY. cmake_policy(SET CMP0091 NEW) endif() # Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24: if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) endif() if(POLICY CMP0115) # Require explicit extensions for source files, do not guess. # The extra calls to GetFileAttributesW significantly slow down cmake on Windows. # https://gitlab.kitware.com/cmake/cmake/-/issues/23154 cmake_policy(SET CMP0115 NEW) endif() endmacro() ================================================ FILE: cmake/EthToolchains.cmake ================================================ # Require C++20. if (NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 20) # This requires at least CMake 3.12 to accept this C++20 flag. endif () set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_EXTENSIONS OFF) if(NOT CMAKE_TOOLCHAIN_FILE) # Use default toolchain file if none is provided. set( CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/toolchains/default.cmake" CACHE FILEPATH "The CMake toolchain file" ) endif() ================================================ FILE: cmake/EthUtils.cmake ================================================ # # renames the file if it is different from its destination include(CMakeParseArguments) # macro(replace_if_different SOURCE DST) set(extra_macro_args ${ARGN}) set(options CREATE) set(one_value_args) set(multi_value_args) cmake_parse_arguments(REPLACE_IF_DIFFERENT "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") if (REPLACE_IF_DIFFERENT_CREATE AND (NOT (EXISTS "${DST}"))) file(WRITE "${DST}" "") endif() execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files "${SOURCE}" "${DST}" RESULT_VARIABLE DIFFERENT OUTPUT_QUIET ERROR_QUIET) if (DIFFERENT) execute_process(COMMAND ${CMAKE_COMMAND} -E rename "${SOURCE}" "${DST}") else() execute_process(COMMAND ${CMAKE_COMMAND} -E remove "${SOURCE}") endif() endmacro() macro(eth_default_option O DEF) if (DEFINED ${O}) if (${${O}}) set(${O} ON) else () set(${O} OFF) endif() else () set(${O} ${DEF}) endif() endmacro() function(detect_stray_source_files FILELIST DIRECTORY) if(CMAKE_VERSION VERSION_LESS 3.12) file(GLOB sources RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${DIRECTORY}/*.cpp" "${DIRECTORY}/*.h") else() file(GLOB sources RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" CONFIGURE_DEPENDS "${DIRECTORY}/*.cpp" "${DIRECTORY}/*.h") endif() foreach(path IN LISTS FILELIST) list(REMOVE_ITEM sources ${path}) endforeach() list(LENGTH sources leftover_sources) if (leftover_sources) message(SEND_ERROR "The following source files are present but are not compiled: ${sources}") endif() endfunction(detect_stray_source_files) # CreateExportedFunctionsForEMSDK(OUTPUT_VARIABLE Symbol1 Symbol2 ... SymbolN) function(CreateExportedFunctionsForEMSDK OUTPUT_VARIABLE) list(TRANSFORM ARGN PREPEND "\"_") list(TRANSFORM ARGN APPEND "\"") list(JOIN ARGN "," ARGN) set(${OUTPUT_VARIABLE} "[${ARGN}]" PARENT_SCOPE) endfunction() ================================================ FILE: cmake/FindCLN.cmake ================================================ find_library(CLN_LIBRARY NAMES cln) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(CLN DEFAULT_MSG CLN_LIBRARY) if(CLN_FOUND AND NOT TARGET CLN::CLN) add_library(CLN::CLN UNKNOWN IMPORTED) set_property(TARGET CLN::CLN PROPERTY IMPORTED_LOCATION ${CLN_LIBRARY}) endif() ================================================ FILE: cmake/FindGMP.cmake ================================================ find_library(GMP_LIBRARY NAMES gmp) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GMP DEFAULT_MSG GMP_LIBRARY) if(GMP_FOUND AND NOT TARGET GMP::GMP) add_library(GMP::GMP UNKNOWN IMPORTED) set_property(TARGET GMP::GMP PROPERTY IMPORTED_LOCATION ${GMP_LIBRARY}) endif() ================================================ FILE: cmake/FindZ3.cmake ================================================ # Save and clear Z3_FIND_VERSION, since the # Z3 config module cannot handle version requirements. set(Z3_FIND_VERSION_ORIG ${Z3_FIND_VERSION}) set(Z3_FIND_VERSION) # Try to find Z3 using its stock cmake files. find_package(Z3 QUIET CONFIG) # Restore Z3_FIND_VERSION for find_package_handle_standard_args. set(Z3_FIND_VERSION ${Z3_FIND_VERSION_ORIG}) set(Z3_FIND_VERSION_ORIG) include(FindPackageHandleStandardArgs) if (Z3_FOUND) set(Z3_VERSION ${Z3_VERSION_STRING}) find_package_handle_standard_args(Z3 CONFIG_MODE) else() find_path(Z3_INCLUDE_DIR NAMES z3++.h PATH_SUFFIXES z3) find_library(Z3_LIBRARY NAMES z3) find_program(Z3_EXECUTABLE z3 PATH_SUFFIXES bin) if(Z3_INCLUDE_DIR AND Z3_LIBRARY) if(Z3_EXECUTABLE) execute_process (COMMAND ${Z3_EXECUTABLE} -version OUTPUT_VARIABLE libz3_version_str ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) string(REGEX REPLACE "^Z3 version ([0-9.]+).*" "\\1" Z3_VERSION_STRING "${libz3_version_str}") unset(libz3_version_str) else() message(WARNING "Could not determine the version of z3, since the z3 executable was not found.") set(Z3_VERSION_STRING "0.0.0") endif() endif() mark_as_advanced(Z3_VERSION_STRING z3_DIR) find_package_handle_standard_args(Z3 REQUIRED_VARS Z3_LIBRARY Z3_INCLUDE_DIR VERSION_VAR Z3_VERSION_STRING) if (NOT TARGET z3::libz3) add_library(z3::libz3 UNKNOWN IMPORTED) set_property(TARGET z3::libz3 PROPERTY IMPORTED_LOCATION ${Z3_LIBRARY}) set_property(TARGET z3::libz3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR}) endif() endif() ================================================ FILE: cmake/fmtlib.cmake ================================================ include(${CMAKE_SOURCE_DIR}/cmake/submodules.cmake) initialize_submodule(fmtlib) set(FMT_SYSTEM_HEADERS ON) add_subdirectory( ${CMAKE_SOURCE_DIR}/deps/fmtlib EXCLUDE_FROM_ALL ) ================================================ FILE: cmake/nlohmann-json.cmake ================================================ include(${CMAKE_SOURCE_DIR}/cmake/submodules.cmake) initialize_submodule(nlohmann-json) set(JSON_Install OFF CACHE INTERNAL "") add_subdirectory( ${CMAKE_SOURCE_DIR}/deps/nlohmann-json EXCLUDE_FROM_ALL ) ================================================ FILE: cmake/range-v3.cmake ================================================ include(${CMAKE_SOURCE_DIR}/cmake/submodules.cmake) initialize_submodule(range-v3) add_library(range-v3 INTERFACE IMPORTED) set_target_properties(range-v3 PROPERTIES INTERFACE_COMPILE_OPTIONS "\$<\$:/permissive->" INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/range-v3/include INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/deps/range-v3/include ) add_dependencies(range-v3 range-v3-project) ================================================ FILE: cmake/scripts/buildinfo.cmake ================================================ # generates BuildInfo.h # # this module expects # ETH_SOURCE_DIR - main CMAKE_SOURCE_DIR # ETH_DST_DIR - main CMAKE_BINARY_DIR # ETH_BUILD_TYPE # ETH_BUILD_PLATFORM # # example usage: # cmake -DETH_SOURCE_DIR=. -DETH_DST_DIR=build -DETH_BUILD_TYPE=Debug -DETH_BUILD_PLATFORM=Darwin.appleclang -P scripts/buildinfo.cmake # # Its main output variables are SOL_VERSION_BUILDINFO and SOL_VERSION_PRERELEASE if (NOT ETH_BUILD_TYPE) set(ETH_BUILD_TYPE "unknown") endif() if (NOT ETH_BUILD_PLATFORM) set(ETH_BUILD_PLATFORM "unknown") endif() # Logic here: If prerelease.txt exists but is empty, it is a non-pre release. # If it does not exist, create our own prerelease string if (EXISTS ${ETH_SOURCE_DIR}/prerelease.txt) file(READ ${ETH_SOURCE_DIR}/prerelease.txt SOL_VERSION_PRERELEASE) string(STRIP "${SOL_VERSION_PRERELEASE}" SOL_VERSION_PRERELEASE) else() string(TIMESTAMP SOL_VERSION_PRERELEASE "develop.%Y.%m.%d" UTC) string(REPLACE .0 . SOL_VERSION_PRERELEASE "${SOL_VERSION_PRERELEASE}") endif() if (EXISTS ${ETH_SOURCE_DIR}/commit_hash.txt) file(READ ${ETH_SOURCE_DIR}/commit_hash.txt SOL_COMMIT_HASH) string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH) else() execute_process( COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse --short=8 HEAD OUTPUT_VARIABLE SOL_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) execute_process( COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} diff HEAD --shortstat OUTPUT_VARIABLE SOL_LOCAL_CHANGES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) endif() if (SOL_COMMIT_HASH) string(STRIP ${SOL_COMMIT_HASH} SOL_COMMIT_HASH) string(SUBSTRING ${SOL_COMMIT_HASH} 0 8 SOL_COMMIT_HASH) endif() if (NOT SOL_COMMIT_HASH) message(FATAL_ERROR "Unable to determine commit hash. Either compile from within git repository or " "supply a file called commit_hash.txt") endif() if (NOT SOL_COMMIT_HASH MATCHES [a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]) message(FATAL_ERROR "Malformed commit hash \"${SOL_COMMIT_HASH}\". It has to consist of exactly 8 hex digits.") endif() if (SOL_COMMIT_HASH AND SOL_LOCAL_CHANGES) set(SOL_COMMIT_HASH "${SOL_COMMIT_HASH}.mod") endif() set(SOL_VERSION_COMMIT "commit.${SOL_COMMIT_HASH}") set(SOL_VERSION_PLATFORM ETH_BUILD_PLATFORM) set(SOL_VERSION_BUILDINFO "commit.${SOL_COMMIT_HASH}.${ETH_BUILD_PLATFORM}") set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp") set(OUTFILE "${ETH_DST_DIR}/BuildInfo.h") configure_file("${ETH_BUILDINFO_IN}" "${TMPFILE}") include("${ETH_CMAKE_DIR}/EthUtils.cmake") replace_if_different("${TMPFILE}" "${OUTFILE}" CREATE) ================================================ FILE: cmake/submodules.cmake ================================================ macro(initialize_submodule SUBMODULE_PATH) if(NOT IGNORE_VENDORED_DEPENDENCIES) file(GLOB submodule_contents "${CMAKE_SOURCE_DIR}/deps/${SUBMODULE_PATH}/*") if(submodule_contents) message(STATUS "git submodule '${SUBMODULE_PATH}' seem to be already initialized: nothing to do.") else() message(STATUS "git submodule '${SUBMODULE_PATH}' seem not to be initialized: implicitly executing 'git submodule update --init '${CMAKE_SOURCE_DIR}/deps/${SUBMODULE_PATH}'.") find_package(Git) if(NOT Git_FOUND) message(FATAL_ERROR "Failed to initialize submodules: 'git' command not found.") endif() execute_process( COMMAND git submodule update --init ${CMAKE_SOURCE_DIR}/deps/${SUBMODULE_PATH} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} RESULT_VARIABLE result ) if(NOT result EQUAL 0) message(FATAL_ERROR "Failed to initialize submodules: 'git submodule update --init' failed.") endif() endif() endif() endmacro() ================================================ FILE: cmake/templates/BuildInfo.h.in ================================================ #pragma once #define ETH_PROJECT_VERSION "@PROJECT_VERSION@" #define ETH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ #define ETH_PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@ #define ETH_PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@ #define SOL_COMMIT_HASH "@SOL_COMMIT_HASH@" #define ETH_BUILD_TYPE "@ETH_BUILD_TYPE@" #define ETH_BUILD_OS "@ETH_BUILD_OS@" #define ETH_BUILD_COMPILER "@ETH_BUILD_COMPILER@" #define ETH_BUILD_PLATFORM "@ETH_BUILD_PLATFORM@" #define SOL_VERSION_PRERELEASE "@SOL_VERSION_PRERELEASE@" #define SOL_VERSION_BUILDINFO "@SOL_VERSION_BUILDINFO@" #define SOL_VERSION_COMMIT "@SOL_VERSION_COMMIT@" #define SOL_VERSION_PLATFORM "@SOL_VERSION_PLATFORM@" ================================================ FILE: cmake/templates/license.h.in ================================================ #pragma once #include static std::string const otherLicenses{R"(Most of the code is licensed under GPLv3 (see below), the license for individual parts and dependencies are as follows: libkeccak-tiny: The file libsolutil/Keccak256.cpp incorporates libkeccak-tiny. A single-file implementation of SHA-3 and SHAKE implemented by David Leon Gil License: CC0, attribution kindly requested. Blame taken too, but not liability. nlohmann-json: The source code of nlohmann-json is licensed under the following conditions: The class is licensed under the MIT License: Copyright © 2013-2022 Niels Lohmann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the MIT License (see above). Copyright © 2008-2009 Björn Hoehrmann bjoern@hoehrmann.de The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the MIT License (see above). Copyright © 2009 Florian Loitsch The class contains a copy of Hedley from Evan Nemerson which is licensed as CC0-1.0. picosha2: The file libsolutil/picosha2.h is imported. Copyright (C) 2017 okdshin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. range-v3: The range-v3 library is licensed under the following conditions: ======================================================== Boost Software License - Version 1.0 - August 17th, 2003 ======================================================== Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================================== libc++ License ============================================================================== The libc++ library is dual licensed under both the University of Illinois "BSD-Like" license and the MIT license. As a user of this code you may choose to use it under either license. As a contributor, you agree to allow your code to be used under both. Full text of the relevant licenses is included below. ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT http://llvm.org/svn/llvm-project/libcxx/trunk/CREDITS.TXT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================================== Stepanov and McJones, "Elements of Programming" license ============================================================================== // Copyright (c) 2009 Alexander Stepanov and Paul McJones // // Permission to use, copy, modify, distribute and sell this software // and its documentation for any purpose is hereby granted without // fee, provided that the above copyright notice appear in all copies // and that both that copyright notice and this permission notice // appear in supporting documentation. The authors make no // representations about the suitability of this software for any // purpose. It is provided "as is" without express or implied // warranty. // // Algorithms from // Elements of Programming // by Alexander Stepanov and Paul McJones // Addison-Wesley Professional, 2009 ============================================================================== SGI C++ Standard Template Library license ============================================================================== // Copyright (c) 1994 // Hewlett-Packard Company // // Permission to use, copy, modify, distribute and sell this software // and its documentation for any purpose is hereby granted without fee, // provided that the above copyright notice appear in all copies and // that both that copyright notice and this permission notice appear // in supporting documentation. Hewlett-Packard Company makes no // representations about the suitability of this software for any // purpose. It is provided "as is" without express or implied warranty. // // Copyright (c) 1996 // Silicon Graphics Computer Systems, Inc. // // Permission to use, copy, modify, distribute and sell this software // and its documentation for any purpose is hereby granted without fee, // provided that the above copyright notice appear in all copies and // that both that copyright notice and this permission notice appear // in supporting documentation. Silicon Graphics makes no // representations about the suitability of this software for any // purpose. It is provided "as is" without express or implied warranty. // scanner/token: The liblangutil/{CharStream,Scanner,Token}.{h,cpp} files are derived from code originating from the V8 project licensed under the following terms: Copyright 2006-2012, the V8 project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. evmc: The code in test/evmc is licensed under the Apache License version 2: Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. mini-lz4: The file scripts/ci/mini-lz4.js is derived from the emscripten adaptation of node-lz4 and licensed under the following terms: Copyright (c) 2012 Pierre Curto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. base64: The file scripts/ci/base64DecToArr.js is derived from a code example in the MDN Web Docs, which permits use under CC0 terms: Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ Z3: The Z3 library is licensed under the following terms: Copyright (c) Microsoft Corporation All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. All other code is licensed under GPL version 3: )"}; static char const licenseText[] = { @LICENSE_TEXT@, 0 }; ================================================ FILE: cmake/toolchains/default.cmake ================================================ ================================================ FILE: cmake/toolchains/libfuzzer.cmake ================================================ # Inherit default options include("${CMAKE_CURRENT_LIST_DIR}/default.cmake") # Build fuzzing binaries set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE) # Use libfuzzer as the fuzzing back-end set(LIB_FUZZING_ENGINE "-fsanitize=fuzzer" CACHE STRING "Use libfuzzer back-end" FORCE) # clang/libfuzzer specific flags for UBSan instrumentation # uses the more memory-efficient gold, which allows us to stay with the "large" resource class without OOM errors set(CMAKE_CXX_FLAGS "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -I /usr/local/include/c++/v1 -fsanitize=undefined -fsanitize=fuzzer-no-link -fuse-ld=gold -stdlib=libc++" CACHE STRING "Custom compilation flags" FORCE) # Link statically against boost libraries set(BOOST_FOUND ON CACHE BOOL "" FORCE) set(Boost_USE_STATIC_LIBS ON CACHE BOOL "Link against static Boost libraries" FORCE) set(Boost_USE_STATIC_RUNTIME ON CACHE BOOL "Link against static Boost runtime library" FORCE) ================================================ FILE: cmake/toolchains/ossfuzz.cmake ================================================ # Inherit default options include("${CMAKE_CURRENT_LIST_DIR}/default.cmake") # Disable Z3. set(USE_Z3 OFF CACHE BOOL "Disable Z3" FORCE) # Enable fuzzers set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE) set(LIB_FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE} CACHE STRING "Use fuzzer back-end defined by environment variable" FORCE) # Link statically against boost libraries set(BOOST_FOUND ON CACHE BOOL "" FORCE) set(Boost_USE_STATIC_LIBS ON CACHE BOOL "Link against static Boost libraries" FORCE) set(Boost_USE_STATIC_RUNTIME ON CACHE BOOL "Link against static Boost runtime library" FORCE) ================================================ FILE: docs/050-breaking-changes.rst ================================================ ******************************** Solidity v0.5.0 Breaking Changes ******************************** This section highlights the main breaking changes introduced in Solidity version 0.5.0, along with the reasoning behind the changes and how to update affected code. For the full list check `the release changelog `_. .. note:: Contracts compiled with Solidity v0.5.0 can still interface with contracts and even libraries compiled with older versions without recompiling or redeploying them. Changing the interfaces to include data locations and visibility and mutability specifiers suffices. See the :ref:`Interoperability With Older Contracts ` section below. Semantic Only Changes ===================== This section lists the changes that are semantic-only, thus potentially hiding new and different behavior in existing code. * Signed right shift now uses proper arithmetic shift, i.e. rounding towards negative infinity, instead of rounding towards zero. Signed and unsigned shift will have dedicated opcodes in Constantinople, and are emulated by Solidity for the moment. * The ``continue`` statement in a ``do...while`` loop now jumps to the condition, which is the common behavior in such cases. It used to jump to the loop body. Thus, if the condition is false, the loop terminates. * The functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` do not pad anymore when given a single ``bytes`` parameter. * Pure and view functions are now called using the opcode ``STATICCALL`` instead of ``CALL`` if the EVM version is Byzantium or later. This disallows state changes on the EVM level. * The ABI encoder now properly pads byte arrays and strings from calldata (``msg.data`` and external function parameters) when used in external function calls and in ``abi.encode``. For unpadded encoding, use ``abi.encodePacked``. * The ABI decoder reverts in the beginning of functions and in ``abi.decode()`` if passed calldata is too short or points out of bounds. Note that dirty higher order bits are still simply ignored. * Forward all available gas with external function calls starting from Tangerine Whistle. Semantic and Syntactic Changes ============================== This section highlights changes that affect syntax and semantics. * The functions ``.call()``, ``.delegatecall()``, ``staticcall()``, ``keccak256()``, ``sha256()`` and ``ripemd160()`` now accept only a single ``bytes`` argument. Moreover, the argument is not padded. This was changed to make more explicit and clear how the arguments are concatenated. Change every ``.call()`` (and family) to a ``.call("")`` and every ``.call(signature, a, b, c)`` to use ``.call(abi.encodeWithSignature(signature, a, b, c))`` (the last one only works for value types). Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``. Even though it is not a breaking change, it is suggested that developers change ``x.call(bytes4(keccak256("f(uint256)")), a, b)`` to ``x.call(abi.encodeWithSignature("f(uint256)", a, b))``. * Functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` now return ``(bool, bytes memory)`` to provide access to the return data. Change ``bool success = otherContract.call("f")`` to ``(bool success, bytes memory data) = otherContract.call("f")``. * Solidity now implements C99-style scoping rules for function local variables, that is, variables can only be used after they have been declared and only in the same or nested scopes. Variables declared in the initialization block of a ``for`` loop are valid at any point inside the loop. Explicitness Requirements ========================= This section lists changes where the code now needs to be more explicit. For most of the topics the compiler will provide suggestions. * Explicit function visibility is now mandatory. Add ``public`` to every function and constructor, and ``external`` to every fallback or interface function that does not specify its visibility already. * Explicit data location for all variables of struct, array or mapping types is now mandatory. This is also applied to function parameters and return variables. For example, change ``uint[] x = z`` to ``uint[] storage x = z``, and ``function f(uint[][] x)`` to ``function f(uint[][] memory x)`` where ``memory`` is the data location and might be replaced by ``storage`` or ``calldata`` accordingly. Note that ``external`` functions require parameters with a data location of ``calldata``. * Contract types do not include ``address`` members anymore in order to separate the namespaces. Therefore, it is now necessary to explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``, and ``c.balance`` to ``address(c).balance``. * Explicit conversions between unrelated contract types are now disallowed. You can only convert from a contract type to one of its base or ancestor types. If you are sure that a contract is compatible with the contract type you want to convert to, although it does not inherit from it, you can work around this by converting to ``address`` first. Example: if ``A`` and ``B`` are contract types, ``B`` does not inherit from ``A`` and ``b`` is a contract of type ``B``, you can still convert ``b`` to type ``A`` using ``A(address(b))``. Note that you still need to watch out for matching payable fallback functions, as explained below. * The ``address`` type was split into ``address`` and ``address payable``, where only ``address payable`` provides the ``transfer`` function. An ``address payable`` can be directly converted to an ``address``, but the other way around is not allowed. Converting ``address`` to ``address payable`` is possible via conversion through ``uint160``. If ``c`` is a contract, ``address(c)`` results in ``address payable`` only if ``c`` has a payable fallback function. If you use the :ref:`withdraw pattern`, you most likely do not have to change your code because ``transfer`` is only used on ``msg.sender`` instead of stored addresses and ``msg.sender`` is an ``address payable``. * Conversions between ``bytesX`` and ``uintY`` of different size are now disallowed due to ``bytesX`` padding on the right and ``uintY`` padding on the left which may cause unexpected conversion results. The size must now be adjusted within the type before the conversion. For example, you can convert a ``bytes4`` (4 bytes) to a ``uint64`` (8 bytes) by first converting the ``bytes4`` variable to ``bytes8`` and then to ``uint64``. You get the opposite padding when converting through ``uint32``. Before v0.5.0 any conversion between ``bytesX`` and ``uintY`` would go through ``uint8X``. For example ``uint8(bytes3(0x291807))`` would be converted to ``uint8(uint24(bytes3(0x291807)))`` (the result is ``0x07``). * Using ``msg.value`` in non-payable functions (or introducing it via a modifier) is disallowed as a security feature. Turn the function into ``payable`` or create a new internal function for the program logic that uses ``msg.value``. * For clarity reasons, the command-line interface now requires ``-`` if the standard input is used as source. Deprecated Elements =================== This section lists changes that deprecate prior features or syntax. Note that many of these changes were already enabled in the experimental mode ``v0.5.0``. Command-line and JSON Interfaces -------------------------------- * The command-line option ``--formal`` (used to generate Why3 output for further formal verification) was deprecated and is now removed. A new formal verification module, the SMTChecker, is enabled via ``pragma experimental SMTChecker;``. * The command-line option ``--julia`` was renamed to ``--yul`` due to the renaming of the intermediate language ``Julia`` to ``Yul``. * The ``--clone-bin`` and ``--combined-json clone-bin`` command-line options were removed. * Remappings with empty prefix are disallowed. * The JSON AST fields ``constant`` and ``payable`` were removed. The information is now present in the ``stateMutability`` field. * The JSON AST field ``isConstructor`` of the ``FunctionDefinition`` node was replaced by a field called ``kind`` which can have the value ``"constructor"``, ``"fallback"`` or ``"function"``. * In unlinked binary hex files, library address placeholders are now the first 36 hex characters of the keccak256 hash of the fully qualified library name, surrounded by ``$...$``. Previously, just the fully qualified library name was used. This reduces the chances of collisions, especially when long paths are used. Binary files now also contain a list of mappings from these placeholders to the fully qualified names. Constructors ------------ * Constructors must now be defined using the ``constructor`` keyword. * Calling base constructors without parentheses is now disallowed. * Specifying base constructor arguments multiple times in the same inheritance hierarchy is now disallowed. * Calling a constructor with arguments but with wrong argument count is now disallowed. If you only want to specify an inheritance relation without giving arguments, do not provide parentheses at all. Functions --------- * Function ``callcode`` is now disallowed (in favor of ``delegatecall``). It is still possible to use it via inline assembly. * ``suicide`` is now disallowed (in favor of ``selfdestruct``). * ``sha3`` is now disallowed (in favor of ``keccak256``). * ``throw`` is now disallowed (in favor of ``revert``, ``require`` and ``assert``). Conversions ----------- * Explicit and implicit conversions from decimal literals to ``bytesXX`` types is now disallowed. * Explicit and implicit conversions from hex literals to ``bytesXX`` types of different size is now disallowed. Literals and Suffixes --------------------- * The unit denomination ``years`` is now disallowed due to complications and confusions about leap years. * Trailing dots that are not followed by a number are now disallowed. * Combining hex numbers with unit denominations (e.g. ``0x1e wei``) is now disallowed. * The prefix ``0X`` for hex numbers is disallowed, only ``0x`` is possible. Variables --------- * Declaring empty structs is now disallowed for clarity. * The ``var`` keyword is now disallowed to favor explicitness. * Assignments between tuples with different number of components is now disallowed. * Values for constants that are not compile-time constants are disallowed. * Multi-variable declarations with mismatching number of values are now disallowed. * Uninitialized storage variables are now disallowed. * Empty tuple components are now disallowed. * Detecting cyclic dependencies in variables and structs is limited in recursion to 256. * Fixed-size arrays with a length of zero are now disallowed. Syntax ------ * Using ``constant`` as function state mutability modifier is now disallowed. * Boolean expressions cannot use arithmetic operations. * The unary ``+`` operator is now disallowed. * Literals cannot anymore be used with ``abi.encodePacked`` without prior conversion to an explicit type. * Empty return statements for functions with one or more return values are now disallowed. * The "loose assembly" syntax is now disallowed entirely, that is, jump labels, jumps and non-functional instructions cannot be used anymore. Use the new ``while``, ``switch`` and ``if`` constructs instead. * Functions without implementation cannot use modifiers anymore. * Function types with named return values are now disallowed. * Single statement variable declarations inside if/while/for bodies that are not blocks are now disallowed. * New keywords: ``calldata`` and ``constructor``. * New reserved keywords: ``alias``, ``apply``, ``auto``, ``copyof``, ``define``, ``immutable``, ``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. .. _interoperability: Interoperability With Older Contracts ===================================== It is still possible to interface with contracts written for Solidity versions prior to v0.5.0 (or the other way around) by defining interfaces for them. Consider you have the following pre-0.5.0 contract already deployed: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.4.25; // This will report a warning until version 0.4.25 of the compiler // This will not compile after 0.5.0 contract OldContract { function someOldFunction(uint8 a) { //... } function anotherOldFunction() constant returns (bool) { //... } // ... } This will no longer compile with Solidity v0.5.0. However, you can define a compatible interface for it: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; interface OldContract { function someOldFunction(uint8 a) external; function anotherOldFunction() external returns (bool); } Note that we did not declare ``anotherOldFunction`` to be ``view``, despite it being declared ``constant`` in the original contract. This is due to the fact that starting with Solidity v0.5.0 ``staticcall`` is used to call ``view`` functions. Prior to v0.5.0 the ``constant`` keyword was not enforced, so calling a function declared ``constant`` with ``staticcall`` may still revert, since the ``constant`` function may still attempt to modify storage. Consequently, when defining an interface for older contracts, you should only use ``view`` in place of ``constant`` in case you are absolutely sure that the function will work with ``staticcall``. Given the interface defined above, you can now easily use the already deployed pre-0.5.0 contract: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; interface OldContract { function someOldFunction(uint8 a) external; function anotherOldFunction() external returns (bool); } contract NewContract { function doSomething(OldContract a) public returns (bool) { a.someOldFunction(0x42); return a.anotherOldFunction(); } } Similarly, pre-0.5.0 libraries can be used by defining the functions of the library without implementation and supplying the address of the pre-0.5.0 library during linking (see :ref:`commandline-compiler` for how to use the commandline compiler for linking): .. code-block:: solidity // This will not compile after 0.6.0 // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.5.0; library OldLibrary { function someFunction(uint8 a) public returns(bool); } contract NewContract { function f(uint8 a) public returns (bool) { return OldLibrary.someFunction(a); } } Example ======= The following example shows a contract and its updated version for Solidity v0.5.0 with some of the changes listed in this section. Old version: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.4.25; // This will not compile after 0.5.0 contract OtherContract { uint x; function f(uint y) external { x = y; } function() payable external {} } contract Old { OtherContract other; uint myNumber; // Function mutability not provided, not an error. function someInteger() internal returns (uint) { return 2; } // Function visibility not provided, not an error. // Function mutability not provided, not an error. function f(uint x) returns (bytes) { // Var is fine in this version. var z = someInteger(); x += z; // Throw is fine in this version. if (x > 100) throw; bytes memory b = new bytes(x); y = -3 >> 1; // y == -1 (wrong, should be -2) do { x += 1; if (x > 10) continue; // 'Continue' causes an infinite loop. } while (x < 11); // Call returns only a Bool. bool success = address(other).call("f"); if (!success) revert(); else { // Local variables could be declared after their use. int y; } return b; } // No need for an explicit data location for 'arr' function g(uint[] arr, bytes8 x, OtherContract otherContract) public { otherContract.transfer(1 ether); // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes), // the first 4 bytes of x will be lost. This might lead to // unexpected behavior since bytesX are right padded. uint32 y = uint32(x); myNumber += y + msg.value; } } New version: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.5.0; // This will not compile after 0.6.0 contract OtherContract { uint x; function f(uint y) external { x = y; } function() payable external {} } contract New { OtherContract other; uint myNumber; // Function mutability must be specified. function someInteger() internal pure returns (uint) { return 2; } // Function visibility must be specified. // Function mutability must be specified. function f(uint x) public returns (bytes memory) { // The type must now be explicitly given. uint z = someInteger(); x += z; // Throw is now disallowed. require(x <= 100); int y = -3 >> 1; require(y == -2); do { x += 1; if (x > 10) continue; // 'Continue' jumps to the condition below. } while (x < 11); // Call returns (bool, bytes). // Data location must be specified. (bool success, bytes memory data) = address(other).call("f"); if (!success) revert(); return data; } using AddressMakePayable for address; // Data location for 'arr' must be specified function g(uint[] memory /* arr */, bytes8 x, OtherContract otherContract, address unknownContract) public payable { // 'otherContract.transfer' is not provided. // Since the code of 'OtherContract' is known and has the fallback // function, address(otherContract) has type 'address payable'. address(otherContract).transfer(1 ether); // 'unknownContract.transfer' is not provided. // 'address(unknownContract).transfer' is not provided // since 'address(unknownContract)' is not 'address payable'. // If the function takes an 'address' which you want to send // funds to, you can convert it to 'address payable' via 'uint160'. // Note: This is not recommended and the explicit type // 'address payable' should be used whenever possible. // To increase clarity, we suggest the use of a library for // the conversion (provided after the contract in this example). address payable addr = unknownContract.makePayable(); require(addr.send(1 ether)); // Since uint32 (4 bytes) is smaller than bytes8 (8 bytes), // the conversion is not allowed. // We need to convert to a common size first: bytes4 x4 = bytes4(x); // Padding happens on the right uint32 y = uint32(x4); // Conversion is consistent // 'msg.value' cannot be used in a 'non-payable' function. // We need to make the function payable myNumber += y + msg.value; } } // We can define a library for explicitly converting ``address`` // to ``address payable`` as a workaround. library AddressMakePayable { function makePayable(address x) internal pure returns (address payable) { return address(uint160(x)); } } ================================================ FILE: docs/060-breaking-changes.rst ================================================ ******************************** Solidity v0.6.0 Breaking Changes ******************************** This section highlights the main breaking changes introduced in Solidity version 0.6.0, along with the reasoning behind the changes and how to update affected code. For the full list check `the release changelog `_. Changes the Compiler Might not Warn About ========================================= This section lists changes where the behavior of your code might change without the compiler telling you about it. * The resulting type of an exponentiation is the type of the base. It used to be the smallest type that can hold both the type of the base and the type of the exponent, as with symmetric operations. Additionally, signed types are allowed for the base of the exponentiation. Explicitness Requirements ========================= This section lists changes where the code now needs to be more explicit, but the semantics do not change. For most of the topics the compiler will provide suggestions. * Functions can now only be overridden when they are either marked with the ``virtual`` keyword or defined in an interface. Functions without implementation outside an interface have to be marked ``virtual``. When overriding a function or modifier, the new keyword ``override`` must be used. When overriding a function or modifier defined in multiple parallel bases, all bases must be listed in parentheses after the keyword like so: ``override(Base1, Base2)``. * Member-access to ``length`` of arrays is now always read-only, even for storage arrays. It is no longer possible to resize storage arrays by assigning a new value to their length. Use ``push()``, ``push(value)`` or ``pop()`` instead, or assign a full array, which will of course overwrite the existing content. The reason behind this is to prevent storage collisions of gigantic storage arrays. * The new keyword ``abstract`` can be used to mark contracts as abstract. It has to be used if a contract does not implement all its functions. Abstract contracts cannot be created using the ``new`` operator, and it is not possible to generate bytecode for them during compilation. * Libraries have to implement all their functions, not only the internal ones. * The names of variables declared in inline assembly may no longer end in ``_slot`` or ``_offset``. * Variable declarations in inline assembly may no longer shadow any declaration outside the inline assembly block. If the name contains a dot, its prefix up to the dot may not conflict with any declaration outside the inline assembly block. * In inline assembly, opcodes that do not take arguments are now represented as "built-in functions" instead of standalone identifiers. So ``gas`` is now ``gas()``. * State variable shadowing is now disallowed. A derived contract can only declare a state variable ``x``, if there is no visible state variable with the same name in any of its bases. Semantic and Syntactic Changes ============================== This section lists changes where you have to modify your code and it does something else afterwards. * Conversions from external function types to ``address`` are now disallowed. Instead external function types have a member called ``address``, similar to the existing ``selector`` member. * The function ``push(value)`` for dynamic storage arrays does not return the new length anymore (it returns nothing). * The unnamed function commonly referred to as "fallback function" was split up into a new fallback function that is defined using the ``fallback`` keyword and a receive ether function defined using the ``receive`` keyword. * If present, the receive ether function is called whenever the call data is empty (whether or not ether is received). This function is implicitly ``payable``. * The new fallback function is called when no other function matches (if the receive ether function does not exist then this includes calls with empty call data). You can make this function ``payable`` or not. If it is not ``payable`` then transactions not matching any other function which send value will revert. You should only need to implement the new fallback function if you are following an upgrade or proxy pattern. New Features ============ This section lists things that were not possible prior to Solidity 0.6.0 or were more difficult to achieve. * The :ref:`try/catch statement ` allows you to react on failed external calls. * ``struct`` and ``enum`` types can be declared at file level. * Array slices can be used for calldata arrays, for example ``abi.decode(msg.data[4:], (uint, uint))`` is a low-level way to decode the function call payload. * Natspec supports multiple return parameters in developer documentation, enforcing the same naming check as ``@param``. * Yul and Inline Assembly have a new statement called ``leave`` that exits the current function. * Conversions from ``address`` to ``address payable`` are now possible via ``payable(x)``, where ``x`` must be of type ``address``. Interface Changes ================= This section lists changes that are unrelated to the language itself, but that have an effect on the interfaces of the compiler. These may change the way how you use the compiler on the command-line, how you use its programmable interface, or how you analyze the output produced by it. New Error Reporter ~~~~~~~~~~~~~~~~~~ A new error reporter was introduced, which aims at producing more accessible error messages on the command-line. It is enabled by default, but passing ``--old-reporter`` falls back to the deprecated old error reporter. Metadata Hash Options ~~~~~~~~~~~~~~~~~~~~~ The compiler now appends the `IPFS `_ hash of the metadata file to the end of the bytecode by default (for details, see documentation on :doc:`contract metadata `). Before 0.6.0, the compiler appended the `Swarm `_ hash by default, and in order to still support this behavior, the new command-line option ``--metadata-hash`` was introduced. It allows you to select the hash to be produced and appended, by passing either ``ipfs`` or ``swarm`` as value to the ``--metadata-hash`` command-line option. Passing the value ``none`` completely removes the hash. These changes can also be used via the :ref:`Standard JSON Interface` and effect the metadata JSON generated by the compiler. The recommended way to read the metadata is to read the last two bytes to determine the length of the CBOR encoding and perform a proper decoding on that data block as explained in the :ref:`metadata section`. Yul Optimizer ~~~~~~~~~~~~~ Together with the legacy bytecode optimizer, the :doc:`Yul ` optimizer is now enabled by default when you call the compiler with ``--optimize``. It can be disabled by calling the compiler with ``--no-optimize-yul``. This mostly affects code that uses ABI coder v2. C API Changes ~~~~~~~~~~~~~ The client code that uses the C API of ``libsolc`` is now in control of the memory used by the compiler. To make this change consistent, ``solidity_free`` was renamed to ``solidity_reset``, the functions ``solidity_alloc`` and ``solidity_free`` were added and ``solidity_compile`` now returns a string that must be explicitly freed via ``solidity_free()``. How to update your code ======================= This section gives detailed instructions on how to update prior code for every breaking change. * Change ``address(f)`` to ``f.address`` for ``f`` being of external function type. * Replace ``function () external [payable] { ... }`` by either ``receive() external payable { ... }``, ``fallback() external [payable] { ... }`` or both. Prefer using a ``receive`` function only, whenever possible. * Change ``uint length = array.push(value)`` to ``array.push(value);``. The new length can be accessed via ``array.length``. * Change ``array.length++`` to ``array.push()`` to increase, and use ``pop()`` to decrease the length of a storage array. * For every named return parameter in a function's ``@dev`` documentation define a ``@return`` entry which contains the parameter's name as the first word. E.g. if you have function ``f()`` defined like ``function f() public returns (uint value)`` and a ``@dev`` annotating it, document its return parameters like so: ``@return value The return value.``. You can mix named and un-named return parameters documentation so long as the notices are in the order they appear in the tuple return type. * Choose unique identifiers for variable declarations in inline assembly that do not conflict with declarations outside the inline assembly block. * Add ``virtual`` to every non-interface function you intend to override. Add ``virtual`` to all functions without implementation outside interfaces. For single inheritance, add ``override`` to every overriding function. For multiple inheritance, add ``override(A, B, ..)``, where you list all contracts that define the overridden function in the parentheses. When multiple bases define the same function, the inheriting contract must override all conflicting functions. * In inline assembly, add ``()`` to all opcodes that do not otherwise accept an argument. For example, change ``pc`` to ``pc()``, and ``gas`` to ``gas()``. ================================================ FILE: docs/070-breaking-changes.rst ================================================ ******************************** Solidity v0.7.0 Breaking Changes ******************************** This section highlights the main breaking changes introduced in Solidity version 0.7.0, along with the reasoning behind the changes and how to update affected code. For the full list check `the release changelog `_. Silent Changes of the Semantics =============================== * Exponentiation and shifts of literals by non-literals (e.g. ``1 << x`` or ``2 ** x``) will always use either the type ``uint256`` (for non-negative literals) or ``int256`` (for negative literals) to perform the operation. Previously, the operation was performed in the type of the shift amount / the exponent which can be misleading. Changes to the Syntax ===================== * In external function and contract creation calls, Ether and gas is now specified using a new syntax: ``x.f{gas: 10000, value: 2 ether}(arg1, arg2)``. The old syntax -- ``x.f.gas(10000).value(2 ether)(arg1, arg2)`` -- will cause an error. * The global variable ``now`` is deprecated, ``block.timestamp`` should be used instead. The single identifier ``now`` is too generic for a global variable and could give the impression that it changes during transaction processing, whereas ``block.timestamp`` correctly reflects the fact that it is just a property of the block. * NatSpec comments on variables are only allowed for public state variables and not for local or internal variables. * The token ``gwei`` is a keyword now (used to specify, e.g. ``2 gwei`` as a number) and cannot be used as an identifier. * String literals now can only contain printable ASCII characters and this also includes a variety of escape sequences, such as hexadecimal (``\xff``) and unicode escapes (``\u20ac``). * Unicode string literals are supported now to accommodate valid UTF-8 sequences. They are identified with the ``unicode`` prefix: ``unicode"Hello 😃"``. * State Mutability: The state mutability of functions can now be restricted during inheritance: Functions with default state mutability can be overridden by ``pure`` and ``view`` functions while ``view`` functions can be overridden by ``pure`` functions. At the same time, public state variables are considered ``view`` and even ``pure`` if they are constants. Inline Assembly --------------- * Disallow ``.`` in user-defined function and variable names in inline assembly. It is still valid if you use Solidity in Yul-only mode. * Slot and offset of storage pointer variable ``x`` are accessed via ``x.slot`` and ``x.offset`` instead of ``x_slot`` and ``x_offset``. Removal of Unused or Unsafe Features ==================================== Mappings outside Storage ------------------------ * If a struct or array contains a mapping, it can only be used in storage. Previously, mapping members were silently skipped in memory, which is confusing and error-prone. * Assignments to structs or arrays in storage does not work if they contain mappings. Previously, mappings were silently skipped during the copy operation, which is misleading and error-prone. Functions and Events -------------------- * Visibility (``public`` / ``internal``) is not needed for constructors anymore: To prevent a contract from being created, it can be marked ``abstract``. This makes the visibility concept for constructors obsolete. * Type Checker: Disallow ``virtual`` for library functions: Since libraries cannot be inherited from, library functions should not be virtual. * Multiple events with the same name and parameter types in the same inheritance hierarchy are disallowed. * ``using A for B`` only affects the contract it is mentioned in. Previously, the effect was inherited. Now, you have to repeat the ``using`` statement in all derived contracts that make use of the feature. Expressions ----------- * Shifts by signed types are disallowed. Previously, shifts by negative amounts were allowed, but reverted at runtime. * The ``finney`` and ``szabo`` denominations are removed. They are rarely used and do not make the actual amount readily visible. Instead, explicit values like ``1e20`` or the very common ``gwei`` can be used. Declarations ------------ * The keyword ``var`` cannot be used anymore. Previously, this keyword would parse but result in a type error and a suggestion about which type to use. Now, it results in a parser error. Interface Changes ================= * JSON AST: Mark hex string literals with ``kind: "hexString"``. * JSON AST: Members with value ``null`` are removed from JSON output. * NatSpec: Constructors and functions have consistent userdoc output. How to update your code ======================= This section gives detailed instructions on how to update prior code for every breaking change. * Change ``x.f.value(...)()`` to ``x.f{value: ...}()``. Similarly ``(new C).value(...)()`` to ``new C{value: ...}()`` and ``x.f.gas(...).value(...)()`` to ``x.f{gas: ..., value: ...}()``. * Change ``now`` to ``block.timestamp``. * Change types of right operand in shift operators to unsigned types. For example change ``x >> (256 - y)`` to ``x >> uint(256 - y)``. * Repeat the ``using A for B`` statements in all derived contracts if needed. * Remove the ``public`` keyword from every constructor. * Remove the ``internal`` keyword from every constructor and add ``abstract`` to the contract (if not already present). * Change ``_slot`` and ``_offset`` suffixes in inline assembly to ``.slot`` and ``.offset``, respectively. ================================================ FILE: docs/080-breaking-changes.rst ================================================ ******************************** Solidity v0.8.0 Breaking Changes ******************************** This section highlights the main breaking changes introduced in Solidity version 0.8.0. For the full list check `the release changelog `_. Silent Changes of the Semantics =============================== This section lists changes where existing code changes its behavior without the compiler notifying you about it. * Arithmetic operations revert on underflow and overflow. You can use ``unchecked { ... }`` to use the previous wrapping behavior. Checks for overflow are very common, so we made them the default to increase readability of code, even if it comes at a slight increase of gas costs. * ABI coder v2 is activated by default. You can choose to use the old behavior using ``pragma abicoder v1;``. The pragma ``pragma experimental ABIEncoderV2;`` is still valid, but it is deprecated and has no effect. If you want to be explicit, please use ``pragma abicoder v2;`` instead. Note that ABI coder v2 supports more types than v1 and performs more sanity checks on the inputs. ABI coder v2 makes some function calls more expensive and it can also make contract calls revert that did not revert with ABI coder v1 when they contain data that does not conform to the parameter types. * Exponentiation is right associative, i.e., the expression ``a**b**c`` is parsed as ``a**(b**c)``. Before 0.8.0, it was parsed as ``(a**b)**c``. This is the common way to parse the exponentiation operator. * Failing assertions and other internal checks like division by zero or arithmetic overflow do not use the invalid opcode but instead the revert opcode. More specifically, they will use error data equal to a function call to ``Panic(uint256)`` with an error code specific to the circumstances. This will save gas on errors while it still allows static analysis tools to distinguish these situations from a revert on invalid input, like a failing ``require``. * If a byte array in storage is accessed whose length is encoded incorrectly, a panic is caused. A contract cannot get into this situation unless inline assembly is used to modify the raw representation of storage byte arrays. * If constants are used in array length expressions, previous versions of Solidity would use arbitrary precision in all branches of the evaluation tree. Now, if constant variables are used as intermediate expressions, their values will be properly rounded in the same way as when they are used in run-time expressions. * The type ``byte`` has been removed. It was an alias of ``bytes1``. New Restrictions ================ This section lists changes that might cause existing contracts to not compile anymore. * There are new restrictions related to explicit conversions of literals. The previous behavior in the following cases was likely ambiguous: 1. Explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` are disallowed. 2. Explicit conversions between literals and an integer type ``T`` are only allowed if the literal lies between ``type(T).min`` and ``type(T).max``. In particular, replace usages of ``uint(-1)`` with ``type(uint).max``. 3. Explicit conversions between literals and enums are only allowed if the literal can represent a value in the enum. 4. Explicit conversions between literals and ``address`` type (e.g. ``address(literal)``) have the type ``address`` instead of ``address payable``. One can get a payable address type by using an explicit conversion, i.e., ``payable(literal)``. * :ref:`Address literals` have the type ``address`` instead of ``address payable``. They can be converted to ``address payable`` by using an explicit conversion, e.g. ``payable(0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF)``. * There are new restrictions on explicit type conversions. The conversion is only allowed when there is at most one change in sign, width or type-category (``int``, ``address``, ``bytesNN``, etc.). To perform multiple changes, use multiple conversions. Let us use the notation ``T(S)`` to denote the explicit conversion ``T(x)``, where, ``T`` and ``S`` are types, and ``x`` is any arbitrary variable of type ``S``. An example of such a disallowed conversion would be ``uint16(int8)`` since it changes both width (8 bits to 16 bits) and sign (signed integer to unsigned integer). In order to do the conversion, one has to go through an intermediate type. In the previous example, this would be ``uint16(uint8(int8))`` or ``uint16(int16(int8))``. Note that the two ways to convert will produce different results e.g., for ``-1``. The following are some examples of conversions that are disallowed by this rule. - ``address(uint)`` and ``uint(address)``: converting both type-category and width. Replace this by ``address(uint160(uint))`` and ``uint(uint160(address))`` respectively. - ``payable(uint160)``, ``payable(bytes20)`` and ``payable(integer-literal)``: converting both type-category and state-mutability. Replace this by ``payable(address(uint160))``, ``payable(address(bytes20))`` and ``payable(address(integer-literal))`` respectively. Note that ``payable(0)`` is valid and is an exception to the rule. - ``int80(bytes10)`` and ``bytes10(int80)``: converting both type-category and sign. Replace this by ``int80(uint80(bytes10))`` and ``bytes10(uint80(int80)`` respectively. - ``Contract(uint)``: converting both type-category and width. Replace this by ``Contract(address(uint160(uint)))``. These conversions were disallowed to avoid ambiguity. For example, in the expression ``uint16 x = uint16(int8(-1))``, the value of ``x`` would depend on whether the sign or the width conversion was applied first. * Function call options can only be given once, i.e. ``c.f{gas: 10000}{value: 1}()`` is invalid and has to be changed to ``c.f{gas: 10000, value: 1}()``. * The global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4`` have been removed. These are low-level functions that were largely unused. Their behavior can be accessed from inline assembly. * ``enum`` definitions cannot contain more than 256 members. This will make it safe to assume that the underlying type in the ABI is always ``uint8``. * Declarations with the name ``this``, ``super`` and ``_`` are disallowed, with the exception of public functions and events. The exception is to make it possible to declare interfaces of contracts implemented in languages other than Solidity that do permit such function names. * Remove support for the ``\b``, ``\f``, and ``\v`` escape sequences in code. They can still be inserted via hexadecimal escapes, e.g. ``\x08``, ``\x0c``, and ``\x0b``, respectively. * The global variables ``tx.origin`` and ``msg.sender`` have the type ``address`` instead of ``address payable``. One can convert them into ``address payable`` by using an explicit conversion, i.e., ``payable(tx.origin)`` or ``payable(msg.sender)``. This change was done since the compiler cannot determine whether or not these addresses are payable or not, so it now requires an explicit conversion to make this requirement visible. * Explicit conversion into ``address`` type always returns a non-payable ``address`` type. In particular, the following explicit conversions have the type ``address`` instead of ``address payable``: - ``address(u)`` where ``u`` is a variable of type ``uint160``. One can convert ``u`` into the type ``address payable`` by using two explicit conversions, i.e., ``payable(address(u))``. - ``address(b)`` where ``b`` is a variable of type ``bytes20``. One can convert ``b`` into the type ``address payable`` by using two explicit conversions, i.e., ``payable(address(b))``. - ``address(c)`` where ``c`` is a contract. Previously, the return type of this conversion depended on whether the contract can receive Ether (either by having a receive function or a payable fallback function). The conversion ``payable(c)`` has the type ``address payable`` and is only allowed when the contract ``c`` can receive Ether. In general, one can always convert ``c`` into the type ``address payable`` by using the following explicit conversion: ``payable(address(c))``. Note that ``address(this)`` falls under the same category as ``address(c)`` and the same rules apply for it. * The ``chainid`` builtin in inline assembly is now considered ``view`` instead of ``pure``. * Unary negation cannot be used on unsigned integers anymore, only on signed integers. Interface Changes ================= * The output of ``--combined-json`` has changed: JSON fields ``abi``, ``devdoc``, ``userdoc`` and ``storage-layout`` are sub-objects now. Before 0.8.0 they used to be serialised as strings. * The "legacy AST" has been removed (``--ast-json`` on the commandline interface and ``legacyAST`` for standard JSON). Use the "compact AST" (``--ast-compact-json`` resp. ``AST``) as replacement. * The old error reporter (``--old-reporter``) has been removed. How to update your code ======================= - If you rely on wrapping arithmetic, surround each operation with ``unchecked { ... }``. - Optional: If you use SafeMath or a similar library, change ``x.add(y)`` to ``x + y``, ``x.mul(y)`` to ``x * y`` etc. - Add ``pragma abicoder v1;`` if you want to stay with the old ABI coder. - Optionally remove ``pragma experimental ABIEncoderV2`` or ``pragma abicoder v2`` since it is redundant. - Change ``byte`` to ``bytes1``. - Add intermediate explicit type conversions if required. - Combine ``c.f{gas: 10000}{value: 1}()`` to ``c.f{gas: 10000, value: 1}()``. - Change ``msg.sender.transfer(x)`` to ``payable(msg.sender).transfer(x)`` or use a stored variable of ``address payable`` type. - Change ``x**y**z`` to ``(x**y)**z``. - Use inline assembly as a replacement for ``log0``, ..., ``log4``. - Negate unsigned integers by subtracting them from the maximum value of the type and adding 1 (e.g. ``type(uint256).max - x + 1``, while ensuring that ``x`` is not zero) ================================================ FILE: docs/Makefile ================================================ # Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Solidity.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Solidity.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Solidity" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Solidity" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." ================================================ FILE: docs/README.md ================================================ # Solidity Language Docs ## Local environment setup 1. Install python https://www.python.org/downloads/ 1. Install sphinx (the tool used to generate the docs) https://www.sphinx-doc.org/en/master/usage/installation.html Go to `/docs` and run `./docs.sh` to install dependencies and build the project: ```sh cd docs ./docs.sh ``` That will output the generated htmls under _build/ ## Serve environment ```py python3 -m http.server -d _build/html --cgi 8080 ``` Visit dev server at http://localhost:8080 ================================================ FILE: docs/_static/css/custom-dark.css ================================================ /* DARK MODE STYLING */ /* code directives */ :root[style*=dark] .method dt, :root[style*=dark] .class dt, :root[style*=dark] .data dt, :root[style*=dark] .attribute dt, :root[style*=dark] .function dt, :root[style*=dark] .classmethod dt, :root[style*=dark] .exception dt, :root[style*=dark] .descclassname, :root[style*=dark] .descname { background-color: #2d2d2d !important; } :root[style*=dark] .rst-content dl:not(.docutils) dt { background-color: #0008; border-top: solid 3px #fff2; border-left: solid 3px #fff2; } :root[style*=dark] em.property { color: #888888; } /* tables */ :root[style*=dark] .rst-content table.docutils td { border: 0px; } :root[style*=dark] .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td { background-color: #0002; } :root[style*=dark] .rst-content pre { background: none; } /* inlined code highlights */ :root[style*=dark] .xref, :root[style*=dark] .py-meth { color: #aaddff !important; font-weight: normal !important; } /* highlight color search text */ :root[style*=dark] .rst-content .highlighted { background: #ff5722; box-shadow: 0 0 0 2px #f0978b; } /* notes, warnings, hints */ :root[style*=dark] .hint .admonition-title { background: #2aa87c !important; } :root[style*=dark] .warning .admonition-title { background: #cc4444 !important; } :root[style*=dark] .admonition-title { background: #3a7ca8 !important; } :root[style*=dark] .admonition, :root[style*=dark] .note { background-color: #0008 !important; } /* table of contents */ :root[style*=dark] .sidebar { background-color: #191919 !important; } :root[style*=dark] .sidebar-title { background-color: #2b2b2b !important; } :root[style*=dark] .wy-menu-vertical code.docutils.literal.notranslate { background: none !important; border: none !important; } :root[style*=dark] .toc-backref { color: grey !important; } :root[style*=dark] .highlight { background: #0008; color: #f8f8f2 } :root[style*=dark] .highlight .c { color: #888 } /* Comment */ :root[style*=dark] .highlight .err { color: #960050; background-color: #1e0010 } /* Error */ :root[style*=dark] .highlight .k { color: #66d9ef } /* Keyword */ :root[style*=dark] .highlight .l { color: #ae81ff } /* Literal */ :root[style*=dark] .highlight .n { color: #f8f8f2 } /* Name */ :root[style*=dark] .highlight .o { color: #f92672 } /* Operator */ :root[style*=dark] .highlight .p { color: #f8f8f2 } /* Punctuation */ :root[style*=dark] .highlight .ch { color: #888 } /* Comment.Hashbang */ :root[style*=dark] .highlight .cm { color: #888 } /* Comment.Multiline */ :root[style*=dark] .highlight .cp { color: #888 } /* Comment.Preproc */ :root[style*=dark] .highlight .cpf { color: #888 } /* Comment.PreprocFile */ :root[style*=dark] .highlight .c1 { color: #888 } /* Comment.Single */ :root[style*=dark] .highlight .cs { color: #888 } /* Comment.Special */ :root[style*=dark] .highlight .gd { color: #f92672 } /* Generic.Deleted */ :root[style*=dark] .highlight .ge { font-style: italic } /* Generic.Emph */ :root[style*=dark] .highlight .gi { color: #a6e22e } /* Generic.Inserted */ :root[style*=dark] .highlight .gs { font-weight: bold } /* Generic.Strong */ :root[style*=dark] .highlight .gu { color: #888 } /* Generic.Subheading */ :root[style*=dark] .highlight .kc { color: #66d9ef } /* Keyword.Constant */ :root[style*=dark] .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ :root[style*=dark] .highlight .kn { color: #f92672 } /* Keyword.Namespace */ :root[style*=dark] .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ :root[style*=dark] .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ :root[style*=dark] .highlight .kt { color: #66d9ef } /* Keyword.Type */ :root[style*=dark] .highlight .ld { color: #e6db74 } /* Literal.Date */ :root[style*=dark] .highlight .m { color: #ae81ff } /* Literal.Number */ :root[style*=dark] .highlight .s { color: #e6db74 } /* Literal.String */ :root[style*=dark] .highlight .na { color: #a6e22e } /* Name.Attribute */ :root[style*=dark] .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ :root[style*=dark] .highlight .nc { color: #a6e22e } /* Name.Class */ :root[style*=dark] .highlight .no { color: #66d9ef } /* Name.Constant */ :root[style*=dark] .highlight .nd { color: #a6e22e } /* Name.Decorator */ :root[style*=dark] .highlight .ni { color: #f8f8f2 } /* Name.Entity */ :root[style*=dark] .highlight .ne { color: #a6e22e } /* Name.Exception */ :root[style*=dark] .highlight .nf { color: #a6e22e } /* Name.Function */ :root[style*=dark] .highlight .nl { color: #f8f8f2 } /* Name.Label */ :root[style*=dark] .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ :root[style*=dark] .highlight .nx { color: #a6e22e } /* Name.Other */ :root[style*=dark] .highlight .py { color: #f8f8f2 } /* Name.Property */ :root[style*=dark] .highlight .nt { color: #f92672 } /* Name.Tag */ :root[style*=dark] .highlight .nv { color: #f8f8f2 } /* Name.Variable */ :root[style*=dark] .highlight .ow { color: #f92672 } /* Operator.Word */ :root[style*=dark] .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ :root[style*=dark] .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ :root[style*=dark] .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ :root[style*=dark] .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ :root[style*=dark] .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ :root[style*=dark] .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ :root[style*=dark] .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ :root[style*=dark] .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ :root[style*=dark] .highlight .sc { color: #e6db74 } /* Literal.String.Char */ :root[style*=dark] .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ :root[style*=dark] .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ :root[style*=dark] .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ :root[style*=dark] .highlight .se { color: #ae81ff } /* Literal.String.Escape */ :root[style*=dark] .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ :root[style*=dark] .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ :root[style*=dark] .highlight .sx { color: #e6db74 } /* Literal.String.Other */ :root[style*=dark] .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ :root[style*=dark] .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ :root[style*=dark] .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ :root[style*=dark] .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ :root[style*=dark] .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ :root[style*=dark] .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ :root[style*=dark] .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ :root[style*=dark] .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ :root[style*=dark] .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ :root[style*=dark] .highlight .il { color: #ae81ff } /* Grammar */ :root[style*=dark] .railroad-diagram { fill: white; } :root[style*=dark] .railroad-diagram path { stroke: white; } :root[style*=dark] .railroad-diagram rect { stroke: white; } :root[style*=dark] .sig-name { background-color: transparent !important; } ================================================ FILE: docs/_static/css/custom.css ================================================ /* ROOT DECLARATIONS */ :root { /* Text */ --color-a: #2B247C; --color-b: #672AC8; --color-c: #5554D9; --color-d: #9F94E8; --color-e: #AEC0F1; --color-f: #E6E3EC; /* Background */ --white: #FAF8FF; --black: #110C4E; --menu-bg: #2B247C06; --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); --navHeight: 4.5rem; --sideWidth: 300px; --maxWidth: 80rem; --desktopInlinePadding: 2rem; --mobileInlinePadding: 1rem; --currentVersionHeight: 45px; text-rendering: geometricPrecision; -webkit-font-smoothing: antialiased; } a, button { border-radius: 0; } :root[style*=dark] { --color-a: #E6E3EC !important; --color-b: #AEC0F1 !important; --color-c: #9F94E8 !important; --color-d: #5554D9 !important; --color-e: #672AC8 !important; --color-f: #2B247C !important; --white: #110C4E !important; --black: #FAF8FF !important; --menu-bg: #E6E3EC06 !important; } html, body, .unified-header::before, .wy-nav-side, .rst-versions, code, div, input[type=text], a, .wy-grid-for-nav { transition: background 150ms ease-in-out; } html, body, .wy-grid-for-nav { background-color: var(--color-f) !important; } body { font-family: "Overpass", sans-serif; } a { color: var(--color-c); } a, section { scroll-margin-top: calc(var(--navHeight) + 2rem); } hr { margin-block: 2rem; border-color: var(--color-d) !important; } /* HEADER STYLES */ h1 { font-family: 'Overpass', sans-serif; font-weight: 700; font-size: 44px; color: var(--color-a) !important; line-height: 1.1; text-wrap: balance; margin-top: 4rem; margin-bottom: 1.5rem; } section:first-of-type h1:first-of-type { font-family: 'Overpass Mono', monospace; font-size: 48px; margin-top: 3rem; margin-bottom: 5rem; } h2 { font-family: 'Overpass', sans-serif; font-weight: 700; font-size: 38px; color: var(--color-a) !important; line-height: 46px; text-wrap: balance; margin-top: 4rem; margin-bottom: 1.5rem; } *:not([role=navigation])>p[role=heading]>span, h3 { font-family: 'Overpass', sans-serif; font-weight: 700; font-size: 32px; color: var(--color-a) !important; line-height: 46px; text-wrap: balance; margin-top: 4rem; margin-bottom: 1.5rem; } h4 { font-family: 'Overpass', sans-serif; font-weight: 700; font-size: 32px; color: var(--color-a) !important; line-height: 46px; text-wrap: balance; margin-top: 3rem; margin-bottom: 1.5rem; } h5 { font-family: 'Overpass', sans-serif; font-weight: 700; font-size: 18px; color: var(--color-a) !important; line-height: 1.4; text-wrap: balance; } h6 { font-family: 'Overpass', sans-serif; font-weight: 700; font-size: 16px; color: var(--color-a) !important; line-height: 1.4; text-wrap: balance; } span.pre, pre { /* css-3 */ white-space: pre-wrap; /* Mozilla, since 1999 */ white-space: -moz-pre-wrap; /* Opera 4-6 */ white-space: -pre-wrap; /* Opera 7 */ white-space: -o-pre-wrap; word-wrap: break-word; font-family: 'Overpass Mono', monospace; } small, small * { font-size: 12px; } .wy-table-responsive table td, .wy-table-responsive table th { white-space: normal; } .rst-content table.docutils td { vertical-align: top; } /* links */ .rst-content .highlighted { background: #eac545; } /* code block highlights */ .rst-content pre { background: #fafafa; } /* project version (displayed under project logo) */ .wy-side-nav-search>div.version { color: var(--color-b); margin-top: 0; margin-bottom: 0.5rem; text-align: start; } /* Link to Remix IDE shown next to code snippets */ .rst-content p.remix-link-container { display: block; text-align: right; margin: 0; line-height: 1em; } .rst-content .remix-link-container a.remix-link { font-size: 0.7em; padding: 0.1em 0.5em; background: transparent; color: var(--color-a) !important; border: 1px solid var(--color-a); text-decoration: none; } .rst-content div.highlight-solidity, .rst-content div.highlight-yul { margin-top: 0; } /* CUSTOMIZATION UPDATES */ .wy-nav-content-wrap, .wy-nav-content { background: transparent !important; } .wy-side-nav-search { background-color: transparent !important; color: var(--color-a) !important; box-shadow: 0 4px 4px 0 var(--color-a); border-bottom: 1px solid var(--color-d) !important; } .wy-side-nav-search svg { color: var(--color-a) !important; } .wy-nav-top { background-color: transparent !important; color: var(--color-a) !important; } .wy-nav-top a { color: var(--color-a) !important; } .wy-breadcrumbs a.icon-home:before { content: "Documentation"; font-family: "Overpass", sans-serif; } .rst-content table.docutils thead { color: var(--color-a); } code.docutils.literal.notranslate { padding: 2px 4px; font-size: 0.875em; font-family: "Overpass Mono", monospace; background: var(--white); color: var(--color-c); border: 0px; } dt code.docutils.literal.notranslate { background: none; } .wy-nav-content { color: var(--color-a); } /* .rst-content a:not(:visited) { */ /* color: var(--color-b) !important; */ /* } */ .rst-content a:visited { color: var(--color-c) !important; } .rst-content a { text-decoration: underline; } .rst-content a:where(:focus, :focus-visible, :hover) { color: var(--color-d) !important; } .wy-side-scroll a { color: var(--color-a); background: transparent; font-size: 1rem; line-height: 125%; } .wy-menu-vertical li.current a, .wy-menu-vertical li.current li a, .wy-menu-vertical li.current li a code { border: none; color: var(--color-a); } ul.current ul, .wy-menu-vertical li.current a:hover, .wy-menu-vertical li.toctree-l2.current li.toctree-l3>a, .wy-menu-vertical li.toctree-l3.current li.toctree-l4>a, .wy-menu-vertical li.toctree-l4.current li.toctree-l5>a, .wy-menu-vertical li.toctree-l5.current li.toctree-l6>a, .wy-menu-vertical li.current { background: var(--menu-bg) !important; } .wy-menu.wy-menu-vertical>ul { margin-bottom: 3rem; } .wy-menu.wy-menu-vertical>p { color: var(--color-c); } .wy-menu-vertical li.on a, .wy-menu-vertical li.current>a { background: var(--menu-bg) !important; border-bottom: 0px !important; border-top: 0px !important; } .btn { border-radius: 0; text-decoration: none !important; } .wy-breadcrumbs-aside a, .wy-breadcrumbs-aside a:visited, a.fa.fa-github, a.fa.fa-github:visited, a.fa.fa-github:not(:visited), a.btn.btn-neutral:visited, a.btn.btn-neutral:not(:visited), a.btn.btn-neutral { background: transparent !important; color: var(--color-a) !important; border: 2px solid var(--color-a) !important; text-decoration: none; } .rst-content .remix-link-container a.remix-link:hover, .wy-breadcrumbs-aside a:hover, a.fa.fa-github:hover, a.btn.btn-neutral:hover { background: var(--white) !important; color: var(--color-b) !important; border-color: var(--color-b) !important; } footer .rst-footer-buttons { display: flex; justify-content: center; gap: 2rem; } /** * Customization for the unified layout */ /* Site wrapper, and two children: header and rest */ .unified-wrapper { position: relative; display: flex; flex-direction: column; inset: 0; max-width: var(--maxWidth); margin-inline: auto; } /* Site header */ .unified-header { position: fixed; top: 0; inset-inline: 0; z-index: 99999; display: flex; align-items: center; box-shadow: var(--shadow); } .unified-header .inner-header { display: flex; margin-inline: auto; width: 100%; max-width: var(--maxWidth); align-items: center; justify-content: space-between; padding-inline: var(--desktopInlinePadding); padding-block: 1rem; } .unified-header::before { content: ""; position: absolute; inset: 0; opacity: 95%; background: var(--color-f); z-index: -1; backdrop-filter: blur(3px); } .unified-header .home-link { display: block; text-decoration: none; width: 25px; height: 40px; } .unified-header .home-link:hover .solidity-logo { transform: scale(1.1); transition: transform 100ms ease-in-out; } .unified-header img.solidity-logo { transform: scale(1); transition: transform 100ms ease-in-out; width: 100%; height: 100%; } .unified-header .nav-bar { display: flex; align-items: center; justify-content: flex-end; } .unified-header .nav-bar .nav-button-container { display: flex; align-items: center; justify-content: center; gap: 0.5rem; } .unified-header .nav-link { display: inline-block; padding-inline: 8px; padding-block: 4px; font-size: 14px; font-family: 'Overpass Mono', monospace; text-decoration: none; color: var(--color-a); letter-spacing: -0.02em; font-weight: 400; box-sizing: content-box; border-bottom: 1px solid transparent; white-space: nowrap; } .unified-header .nav-link.active { background: var(--white); } .unified-header .nav-link:hover { color: var(--color-c); border-bottom: 1px solid var(--color-c); } /* Rest: Flex-row, with two children: side bar, and content */ .unified-wrapper .wy-grid-for-nav { position: relative !important; display: flex; margin-inline: auto; } /* First child: Side bar */ .unified-wrapper .wy-grid-for-nav nav.wy-nav-side { position: fixed; display: flex; flex-direction: column; background: var(--color-f); color: var(--color-a); padding-bottom: unset !important; z-index: 10 !important; min-height: unset !important; width: var(--sideWidth) !important; top: var(--navHeight); bottom: 0; left: auto; overflow: auto; } .unified-wrapper .wy-grid-for-nav nav.wy-nav-side .wy-side-scroll { position: static !important; width: unset !important; overflow: unset !important; height: unset !important; padding-bottom: 2rem; } .unified-wrapper .wy-grid-for-nav nav.wy-nav-side .wy-side-scroll .wy-side-nav-search { margin: 0 !important; width: var(--sideWidth) !important; } .wy-nav-side, .wy-side-scroll, .wy-side-nav-search, .my-menu { width: 100% !important; } .wy-nav-side input[type=text] { font-family: "Overpass", sans-serif; border-radius: 0; border-color: var(--color-d); background: var(--white); box-shadow: none; color: var(--color-a); } .wy-nav-side input[type=text]::placeholder { font-family: "Overpass", sans-serif; color: var(--color-e); font-size: 16px; position: relative; top: 4px; } /* Second child: Content */ .unified-wrapper .wy-grid-for-nav .wy-nav-content { width: 100%; max-width: unset !important; /* override */ padding-inline: var(--desktopInlinePadding); margin-inline-start: var(--sideWidth); margin-top: var(--navHeight); } .unified-wrapper .wy-grid-for-nav .wy-nav-content .rst-content { max-width: min(70ch, calc(100vw - 2 * var(--desktopInlinePadding) - var(--sideWidth))); margin-inline: auto; } .unified-wrapper.menu-open .backdrop { opacity: 0.5; } .unified-wrapper .wy-nav-side, .unified-wrapper .rst-versions { left: auto; } .unified-wrapper .backdrop { opacity: 0; transition: opacity 200ms ease-in-out; } @media (max-width: 768px) { h2 { margin-top: 3rem; margin-bottom: 1rem; } h3 { margin-top: 3rem; margin-bottom: 1rem; } h4 { margin-top: 2rem; margin-bottom: 1rem; } /* Menu closed styles */ .unified-header .nav-link { display: none; } .unified-header .inner-header { padding-inline: var(--mobileInlinePadding); } .unified-wrapper .wy-grid-for-nav nav.wy-nav-side { transform: translateX(-100%); transition: transform 200ms ease-in-out; } /* Menu open styles */ .unified-wrapper.menu-open nav.wy-nav-side { transform: translateX(0); transition: transform 200ms ease-in-out; } .unified-wrapper.menu-open .rst-versions { position: sticky; bottom: 0; width: 100%; } .unified-wrapper.menu-open .backdrop { display: block; position: fixed; inset: 0; opacity: 1; transition: opacity 200ms ease-in-out; z-index: 5; background: #0006; } a.skip-to-content { display: none; } .wy-nav-content { margin-inline-start: 0 !important; } .rst-content { max-width: 100% !important; } .wy-side-scroll { padding-bottom: 0 !important; } } ul.search .context { color: var(--color-a) !important; } .rst-versions { background: var(--color-f); } .rst-versions.shift-up { height: unset !important; max-height: unset !important; overflow-y: unset !important; } .rst-content dl:not(.docutils) dt { color: var(--color-a); background-color: #fff8; border-top: solid 3px #0002; border-inline-start: solid 3px #0002; padding: 2px 6px; } .rst-versions .rst-current-version { border-color: var(--color-d) !important; } .rst-current-version *, .rst-current-version .fa:before, .rst-current-version .fa-element { color: var(--color-b) !important; } .rst-current-version dt, .rst-current-version dd, .rst-current-version dd a, .rst-other-versions dl:last-of-type dt, .rst-other-versions dl:last-of-type dd, .rst-other-versions dl:last-of-type dd a { font-size: 14px !important; } .rst-other-versions { background: var(--white) !important; color: var(--color-a) !important; max-height: calc(100vh - var(--navHeight) - var(--currentVersionHeight)); overflow-y: scroll; } .rst-other-versions a { text-decoration: underline; color: var(--color-c) !important; } .rst-other-versions dt { color: var(--color-a) !important; } .rst-other-versions dl { margin-bottom: 1.5rem !important; } .rst-other-versions dl:last-of-type { margin-top: 2rem !important; } /* Bottom Search */ .wy-nav-side input[type=text], .rst-other-versions dl:last-of-type dd { width: 100%; } .rst-other-versions dl:last-of-type dt { color: var(--color-b) !important; } .rst-other-versions dl:last-of-type div[style*=padding], .rst-other-versions dl dd:first-of-type a { padding-inline-start: 0 !important; } button.toctree-expand { color: var(--black) !important; } /* Light/dark color mode toggle 🌓 */ button.color-toggle { display: inline-flex; appearance: none; -webkit-box-align: center; align-items: center; -webkit-box-pack: center; justify-content: center; user-select: none; outline: none; height: 28px; width: 28px; background: none; border: none; padding: 6px; margin: 6px; transition-duration: 200ms; transition-property: background-color, color, fill, stroke, opacity; } button.color-toggle:focus-visible { outline: 2px solid var(--color-c); color: var(--color-c); } button.color-toggle:hover { color: var(--color-c); background: #0002; } button.color-toggle .color-toggle-icon { width: 100%; height: 100%; margin: 0; display: inline-block; line-height: 1em; -webkit-flex-shrink: 0; -ms-flex-negative: 0; flex-shrink: 0; vertical-align: middle; /* color: var(--color-a); */ } button.mobile-menu-button { display: none; } @media (max-width: 768px) { nav.wy-nav-top { display: none; } button.mobile-menu-button { display: flex; } } .hidden { display: none; } #search-results .search li:first-child, #search-results .search li { border-color: var(--color-d); } #search-results .search li:last-child { border: 0px; } .forum-link::after { content: ' ↗'; font-size: 14px; font-family: 'Overpass Mono', monospace; } .wy-breadcrumbs>li { padding-top: 8px; } .wy-breadcrumbs-aside a { padding: 0.5rem 0.75rem; font-size: 12px; font-family: "'Overpass'", sans-serif; font-weight: 700; } a.skip-to-content:visited, a.skip-to-content:not(:visited), a.skip-to-content { display: block; pointer-events: none; width: fit-content; opacity: 0; transition: opacity 200ms ease-in-out; padding: 2px 4px; font-size: 14px; margin-inline-end: auto; margin-inline-start: 1.5rem; color: var(--color-a); white-space: nowrap; } a.skip-to-content:focus { opacity: 1; transition: opacity 200ms ease-in-out; } #content { scroll-margin-top: 6rem; scroll-behavior: smooth; } ================================================ FILE: docs/_static/css/fonts.css ================================================ @import url("https://fonts.cdnfonts.com/css/overpass"); @import url("https://fonts.cdnfonts.com/css/overpass-mono"); ================================================ FILE: docs/_static/css/pygments.css ================================================ pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #eeffcc; } .highlight .c { color: #408090; font-style: italic } /* Comment */ .highlight .err { border: 1px solid #FF0000 } /* Error */ .highlight .k { color: #007020; font-weight: bold } /* Keyword */ .highlight .o { color: #666666 } /* Operator */ .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ .highlight .cp { color: #007020 } /* Comment.Preproc */ .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #A00000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #FF0000 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #00A000 } /* Generic.Inserted */ .highlight .go { color: #333333 } /* Generic.Output */ .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .highlight .gt { color: #0044DD } /* Generic.Traceback */ .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #007020 } /* Keyword.Pseudo */ .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #902000 } /* Keyword.Type */ .highlight .m { color: #208050 } /* Literal.Number */ .highlight .s { color: #4070a0 } /* Literal.String */ .highlight .na { color: #4070a0 } /* Name.Attribute */ .highlight .nb { color: #007020 } /* Name.Builtin */ .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ .highlight .no { color: #60add5 } /* Name.Constant */ .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ .highlight .ne { color: #007020 } /* Name.Exception */ .highlight .nf { color: #06287e } /* Name.Function */ .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #bb60d5 } /* Name.Variable */ .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #208050 } /* Literal.Number.Bin */ .highlight .mf { color: #208050 } /* Literal.Number.Float */ .highlight .mh { color: #208050 } /* Literal.Number.Hex */ .highlight .mi { color: #208050 } /* Literal.Number.Integer */ .highlight .mo { color: #208050 } /* Literal.Number.Oct */ .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ .highlight .sc { color: #4070a0 } /* Literal.String.Char */ .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ .highlight .sx { color: #c65d09 } /* Literal.String.Other */ .highlight .sr { color: #235388 } /* Literal.String.Regex */ .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ .highlight .ss { color: #517918 } /* Literal.String.Symbol */ .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #06287e } /* Name.Function.Magic */ .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ ================================================ FILE: docs/_static/css/toggle.css ================================================ input[type=checkbox] { visibility: hidden; height: 0; width: 0; margin: 0; } .rst-versions .rst-current-version { padding: 10px; display: flex; justify-content: space-between; background-color: var(--color-f); border-top: 1px solid var(--color-c); } .fa-caret-down, .fa-book { color: var(--color-a) !important; } .rst-versions .rst-current-version .fa-book, .rst-versions .rst-current-version .fa-v, .rst-versions .rst-current-version .fa-caret-down { height: 24px; line-height: 24px; vertical-align: middle; } .rst-versions .rst-current-version .fa-element { width: 80px; text-align: center; } .rst-versions .rst-current-version .fa-book { text-align: left; } .rst-versions .rst-current-version .fa-v { color: #27AE60; text-align: right; } label { margin: 0 auto; display: inline-block; justify-content: center; align-items: right; border-radius: 100px; position: relative; cursor: pointer; text-indent: -9999px; width: 50px; height: 21px; background: #000; } label:after { border-radius: 50%; position: absolute; content: ''; background: #fff; width: 15px; height: 15px; top: 3px; left: 3px; transition: ease-in-out 200ms; } input:checked+label { background: #3a7ca8; } input:checked+label:after { left: calc(100% - 5px); transform: translateX(-100%); } html.transition, html.transition *, html.transition *:before, html.transition *:after { transition: ease-in-out 200ms !important; transition-delay: 0 !important; } .wy-menu-vertical a:hover { background-color: #0002; } body { font-weight: 300; letter-spacing: 0.5px; } ================================================ FILE: docs/_static/js/constants.js ================================================ // Site URL const SITE_URL = "https://docs.soliditylang.org" const { origin, pathname } = location; const pathSplit = pathname.split("/"); const rootPath = origin.includes(SITE_URL) && pathSplit.length > 3 ? pathSplit.splice(1, 2).join("/") : '' const ROOT_URL = `${origin}/${rootPath}`; // Color mode constants const [DARK, LIGHT] = ["dark", "light"]; const LIGHT_LOGO_PATH = `${ROOT_URL}/_static/img/logo.svg`; const DARK_LOGO_PATH = `${ROOT_URL}/_static/img/logo-dark.svg`; const SUN_ICON_PATH = `${ROOT_URL}/_static/img/sun.svg`; const MOON_ICON_PATH = `${ROOT_URL}/_static/img/moon.svg`; const LIGHT_HAMBURGER_PATH = `${ROOT_URL}/_static/img/hamburger-light.svg`; const DARK_HAMBURGER_PATH = `${ROOT_URL}/_static/img/hamburger-dark.svg`; const COLOR_TOGGLE_ICON_CLASS = "color-toggle-icon"; const SOLIDITY_LOGO_CLASS = "solidity-logo"; const LS_COLOR_SCHEME = "color-scheme"; // Solidity navigation constants const SOLIDITY_HOME_URL = "https://soliditylang.org"; const BLOG_URL = `${SOLIDITY_HOME_URL}/blog`; const DOCS_URL = "/"; const USE_CASES_PATH = `${SOLIDITY_HOME_URL}/use-cases`; const CONTRIBUTE_PATH = `/en/latest/contributing.html`; const ABOUT_PATH = `${SOLIDITY_HOME_URL}/about`; const FORUM_URL = "https://forum.soliditylang.org/"; const NAV_LINKS = [ { name: window.NAV_LINKS.blog, href: BLOG_URL }, { name: window.NAV_LINKS.documentation, href: DOCS_URL }, { name: window.NAV_LINKS.use_cases, href: USE_CASES_PATH }, { name: window.NAV_LINKS.contribute, href: CONTRIBUTE_PATH }, { name: window.NAV_LINKS.about, href: ABOUT_PATH }, { name: window.NAV_LINKS.forum, href: FORUM_URL }, ]; const MOBILE_MENU_TOGGLE_CLASS = "shift"; const WRAPPER_CLASS = "unified-wrapper"; ================================================ FILE: docs/_static/js/initialize.js ================================================ const getLogoSrc = (isDark) => (isDark ? DARK_LOGO_PATH : LIGHT_LOGO_PATH); const getModeIconSrc = (isDark) => (isDark ? SUN_ICON_PATH : MOON_ICON_PATH); const getMenuIconSrc = (isDark) => isDark ? DARK_HAMBURGER_PATH : LIGHT_HAMBURGER_PATH; function addFooterNote() { const contentInfo = document.querySelector("div[role=contentinfo]"); const footerNote = document.createElement("p"); footerNote.classList.add("footer-note"); footerNote.innerHTML = 'Customized with ❤️ by the ethereum.org team.'; contentInfo.parentNode.insertBefore(footerNote, contentInfo.nextSibling); } function rearrangeDom() { const bodyDivs = document.querySelectorAll("body>div"); bodyDivs.forEach((div) => div.remove()); const wrapperDiv = document.createElement("div"); wrapperDiv.classList.add(WRAPPER_CLASS); bodyDivs.forEach((div) => wrapperDiv.appendChild(div)); document.body.prepend(wrapperDiv); const rstVersions = document.querySelector(".rst-versions"); const wyNavSide = document.querySelector("nav.wy-nav-side"); // NOTE: Since RTD migration to addons, `.rst-versions` is no longer present in the DOM. // The following code is kept for compatibility with older versions. // See: https://github.com/readthedocs/readthedocs.org/issues/11474 if (rstVersions && wyNavSide) { rstVersions.remove(); wyNavSide.appendChild(rstVersions); } const backdrop = document.createElement("div"); backdrop.classList.add("backdrop"); wrapperDiv.appendChild(backdrop); const content = document.querySelector(".wy-nav-content"); if (content) { content.id = "content"; document.querySelector("section.wy-nav-content-wrap")?.remove(); document.querySelector(".wy-grid-for-nav")?.appendChild(content); } } function buildHeader() { const isDarkMode = localStorage.getItem(LS_COLOR_SCHEME) == DARK; const header = document.createElement("div"); header.classList.add("unified-header"); document.querySelector(`.${WRAPPER_CLASS}`).prepend(header); const innerHeader = document.createElement("div"); innerHeader.classList.add("inner-header"); header.appendChild(innerHeader); const homeLink = document.createElement("a"); homeLink.classList.add("home-link"); homeLink.href = SOLIDITY_HOME_URL; homeLink.ariaLabel = "Solidity home"; innerHeader.appendChild(homeLink); const logo = document.createElement("img"); logo.classList.add(SOLIDITY_LOGO_CLASS); logo.src = getLogoSrc(isDarkMode); logo.alt = "Solidity logo"; homeLink.appendChild(logo); const skipToContent = document.createElement("a"); skipToContent.classList.add("skip-to-content"); skipToContent.href = "#content"; skipToContent.innerText = "{skip to content}"; innerHeader.appendChild(skipToContent); const navBar = document.createElement("nav"); navBar.classList.add("nav-bar"); innerHeader.appendChild(navBar); const linkElements = NAV_LINKS.map(({ name, href }) => { const link = document.createElement("a"); link.classList.add("nav-link"); link.setAttribute("key", name); link.setAttribute("href", href); link.setAttribute("aria-label", name); if (href === FORUM_URL) { link.classList.add("forum-link"); link.setAttribute("target", "_blank"); link.setAttribute("rel", "noopener noreferrer"); } link.innerText = name; return link; }); linkElements.forEach((link) => navBar.appendChild(link)); // Flex wrapper for color mode and mobile menu buttons const navButtonContainer = document.createElement("div"); navButtonContainer.classList.add("nav-button-container"); navBar.appendChild(navButtonContainer); // Build color toggle const toggleIcon = document.createElement("img"); toggleIcon.classList.add(COLOR_TOGGLE_ICON_CLASS); toggleIcon.src = getModeIconSrc(isDarkMode); toggleIcon.alt = "Color mode toggle icon"; toggleIcon.setAttribute("aria-hidden", "true"); toggleIcon.setAttribute("key", "toggle icon"); const colorModeButton = document.createElement("button"); colorModeButton.classList.add("color-toggle"); colorModeButton.setAttribute("type", "button"); colorModeButton.setAttribute("aria-label", "Toggle light dark mode"); colorModeButton.setAttribute("key", "color mode button"); colorModeButton.addEventListener("click", toggleColorMode); colorModeButton.appendChild(toggleIcon); navButtonContainer.appendChild(colorModeButton); // Build mobile hamburger menu const menuIcon = document.createElement("img"); menuIcon.classList.add(COLOR_TOGGLE_ICON_CLASS); menuIcon.src = getMenuIconSrc(isDarkMode); menuIcon.alt = "Toggle menu"; menuIcon.setAttribute("aria-hidden", "true"); menuIcon.setAttribute("key", "menu icon"); const menuButton = document.createElement("button"); menuButton.classList.add("color-toggle"); menuButton.classList.add("mobile-menu-button"); menuButton.setAttribute("type", "button"); menuButton.setAttribute("aria-label", "Toggle menu"); menuButton.setAttribute("key", "menu button"); menuButton.addEventListener("click", toggleMenu); menuButton.appendChild(menuIcon); navButtonContainer.appendChild(menuButton); } const updateActiveNavLink = () => { const navLinks = document.querySelectorAll(".unified-header .nav-link"); navLinks.forEach((link) => { const href = link.getAttribute("href"); if (document.documentURI.includes("contributing.html")) { link.classList[href.includes("contributing.html") ? "add" : "remove"]( "active" ); } else { link.classList[document.documentURI.includes(href) ? "add" : "remove"]( "active" ); } }); }; document.addEventListener("locationchange", updateActiveNavLink); function updateGitHubEditPath() { // Replaces the version number in the GitHub edit path with "develop" if it exists. // This is to ensure that the edit path always points to the `develop` branch instead of the specific version branch. // Note that it will fail silently if the anchor element is not found, i.e. the page is not editable or // if the sphinx_rtd_theme is updated to a version that changes the anchor element. // See: https://github.com/readthedocs/sphinx_rtd_theme/blob/a1c2147b17cbf0e57b7d7a6450ad4d9a5ff362cf/sphinx_rtd_theme/breadcrumbs.html#L35 // TODO: We should consider a more robust way to handle this in the future. const gitHubEditAnchor = document.querySelector(".wy-breadcrumbs-aside > a"); if (!gitHubEditAnchor) return; const url = new URL(gitHubEditAnchor.href); const split = url.pathname.split("/"); const versionIndex = split.indexOf("blob") + 1; split[versionIndex] = "develop"; url.pathname = split.join("/"); gitHubEditAnchor.setAttribute("href", url.toString()); gitHubEditAnchor.setAttribute("target", "_blank"); gitHubEditAnchor.setAttribute("rel", "noopener noreferrer"); } function initialize() { // Rearrange DOM elements for styling rearrangeDom(); // Check localStorage for existing color scheme preference var prefersDark = localStorage.getItem(LS_COLOR_SCHEME) == DARK; // Check link for search param "color"... it may be "light" or "dark" var urlParams = new URLSearchParams(window.location.search); if (urlParams.size > 0) { // This is used for color mode continuity between the main Solidity Lang site and the docs var colorSchemeParam = urlParams.get("color"); // If present, overwrite prefersDark accordingly if (colorSchemeParam) { prefersDark = colorSchemeParam == DARK; } // Remove "color" search param from URL const { location, title } = document; const { pathname, origin, search, hash } = location; const newSearchParams = new URLSearchParams(search); newSearchParams.delete("color"); const sanitizedSearch = newSearchParams.size < 1 ? "" : "?" + newSearchParams.toString(); window.history.replaceState( origin, title, pathname + sanitizedSearch + hash ); } // In case none existed, establish localStorage color scheme preference var mode = prefersDark ? DARK : LIGHT; localStorage.setItem(LS_COLOR_SCHEME, mode); // Select the root element and set the style attribute to denote color-scheme attribute document .querySelector(":root") .setAttribute("style", `--color-scheme: ${mode}`); // NOTE: Since RTD migration to addons, the elements below are no longer present in the DOM. // The following code is kept for compatibility with older versions. // Remove old input and RTD logo anchor element document.querySelector("input[name=mode]")?.remove(); document.querySelector("label[for=switch]")?.remove(); document.querySelector(".wy-side-nav-search > a")?.remove(); // Add footer note addFooterNote(); // Build header buildHeader(); // Close menu toggleMenu({ force: false }); // Update active nav link updateActiveNavLink(); // Update GitHub edit path to direct to `develop` branch updateGitHubEditPath(); } document.addEventListener("DOMContentLoaded", initialize); const handleClick = (e) => { if (e.target.closest(".backdrop")) { toggleMenu({ force: false }); } if (e.target.closest("a")) { const target = e.target.closest("a"); const href = target.getAttribute("href"); if (href.includes(SOLIDITY_HOME_URL)) { const url = new URL(href); const params = new URLSearchParams(url.search); params.set("color", localStorage.getItem(LS_COLOR_SCHEME)); url.search = params.toString(); target.setAttribute("href", url.toString()); } } }; document.addEventListener("click", handleClick); const handleKeyDown = (e) => { if (e.metaKey && e.key === "k") { document.querySelector("#rtd-search-form input")?.focus(); } else if (e.key === "Escape") { toggleMenu({ force: false }); } if (e.metaKey && e.code === "Backslash") { toggleColorMode(); } }; document.addEventListener("keydown", handleKeyDown); ================================================ FILE: docs/_static/js/toggle.js ================================================ function toggleColorMode() { // Check localStorage for previous color scheme preference, assign the opposite var newMode = localStorage.getItem(LS_COLOR_SCHEME) == DARK ? LIGHT : DARK; // Update localStorage with new color scheme preference localStorage.setItem(LS_COLOR_SCHEME, newMode); // Update the root element with the new color scheme preference document .querySelector(":root") .setAttribute("style", `--color-scheme: ${newMode}`); // Update logo document .querySelector(`img.${SOLIDITY_LOGO_CLASS}`) .setAttribute("src", newMode === LIGHT ? LIGHT_LOGO_PATH : DARK_LOGO_PATH); // Update color mode toggle icon document .querySelector(`img.${COLOR_TOGGLE_ICON_CLASS}`) .setAttribute("src", newMode === LIGHT ? MOON_ICON_PATH : SUN_ICON_PATH); // Update hamburger menu icon color document .querySelector("button.mobile-menu-button img") .setAttribute( "src", newMode === LIGHT ? LIGHT_HAMBURGER_PATH : DARK_HAMBURGER_PATH ); } function toggleMenu(options = {}) { const handleClassToggle = ({ classList }, className) => { if (typeof options.force !== "undefined") { classList.toggle(className, options.force); } else { classList.toggle(className); } }; document .querySelectorAll('[data-toggle="rst-versions"]') .forEach((e) => handleClassToggle(e, MOBILE_MENU_TOGGLE_CLASS)); document .querySelectorAll('[data-toggle="wy-nav-shift"]') .forEach((e) => handleClassToggle(e, MOBILE_MENU_TOGGLE_CLASS)); handleClassToggle(document.querySelector(`.${WRAPPER_CLASS}`), "menu-open"); } ================================================ FILE: docs/_templates/footer.html ================================================ {% extends "!footer.html" %} {% block extrafooter %}

Credits and attribution.

{% endblock %} ================================================ FILE: docs/_templates/layout.html ================================================ {% extends "!layout.html" %} {% block scripts %} {{ super() }} {% endblock %} {% block menu %} {{ super() }} {% endblock %} ================================================ FILE: docs/_templates/versions.html ================================================ {# Add rst-badge after rst-versions for small badge style. #}
RTD v: {{ current_version }}
{{ _('Downloads') }}
{% for type, url in downloads %}
{{ type }}
{% endfor %}
{{ _('Versions') }}
{% for slug, url in versions %}
{{ slug }}
{% endfor %}
{# Translators: The phrase "Read the Docs" is not translated #}
{{ _('On Read the Docs') }}
{{ _('Project Home') }}
{{ _('Builds') }}
================================================ FILE: docs/abi-spec.rst ================================================ .. index:: abi, application binary interface .. _ABI: ************************** Contract ABI Specification ************************** Basic Design ============ The Contract Application Binary Interface (ABI) is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interaction. Data is encoded according to its type, as described in this specification. The encoding is not self describing and thus requires a schema in order to decode. We assume that the interface functions of a contract are strongly typed, known at compilation time and static. We assume that all contracts will have the interface definitions of any contracts they call available at compile-time. This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. Also, the ABI specification for libraries is :ref:`slightly different `. .. _abi_function_selector: .. index:: ! selector; of a function Function Selector ================= The first four bytes of the call data for a function call specifies the function to be called. It is the first (left, high-order in big-endian) four bytes of the Keccak-256 hash of the signature of the function. The signature is defined as the canonical expression of the basic prototype without data location specifier, i.e. the function name with the parenthesised list of parameter types. Parameter types are split by a single comma — no spaces are used. .. note:: The return type of a function is not part of this signature. In :ref:`Solidity's function overloading ` return types are not considered. The reason is to keep function call resolution context-independent. The :ref:`JSON description of the ABI` however contains both inputs and outputs. Argument Encoding ================= Starting from the fifth byte, the encoded arguments follow. This encoding is also used in other places, e.g. the return values and also event arguments are encoded in the same way, without the four bytes specifying the function. Types ===== Note that the library ABIs can take types different than below e.g. for non-storage structs. See :ref:`library selectors ` for details. The following elementary types exist: - ``uint``: unsigned integer type of ``M`` bits, ``0 < M <= 256``, ``M % 8 == 0``. e.g. ``uint32``, ``uint8``, ``uint256``. - ``int``: two's complement signed integer type of ``M`` bits, ``0 < M <= 256``, ``M % 8 == 0``. - ``address``: equivalent to ``uint160``, except for the assumed interpretation and language typing. For computing the function selector, ``address`` is used. - ``uint``, ``int``: synonyms for ``uint256``, ``int256`` respectively. For computing the function selector, ``uint256`` and ``int256`` have to be used. - ``bool``: equivalent to ``uint8`` restricted to the values 0 and 1. For computing the function selector, ``bool`` is used. - ``fixedx``: signed fixed-point decimal number of ``M`` bits, ``8 <= M <= 256``, ``M % 8 == 0``, and ``0 < N <= 80``, which denotes the value ``v`` as ``v / (10 ** N)``. - ``ufixedx``: unsigned variant of ``fixedx``. - ``fixed``, ``ufixed``: synonyms for ``fixed128x18``, ``ufixed128x18`` respectively. For computing the function selector, ``fixed128x18`` and ``ufixed128x18`` have to be used. - ``bytes``: binary type of ``M`` bytes, ``0 < M <= 32``. - ``function``: an address (20 bytes) followed by a function selector (4 bytes). Encoded identical to ``bytes24``. The following (fixed-size) array type exists: - ``[M]``: a fixed-length array of ``M`` elements, ``M >= 0``, of the given type. .. note:: While this ABI specification can express fixed-length arrays with zero elements, they're not supported by the compiler. The following non-fixed-size types exist: - ``bytes``: dynamic sized byte sequence. - ``string``: dynamic sized unicode string assumed to be UTF-8 encoded. - ``[]``: a variable-length array of elements of the given type. Types can be combined to a tuple by enclosing them inside parentheses, separated by commas: - ``(T1,T2,...,Tn)``: tuple consisting of the types ``T1``, ..., ``Tn``, ``n >= 0`` It is possible to form tuples of tuples, arrays of tuples and so on. It is also possible to form zero-tuples (where ``n == 0``). Mapping Solidity to ABI types ----------------------------- Solidity supports all the types presented above with the same names with the exception of tuples. On the other hand, some Solidity types are not supported by the ABI. The following table shows on the left column Solidity types that are not part of the ABI, and on the right column the ABI types that represent them. +-------------------------------+-----------------------------------------------------------------------------+ | Solidity | ABI | +===============================+=============================================================================+ |:ref:`address payable
`|``address`` | +-------------------------------+-----------------------------------------------------------------------------+ |:ref:`contract` |``address`` | +-------------------------------+-----------------------------------------------------------------------------+ |:ref:`enum` |``uint8`` | +-------------------------------+-----------------------------------------------------------------------------+ |:ref:`user defined value types |its underlying value type | |` | | +-------------------------------+-----------------------------------------------------------------------------+ |:ref:`struct` |``tuple`` | +-------------------------------+-----------------------------------------------------------------------------+ .. warning:: Before version ``0.8.0`` enums could have more than 256 members and were represented by the smallest integer type just big enough to hold the value of any member. Design Criteria for the Encoding ================================ The encoding is designed to have the following properties, which are especially useful if some arguments are nested arrays: 1. The number of reads necessary to access a value is at most the depth of the value inside the argument array structure, i.e. four reads are needed to retrieve ``a_i[k][l][r]``. In a previous version of the ABI, the number of reads scaled linearly with the total number of dynamic parameters in the worst case. 2. The data of a variable or an array element is not interleaved with other data and it is relocatable, i.e. it only uses relative "addresses". Formal Specification of the Encoding ==================================== We distinguish static and dynamic types. Static types are encoded in-place and dynamic types are encoded at a separately allocated location after the current block. **Definition:** The following types are called "dynamic": * ``bytes`` * ``string`` * ``T[]`` for any ``T`` * ``T[k]`` for any dynamic ``T`` and any ``k >= 0`` * ``(T1,...,Tk)`` if ``Ti`` is dynamic for some ``1 <= i <= k`` All other types are called "static". **Definition:** ``len(a)`` is the number of bytes in a binary string ``a``. The type of ``len(a)`` is assumed to be ``uint256``. We define ``enc``, the actual encoding, as a mapping of values of the ABI types to binary strings such that ``len(enc(X))`` depends on the value of ``X`` if and only if the type of ``X`` is dynamic. **Definition:** For any ABI value ``X``, we recursively define ``enc(X)``, depending on the type of ``X`` being - ``(T1,...,Tk)`` for ``k >= 0`` and any types ``T1``, ..., ``Tk`` ``enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k))`` where ``X = (X(1), ..., X(k))`` and ``head`` and ``tail`` are defined for ``Ti`` as follows: if ``Ti`` is static: ``head(X(i)) = enc(X(i))`` and ``tail(X(i)) = ""`` (the empty string) otherwise, i.e. if ``Ti`` is dynamic: ``head(X(i)) = enc(len( head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(i-1)) ))`` ``tail(X(i)) = enc(X(i))`` Note that in the dynamic case, ``head(X(i))`` is well-defined since the lengths of the head parts only depend on the types and not the values. The value of ``head(X(i))`` is the offset of the beginning of ``tail(X(i))`` relative to the start of ``enc(X)``. - ``T[k]`` for any ``T`` and ``k``: ``enc(X) = enc((X[0], ..., X[k-1]))`` i.e. it is encoded as if it were a tuple with ``k`` elements of the same type. - ``T[]`` where ``X`` has ``k`` elements (``k`` is assumed to be of type ``uint256``): ``enc(X) = enc(k) enc((X[0], ..., X[k-1]))`` i.e. it is encoded as if it were a tuple with ``k`` elements of the same type (resp. an array of static size ``k``), prefixed with the number of elements. - ``bytes``, of length ``k`` (which is assumed to be of type ``uint256``): ``enc(X) = enc(k) pad_right(X)``, i.e. the number of bytes is encoded as a ``uint256`` followed by the actual value of ``X`` as a byte sequence, followed by the minimum number of zero-bytes such that ``len(enc(X))`` is a multiple of 32. - ``string``: ``enc(X) = enc(enc_utf8(X))``, i.e. ``X`` is UTF-8 encoded and this value is interpreted as of ``bytes`` type and encoded further. Note that the length used in this subsequent encoding is the number of bytes of the UTF-8 encoded string, not its number of characters. - ``uint``: ``enc(X)`` is the big-endian encoding of ``X``, padded on the higher-order (left) side with zero-bytes such that the length is 32 bytes. - ``address``: as in the ``uint160`` case - ``int``: ``enc(X)`` is the big-endian two's complement encoding of ``X``, padded on the higher-order (left) side with ``0xff`` bytes for negative ``X`` and with zero-bytes for non-negative ``X`` such that the length is 32 bytes. - ``bool``: as in the ``uint8`` case, where ``1`` is used for ``true`` and ``0`` for ``false`` - ``fixedx``: ``enc(X)`` is ``enc(X * 10**N)`` where ``X * 10**N`` is interpreted as a ``int256``. - ``fixed``: as in the ``fixed128x18`` case - ``ufixedx``: ``enc(X)`` is ``enc(X * 10**N)`` where ``X * 10**N`` is interpreted as a ``uint256``. - ``ufixed``: as in the ``ufixed128x18`` case - ``bytes``: ``enc(X)`` is the sequence of bytes in ``X`` padded with trailing zero-bytes to a length of 32 bytes. Note that for any ``X``, ``len(enc(X))`` is a multiple of 32. Function Selector and Argument Encoding ======================================= All in all, a call to the function ``f`` with parameters ``a_1, ..., a_n`` is encoded as ``function_selector(f) enc((a_1, ..., a_n))`` and the return values ``v_1, ..., v_k`` of ``f`` are encoded as ``enc((v_1, ..., v_k))`` i.e. the values are combined into a tuple and encoded. Examples ======== Given the contract: .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract Foo { function bar(bytes3[2] memory) public pure {} function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; } function sam(bytes memory, bool, uint[] memory) public pure {} } Thus, for our ``Foo`` example, if we wanted to call ``bar`` with the argument ``["abc", "def"]``, we would pass 68 bytes total, broken down into: - ``0xfce353f6``: the Method ID. This is derived from the signature ``bar(bytes3[2])``. - ``0x6162630000000000000000000000000000000000000000000000000000000000``: the first part of the first parameter, a ``bytes3`` value ``"abc"`` (left-aligned). - ``0x6465660000000000000000000000000000000000000000000000000000000000``: the second part of the first parameter, a ``bytes3`` value ``"def"`` (left-aligned). In total: .. code-block:: none 0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000 If we wanted to call ``baz`` with the parameters ``69`` and ``true``, we would pass 68 bytes total, which can be broken down into: - ``0xcdcd77c0``: the Method ID. This is derived as the first 4 bytes of the Keccak hash of the ASCII form of the signature ``baz(uint32,bool)``. - ``0x0000000000000000000000000000000000000000000000000000000000000045``: the first parameter, a uint32 value ``69`` padded to 32 bytes - ``0x0000000000000000000000000000000000000000000000000000000000000001``: the second parameter - boolean ``true``, padded to 32 bytes In total: .. code-block:: none 0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001 It returns a single ``bool``. If, for example, it were to return ``false``, its output would be the single byte array ``0x0000000000000000000000000000000000000000000000000000000000000000``, a single bool. If we wanted to call ``sam`` with the arguments ``"dave"``, ``true`` and ``[1,2,3]``, we would pass 292 bytes total, broken down into: - ``0xa5643bf2``: the Method ID. This is derived from the signature ``sam(bytes,bool,uint256[])``. Note that ``uint`` is replaced with its canonical representation ``uint256``. - ``0x0000000000000000000000000000000000000000000000000000000000000060``: the location of the data part of the first parameter (dynamic type), measured in bytes from the start of the arguments block. In this case, ``0x60``. - ``0x0000000000000000000000000000000000000000000000000000000000000001``: the second parameter: boolean true. - ``0x00000000000000000000000000000000000000000000000000000000000000a0``: the location of the data part of the third parameter (dynamic type), measured in bytes. In this case, ``0xa0``. - ``0x0000000000000000000000000000000000000000000000000000000000000004``: the data part of the first argument, it starts with the length of the byte array in elements, in this case, 4. - ``0x6461766500000000000000000000000000000000000000000000000000000000``: the contents of the first argument: the UTF-8 (equal to ASCII in this case) encoding of ``"dave"``, padded on the right to 32 bytes. - ``0x0000000000000000000000000000000000000000000000000000000000000003``: the data part of the third argument, it starts with the length of the array in elements, in this case, 3. - ``0x0000000000000000000000000000000000000000000000000000000000000001``: the first entry of the third parameter. - ``0x0000000000000000000000000000000000000000000000000000000000000002``: the second entry of the third parameter. - ``0x0000000000000000000000000000000000000000000000000000000000000003``: the third entry of the third parameter. In total: .. code-block:: none 0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003 Use of Dynamic Types ==================== A call to a function with the signature ``f(uint256,uint32[],bytes10,bytes)`` with values ``(0x123, [0x456, 0x789], "1234567890", "Hello, world!")`` is encoded in the following way: We take the first four bytes of ``keccak("f(uint256,uint32[],bytes10,bytes)")``, i.e. ``0x8be65246``. Then we encode the head parts of all four arguments. For the static types ``uint256`` and ``bytes10``, these are directly the values we want to pass, whereas for the dynamic types ``uint32[]`` and ``bytes``, we use the offset in bytes to the start of their data area, measured from the start of the value encoding (i.e. not counting the first four bytes containing the hash of the function signature). These are: - ``0x0000000000000000000000000000000000000000000000000000000000000123`` (``0x123`` padded to 32 bytes) - ``0x0000000000000000000000000000000000000000000000000000000000000080`` (offset to start of data part of second parameter, 4*32 bytes, exactly the size of the head part) - ``0x3132333435363738393000000000000000000000000000000000000000000000`` (``"1234567890"`` padded to 32 bytes on the right) - ``0x00000000000000000000000000000000000000000000000000000000000000e0`` (offset to start of data part of fourth parameter = offset to start of data part of first dynamic parameter + size of data part of first dynamic parameter = 4\*32 + 3\*32 (see below)) After this, the data part of the first dynamic argument, ``[0x456, 0x789]`` follows: - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements of the array, 2) - ``0x0000000000000000000000000000000000000000000000000000000000000456`` (first element) - ``0x0000000000000000000000000000000000000000000000000000000000000789`` (second element) Finally, we encode the data part of the second dynamic argument, ``"Hello, world!"``: - ``0x000000000000000000000000000000000000000000000000000000000000000d`` (number of elements (bytes in this case): 13) - ``0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000`` (``"Hello, world!"`` padded to 32 bytes on the right) All together, the encoding is (newline after function selector and each 32-bytes for clarity): .. code-block:: none 0x8be65246 0000000000000000000000000000000000000000000000000000000000000123 0000000000000000000000000000000000000000000000000000000000000080 3132333435363738393000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000e0 0000000000000000000000000000000000000000000000000000000000000002 0000000000000000000000000000000000000000000000000000000000000456 0000000000000000000000000000000000000000000000000000000000000789 000000000000000000000000000000000000000000000000000000000000000d 48656c6c6f2c20776f726c642100000000000000000000000000000000000000 Let us apply the same principle to encode the data for a function with a signature ``g(uint256[][],string[])`` with values ``([[1, 2], [3]], ["one", "two", "three"])`` but start from the most atomic parts of the encoding: First we encode the length and data of the first embedded dynamic array ``[1, 2]`` of the first root array ``[[1, 2], [3]]``: - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first array, 2; the elements themselves are ``1`` and ``2``) - ``0x0000000000000000000000000000000000000000000000000000000000000001`` (first element) - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (second element) Then we encode the length and data of the second embedded dynamic array ``[3]`` of the first root array ``[[1, 2], [3]]``: - ``0x0000000000000000000000000000000000000000000000000000000000000001`` (number of elements in the second array, 1; the element is ``3``) - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (first element) Then we need to find the offsets ``a`` and ``b`` for their respective dynamic arrays ``[1, 2]`` and ``[3]``. To calculate the offsets we can take a look at the encoded data of the first root array ``[[1, 2], [3]]`` enumerating each line in the encoding: .. code-block:: none 0 - a - offset of [1, 2] 1 - b - offset of [3] 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] 3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] 6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 Offset ``a`` points to the start of the content of the array ``[1, 2]`` which is line 2 (64 bytes); thus ``a = 0x0000000000000000000000000000000000000000000000000000000000000040``. Offset ``b`` points to the start of the content of the array ``[3]`` which is line 5 (160 bytes); thus ``b = 0x00000000000000000000000000000000000000000000000000000000000000a0``. Then we encode the embedded strings of the second root array: - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"one"``) - ``0x6f6e650000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"one"``) - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of characters in word ``"two"``) - ``0x74776f0000000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"two"``) - ``0x0000000000000000000000000000000000000000000000000000000000000005`` (number of characters in word ``"three"``) - ``0x7468726565000000000000000000000000000000000000000000000000000000`` (utf8 representation of word ``"three"``) In parallel to the first root array, since strings are dynamic elements we need to find their offsets ``c``, ``d`` and ``e``: .. code-block:: none 0 - c - offset for "one" 1 - d - offset for "two" 2 - e - offset for "three" 3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" 4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" 5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" 6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" 7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" 8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" Offset ``c`` points to the start of the content of the string ``"one"`` which is line 3 (96 bytes); thus ``c = 0x0000000000000000000000000000000000000000000000000000000000000060``. Offset ``d`` points to the start of the content of the string ``"two"`` which is line 5 (160 bytes); thus ``d = 0x00000000000000000000000000000000000000000000000000000000000000a0``. Offset ``e`` points to the start of the content of the string ``"three"`` which is line 7 (224 bytes); thus ``e = 0x00000000000000000000000000000000000000000000000000000000000000e0``. Note that the encodings of the embedded elements of the root arrays are not dependent on each other and have the same encodings for a function with a signature ``g(string[],uint256[][])``. Then we encode the length of the first root array: - ``0x0000000000000000000000000000000000000000000000000000000000000002`` (number of elements in the first root array, 2; the elements themselves are ``[1, 2]`` and ``[3]``) Then we encode the length of the second root array: - ``0x0000000000000000000000000000000000000000000000000000000000000003`` (number of strings in the second root array, 3; the strings themselves are ``"one"``, ``"two"`` and ``"three"``) Finally we find the offsets ``f`` and ``g`` for their respective root dynamic arrays ``[[1, 2], [3]]`` and ``["one", "two", "three"]``, and assemble parts in the correct order: .. code-block:: none 0x2289b18c - function signature 0 - f - offset of [[1, 2], [3]] 1 - g - offset of ["one", "two", "three"] 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]] 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2] 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3] 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"] 11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one" 12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two" 13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three" 14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" 15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" 16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" 17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" 18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" 19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" Offset ``f`` points to the start of the content of the array ``[[1, 2], [3]]`` which is line 2 (64 bytes); thus ``f = 0x0000000000000000000000000000000000000000000000000000000000000040``. Offset ``g`` points to the start of the content of the array ``["one", "two", "three"]`` which is line 10 (320 bytes); thus ``g = 0x0000000000000000000000000000000000000000000000000000000000000140``. .. _abi_events: Events ====== Events are an abstraction of the Ethereum logging/event-watching protocol. Log entries provide the contract's address, a series of up to four topics and some arbitrary length binary data. Events leverage the existing function ABI in order to interpret this (together with an interface spec) as a properly typed structure. Given an event name and series of event parameters, we split them into two sub-series: those which are indexed and those which are not. Those which are indexed, which may number up to 3 (for non-anonymous events) or 4 (for anonymous ones), are used alongside the Keccak hash of the event signature to form the topics of the log entry. Those which are not indexed form the byte array of the event. In effect, a log entry using this ABI is described as: - ``address``: the address of the contract (intrinsically provided by Ethereum); - ``topics[0]``: ``keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")`` (``canonical_type_of`` is a function that simply returns the canonical type of a given argument, e.g. for ``uint indexed foo``, it would return ``uint256``). This value is only present in ``topics[0]`` if the event is not declared as ``anonymous``; - ``topics[n]``: ``abi_encode(EVENT_INDEXED_ARGS[n - 1])`` if the event is not declared as ``anonymous`` or ``abi_encode(EVENT_INDEXED_ARGS[n])`` if it is (``EVENT_INDEXED_ARGS`` is the series of ``EVENT_ARGS`` that are indexed); - ``data``: ABI encoding of ``EVENT_NON_INDEXED_ARGS`` (``EVENT_NON_INDEXED_ARGS`` is the series of ``EVENT_ARGS`` that are not indexed, ``abi_encode`` is the ABI encoding function used for returning a series of typed values from a function, as described above). For all types of length at most 32 bytes, the ``EVENT_INDEXED_ARGS`` array contains the value directly, padded or sign-extended (for signed integers) to 32 bytes, just as for regular ABI encoding. However, for all "complex" types or types of dynamic length, including all arrays, ``string``, ``bytes`` and structs, ``EVENT_INDEXED_ARGS`` will contain the *Keccak hash* of a special in-place encoded value (see :ref:`indexed_event_encoding`), rather than the encoded value directly. This allows applications to efficiently query for values of dynamic-length types (by setting the hash of the encoded value as the topic), but leaves applications unable to decode indexed values they have not queried for. For dynamic-length types, application developers face a trade-off between fast search for predetermined values (if the argument is indexed) and legibility of arbitrary values (which requires that the arguments not be indexed). Developers may overcome this tradeoff and achieve both efficient search and arbitrary legibility by defining events with two arguments — one indexed, one not — intended to hold the same value. .. _abi_errors: .. index:: error, selector; of an error Errors ====== In case of a failure inside a contract, the contract can use a special opcode to abort execution and revert all state changes. In addition to these effects, descriptive data can be returned to the caller. This descriptive data is the encoding of an error and its arguments in the same way as data for a function call. As an example, let us consider the following contract whose ``transfer`` function always reverts with a custom error of "insufficient balance": .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract TestToken { error InsufficientBalance(uint256 available, uint256 required); function transfer(address /*to*/, uint amount) public pure { revert InsufficientBalance(0, amount); } } The return data would be encoded in the same way as the function call ``InsufficientBalance(0, amount)`` to the function ``InsufficientBalance(uint256,uint256)``, i.e. ``0xcf479181``, ``uint256(0)``, ``uint256(amount)``. The error selectors ``0x00000000`` and ``0xffffffff`` are reserved for future use. .. warning:: Never trust error data. The error data by default bubbles up through the chain of external calls, which means that a contract may receive an error not defined in any of the contracts it calls directly. Furthermore, any contract can fake any error by returning data that matches an error signature, even if the error is not defined anywhere. .. _abi_json: JSON ==== The JSON format for a contract's interface is given by an array of function, event and error descriptions. A function description is a JSON object with the fields: - ``type``: ``"function"``, ``"constructor"``, ``"receive"`` (the :ref:`"receive Ether" function `) or ``"fallback"`` (the :ref:`"default" function `); - ``name``: the name of the function; - ``inputs``: an array of objects, each of which contains: * ``name``: the name of the parameter. * ``type``: the canonical type of the parameter (more below). * ``components``: used for tuple types (more below). - ``outputs``: an array of objects similar to ``inputs``. - ``stateMutability``: a string with one of the following values: ``pure`` (:ref:`specified to not read blockchain state `), ``view`` (:ref:`specified to not modify the blockchain state `), ``nonpayable`` (function does not accept Ether - the default) and ``payable`` (function accepts Ether). Constructor, receive, and fallback never have ``name`` or ``outputs``. Receive and fallback do not have ``inputs`` either. .. note:: Sending non-zero Ether to non-payable function will revert the transaction. .. note:: The state mutability ``nonpayable`` is reflected in Solidity by not specifying a state mutability modifier at all. An event description is a JSON object with fairly similar fields: - ``type``: always ``"event"`` - ``name``: the name of the event. - ``inputs``: an array of objects, each of which contains: * ``name``: the name of the parameter. * ``type``: the canonical type of the parameter (more below). * ``components``: used for tuple types (more below). * ``indexed``: ``true`` if the field is part of the log's topics, ``false`` if it is one of the log's data segments. - ``anonymous``: ``true`` if the event was declared as ``anonymous``. Errors look as follows: - ``type``: always ``"error"`` - ``name``: the name of the error. - ``inputs``: an array of objects, each of which contains: * ``name``: the name of the parameter. * ``type``: the canonical type of the parameter (more below). * ``components``: used for tuple types (more below). .. note:: There can be multiple errors with the same name and even with identical signature in the JSON array; for example, if the errors originate from different files in the smart contract or are referenced from another smart contract. For the ABI, only the name of the error itself is relevant and not where it is defined. For example, .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract Test { constructor() { b = hex"12345678901234567890123456789012"; } event Event(uint indexed a, bytes32 b); event Event2(uint indexed a, bytes32 b); error InsufficientBalance(uint256 available, uint256 required); function foo(uint a) public { emit Event(a, b); } bytes32 b; } would result in the JSON: .. code-block:: json [{ "type":"error", "inputs": [{"name":"available","type":"uint256"},{"name":"required","type":"uint256"}], "name":"InsufficientBalance" }, { "type":"event", "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], "name":"Event" }, { "type":"event", "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], "name":"Event2" }, { "type":"function", "inputs": [{"name":"a","type":"uint256"}], "name":"foo", "outputs": [] }] Handling tuple types -------------------- Despite the fact that names are intentionally not part of the ABI encoding, they do make a lot of sense to be included in the JSON to enable displaying it to the end user. The structure is nested in the following way: An object with members ``name``, ``type`` and potentially ``components`` describes a typed variable. The canonical type is determined until a tuple type is reached and the string description up to that point is stored in ``type`` prefix with the word ``tuple``, i.e. it will be ``tuple`` followed by a sequence of ``[]`` and ``[k]`` with integers ``k``. The components of the tuple are then stored in the member ``components``, which is of an array type and has the same structure as the top-level object except that ``indexed`` is not allowed there. As an example, the code .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.5 <0.9.0; pragma abicoder v2; contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } function f(S memory, T memory, uint) public pure {} function g() public pure returns (S memory, T memory, uint) {} } would result in the JSON: .. code-block:: json [ { "name": "f", "type": "function", "inputs": [ { "name": "s", "type": "tuple", "components": [ { "name": "a", "type": "uint256" }, { "name": "b", "type": "uint256[]" }, { "name": "c", "type": "tuple[]", "components": [ { "name": "x", "type": "uint256" }, { "name": "y", "type": "uint256" } ] } ] }, { "name": "t", "type": "tuple", "components": [ { "name": "x", "type": "uint256" }, { "name": "y", "type": "uint256" } ] }, { "name": "a", "type": "uint256" } ], "outputs": [] } ] .. _abi_packed_mode: Strict Encoding Mode ==================== Strict encoding mode is the mode that leads to exactly the same encoding as defined in the formal specification above. This means that offsets have to be as small as possible while still not creating overlaps in the data areas, and thus no gaps are allowed. Usually, ABI decoders are written in a straightforward way by just following offset pointers, but some decoders might enforce strict mode. The Solidity ABI decoder currently does not enforce strict mode, but the encoder always creates data in strict mode. Non-standard Packed Mode ======================== Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode where: - types shorter than 32 bytes are concatenated directly, without padding or sign extension - dynamic types are encoded in-place and without the length. - array elements are padded, but still encoded in-place Furthermore, structs as well as nested arrays are not supported. As an example, the encoding of ``int16(-1), bytes1(0x42), uint16(0x03), string("Hello, world!")`` results in: .. code-block:: none 0xffff42000348656c6c6f2c20776f726c6421 ^^^^ int16(-1) ^^ bytes1(0x42) ^^^^ uint16(0x03) ^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field More specifically: - During the encoding, everything is encoded in-place. This means that there is no distinction between head and tail, as in the ABI encoding, and the length of an array is not encoded. - The direct arguments of ``abi.encodePacked`` are encoded without padding, as long as they are not arrays (or ``string`` or ``bytes``). - The encoding of an array is the concatenation of the encoding of its elements **with** padding. - Dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded without their length field. - The encoding of ``string`` or ``bytes`` does not apply padding at the end, unless it is part of an array or struct (then it is padded to a multiple of 32 bytes). In general, the encoding is ambiguous as soon as there are two dynamically-sized elements, because of the missing length field. If padding is needed, explicit type conversions can be used: ``abi.encodePacked(uint16(0x12)) == hex"0012"``. Since packed encoding is not used when calling functions, there is no special support for prepending a function selector. Since the encoding is ambiguous, there is no decoding function. .. warning:: If you use ``keccak256(abi.encodePacked(a, b))`` and both ``a`` and ``b`` are dynamic types, it is easy to craft collisions in the hash value by moving parts of ``a`` into ``b`` and vice-versa. More specifically, ``abi.encodePacked("a", "bc") == abi.encodePacked("ab", "c")``. If you use ``abi.encodePacked`` for signatures, authentication or data integrity, make sure to always use the same types and check that at most one of them is dynamic. Unless there is a compelling reason, ``abi.encode`` should be preferred. .. _indexed_event_encoding: Encoding of Indexed Event Parameters ==================================== Indexed event parameters that are not value types, i.e. arrays and structs are not stored directly but instead a Keccak-256 hash of an encoding is stored. This encoding is defined as follows: - the encoding of a ``bytes`` and ``string`` value is just the string contents without any padding or length prefix. - the encoding of a struct is the concatenation of the encoding of its members, always padded to a multiple of 32 bytes (even ``bytes`` and ``string``). - the encoding of an array (both dynamically- and statically-sized) is the concatenation of the encoding of its elements, always padded to a multiple of 32 bytes (even ``bytes`` and ``string``) and without any length prefix In the above, as usual, a negative number is padded by sign extension and not zero padded. ``bytesNN`` types are padded on the right while ``uintNN`` / ``intNN`` are padded on the left. .. warning:: The encoding of a struct is ambiguous if it contains more than one dynamically-sized array. Because of that, always re-check the event data and do not rely on the search result based on the indexed parameters alone. ================================================ FILE: docs/analysing-compilation-output.rst ================================================ .. index:: analyse, asm ############################# Analysing the Compiler Output ############################# It is often useful to look at the assembly code generated by the compiler. The generated binary, i.e., the output of ``solc --bin contract.sol``, is generally difficult to read. It is recommended to use the flag ``--asm`` to analyse the assembly output. Even for large contracts, looking at a visual diff of the assembly before and after a change is often very enlightening. Consider the following contract (named, say ``contract.sol``): .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; contract C { function one() public pure returns (uint) { return 1; } } The following would be the output of ``solc --asm contract.sol`` .. code-block:: none ======= contract.sol:C ======= EVM assembly: /* "contract.sol":0:86 contract C {... */ mstore(0x40, 0x80) callvalue dup1 iszero tag_1 jumpi 0x00 dup1 revert tag_1: pop dataSize(sub_0) dup1 dataOffset(sub_0) 0x00 codecopy 0x00 return stop sub_0: assembly { /* "contract.sol":0:86 contract C {... */ mstore(0x40, 0x80) callvalue dup1 iszero tag_1 jumpi 0x00 dup1 revert tag_1: pop jumpi(tag_2, lt(calldatasize, 0x04)) shr(0xe0, calldataload(0x00)) dup1 0x901717d1 eq tag_3 jumpi tag_2: 0x00 dup1 revert /* "contract.sol":17:84 function one() public pure returns (uint) {... */ tag_3: tag_4 tag_5 jump // in tag_4: mload(0x40) tag_6 swap2 swap1 tag_7 jump // in tag_6: mload(0x40) dup1 swap2 sub swap1 return tag_5: /* "contract.sol":53:57 uint */ 0x00 /* "contract.sol":76:77 1 */ 0x01 /* "contract.sol":69:77 return 1 */ swap1 pop /* "contract.sol":17:84 function one() public pure returns (uint) {... */ swap1 jump // out /* "#utility.yul":7:125 */ tag_10: /* "#utility.yul":94:118 */ tag_12 /* "#utility.yul":112:117 */ dup2 /* "#utility.yul":94:118 */ tag_13 jump // in tag_12: /* "#utility.yul":89:92 */ dup3 /* "#utility.yul":82:119 */ mstore /* "#utility.yul":72:125 */ pop pop jump // out /* "#utility.yul":131:353 */ tag_7: 0x00 /* "#utility.yul":262:264 */ 0x20 /* "#utility.yul":251:260 */ dup3 /* "#utility.yul":247:265 */ add /* "#utility.yul":239:265 */ swap1 pop /* "#utility.yul":275:346 */ tag_15 /* "#utility.yul":343:344 */ 0x00 /* "#utility.yul":332:341 */ dup4 /* "#utility.yul":328:345 */ add /* "#utility.yul":319:325 */ dup5 /* "#utility.yul":275:346 */ tag_10 jump // in tag_15: /* "#utility.yul":229:353 */ swap3 swap2 pop pop jump // out /* "#utility.yul":359:436 */ tag_13: 0x00 /* "#utility.yul":425:430 */ dup2 /* "#utility.yul":414:430 */ swap1 pop /* "#utility.yul":404:436 */ swap2 swap1 pop jump // out auxdata: 0xa2646970667358221220a5874f19737ddd4c5d77ace1619e5160c67b3d4bedac75fce908fed32d98899864736f6c637827302e382e342d646576656c6f702e323032312e332e33302b636f6d6d69742e65613065363933380058 } Alternatively, the above output can also be obtained from `Remix `_, under the option "Compilation Details" after compiling a contract. Notice that the ``asm`` output starts with the creation / constructor code. The deploy code is provided as part of the sub object (in the above example, it is part of the sub-object ``sub_0``). The ``auxdata`` field corresponds to the contract :ref:`metadata `. The comments in the assembly output point to the source location. Note that ``#utility.yul`` is an internally generated file of utility functions that can be obtained using the flags ``--combined-json generated-sources,generated-sources-runtime``. Similarly, the optimized assembly can be obtained with the command: ``solc --optimize --asm contract.sol``. Often times, it is interesting to see if two different sources in Solidity result in the same optimized code. For example, to see if the expressions ``(a * b) / c``, ``a * b / c`` generates the same bytecode. This can be easily done by taking a ``diff`` of the corresponding assembly output, after potentially stripping comments that reference the source locations. .. note:: The ``--asm`` output is not designed to be machine readable. Therefore, there may be breaking changes on the output between minor versions of solc. ================================================ FILE: docs/assembly.rst ================================================ .. _inline-assembly: ############### Inline Assembly ############### .. index:: ! assembly, ! asm, ! evmasm You can interleave Solidity statements with inline assembly in a language close to the one of the Ethereum Virtual Machine. This gives you more fine-grained control, which is especially useful when you are enhancing the language by writing libraries or optimizing gas usage. The language used for inline assembly in Solidity is called :ref:`Yul ` and it is documented in its own section. This section will only cover how the inline assembly code can interface with the surrounding Solidity code. .. warning:: Inline assembly is a way to access the Ethereum Virtual Machine at a low level. This bypasses several important safety features and checks of Solidity. You should only use it for tasks that need it, and only if you are confident with using it. An inline assembly block is marked by ``assembly { ... }``, where the code inside the curly braces is code in the :ref:`Yul ` language. The inline assembly code can access local Solidity variables as explained below. Different inline assembly blocks share no namespace, i.e. it is not possible to call a Yul function or access a Yul variable defined in a different inline assembly block. Example ------- The following example provides library code to access the code of another contract and load it into a ``bytes`` variable. This is possible with "plain Solidity" too, by using ``
.code``. But the point here is that reusable assembly libraries can enhance the Solidity language without a compiler change. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; library GetCode { function at(address addr) public view returns (bytes memory code) { assembly { // retrieve the size of the code, this needs assembly let size := extcodesize(addr) // allocate output byte array - this could also be done without assembly // by using code = new bytes(size) code := mload(0x40) // new "memory end" including padding mstore(0x40, add(code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) // store length in memory mstore(code, size) // actually retrieve the code, this needs assembly extcodecopy(addr, add(code, 0x20), 0, size) } } } Inline assembly is also beneficial in cases where the optimizer fails to produce efficient code, for example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; library VectorSum { // This function is less efficient because the optimizer currently fails to // remove the bounds checks in array access. function sumSolidity(uint[] memory data) public pure returns (uint sum) { for (uint i = 0; i < data.length; ++i) sum += data[i]; } // We know that we only access the array in bounds, so we can avoid the check. // 0x20 needs to be added to an array because the first slot contains the // array length. function sumAsm(uint[] memory data) public pure returns (uint sum) { for (uint i = 0; i < data.length; ++i) { assembly { sum := add(sum, mload(add(add(data, 0x20), mul(i, 0x20)))) } } } // Same as above, but accomplish the entire code within inline assembly. function sumPureAsm(uint[] memory data) public pure returns (uint sum) { assembly { // Load the length (first 32 bytes) let len := mload(data) // Skip over the length field. // // Keep temporary variable so it can be incremented in place. // // NOTE: incrementing data would result in an unusable // data variable after this assembly block let dataElementLocation := add(data, 0x20) // Iterate until the bound is not met. for { let end := add(dataElementLocation, mul(len, 0x20)) } lt(dataElementLocation, end) { dataElementLocation := add(dataElementLocation, 0x20) } { sum := add(sum, mload(dataElementLocation)) } } } } .. index:: selector; of a function Access to External Variables, Functions and Libraries ----------------------------------------------------- You can access Solidity variables and other identifiers by using their name. Local variables of value type are directly usable in inline assembly. They can both be read and assigned to. Local variables that refer to memory evaluate to the address of the variable in memory, not the value itself. Such variables can also be assigned to, but note that an assignment will only change the pointer and not the data and that it is your responsibility to respect Solidity's memory management. See :ref:`Conventions in Solidity `. Similarly, local variables that refer to statically-sized calldata arrays or calldata structs evaluate to the address of the variable in calldata, not the value itself. The variable can also be assigned a new offset, but note that no validation is performed to ensure that the variable will not point beyond ``calldatasize()``. For external function pointers the address and the function selector can be accessed using ``x.address`` and ``x.selector``. The selector consists of four right-aligned bytes. Both values can be assigned to. For example: .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.10 <0.9.0; contract C { // Assigns a new selector and address to the return variable @fun function combineToFunctionPointer(address newAddress, uint newSelector) public pure returns (function() external fun) { assembly { fun.selector := newSelector fun.address := newAddress } } } For dynamic calldata arrays, you can access their calldata offset (in bytes) and length (number of elements) using ``x.offset`` and ``x.length``. Both expressions can also be assigned to, but as for the static case, no validation will be performed to ensure that the resulting data area is within the bounds of ``calldatasize()``. For local storage variables or state variables (including transient storage) a single Yul identifier is not sufficient, since they do not necessarily occupy a single full storage slot. Therefore, their "address" is composed of a slot and a byte-offset inside that slot. To retrieve the slot pointed to by the variable ``x``, you use ``x.slot``, and to retrieve the byte-offset you use ``x.offset``. Using ``x`` itself will result in an error. You can also assign to the ``.slot`` part of a local storage variable pointer. For these (structs, arrays or mappings), the ``.offset`` part is always zero. It is not possible to assign to the ``.slot`` or ``.offset`` part of a state variable, though. Local Solidity variables are available for assignments, for example: .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.28 <0.9.0; // This will report a warning contract C { bool transient a; uint b; function f(uint x) public returns (uint r) { assembly { // We ignore the storage slot offset, we know it is zero // in this special case. r := mul(x, sload(b.slot)) tstore(a.slot, true) } } } .. warning:: If you access variables of a type that spans less than 256 bits (for example ``uint64``, ``address``, or ``bytes16``), you cannot make any assumptions about bits not part of the encoding of the type. Especially, do not assume them to be zero. To be safe, always clear the data properly before you use it in a context where this is important: ``uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ }`` To clean signed types, you can use the ``signextend`` opcode: ``assembly { signextend(, x) }`` Since Solidity 0.6.0, the name of an inline assembly variable may not shadow any declaration visible in the scope of the inline assembly block (including variable, contract and function declarations). Since Solidity 0.7.0, variables and functions declared inside the inline assembly block may not contain ``.``, but using ``.`` is valid to access Solidity variables from outside the inline assembly block. However, it is still valid to use dots if you use Solidity in Yul-only mode. Things to Avoid --------------- Inline assembly might have a quite high-level look, but it actually is extremely low-level. Function calls, loops, ifs and switches are converted by simple rewriting rules and after that, the only thing the assembler does for you is re-arranging functional-style opcodes, counting stack height for variable access and removing stack slots for assembly-local variables when the end of their block is reached. .. _conventions-in-solidity: Conventions in Solidity ----------------------- .. _assembly-typed-variables: Values of Typed Variables ========================= In contrast to EVM assembly, Solidity has types which are narrower than 256 bits, e.g. ``uint24``. For efficiency, most arithmetic operations ignore the fact that types can be shorter than 256 bits, and the higher-order bits are cleaned when necessary, i.e., shortly before they are written to memory or before comparisons are performed. This means that if you access such a variable from within inline assembly, you might have to manually clean the higher-order bits first. .. _assembly-memory-management: Memory Management ================= Solidity manages memory in the following way. There is a "free memory pointer" at position ``0x40`` in memory. If you want to allocate memory, use the memory starting from where this pointer points at and update it. There is no guarantee that the memory has not been used before and thus you cannot assume that its contents are zero bytes. There is no built-in mechanism to release or free allocated memory. Solidity does not guarantee and does not require that the values in memory are placed at positions aligned to a multiple of any value. Here is an assembly snippet you can use for allocating memory that follows the process outlined above: .. code-block:: yul function allocate(length) -> pos { pos := mload(0x40) mstore(0x40, add(pos, length)) } The first 64 bytes of memory can be used as "scratch space" for short-term allocation. The 32 bytes after the free memory pointer (i.e., starting at ``0x60``) are meant to be zero permanently and is used as the initial value for empty dynamic memory arrays. This means that the allocatable memory starts at ``0x80``, which is the initial value of the free memory pointer. Elements in memory arrays in Solidity always occupy multiples of 32 bytes (this is even true for ``bytes1[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory arrays are pointers to memory arrays. The length of a dynamic array is stored at the first slot of the array and followed by the array elements. .. warning:: Statically-sized memory arrays do not have a length field, but it might be added later to allow better convertibility between statically and dynamically-sized arrays; so, do not rely on this. Memory Safety ============= Without the use of inline assembly, the compiler can rely on memory to remain in a well-defined state at all times. This is especially relevant for :ref:`the new code generation pipeline via Yul IR `: this code generation path can move local variables from stack to memory to avoid stack-too-deep errors and perform additional memory optimizations, if it can rely on certain assumptions about memory use. While we recommend to always respect Solidity's memory model, inline assembly allows you to use memory in an incompatible way. Therefore, moving stack variables to memory and additional memory optimizations are, by default, globally disabled in the presence of any inline assembly block that contains a memory operation or assigns to Solidity variables in memory. However, you can specifically annotate an assembly block to indicate that it in fact respects Solidity's memory model as follows: .. code-block:: solidity assembly ("memory-safe") { ... } In particular, a memory-safe assembly block may only access the following memory ranges: - Memory allocated by yourself using a mechanism like the ``allocate`` function described above. - Memory allocated by Solidity, e.g. memory within the bounds of a memory array you reference. - The scratch space between memory offset 0 and 64 mentioned above. - Temporary memory that is located *after* the value of the free memory pointer at the beginning of the assembly block, i.e. memory that is "allocated" at the free memory pointer without updating the free memory pointer. Furthermore, if the assembly block assigns to Solidity variables in memory, you need to assure that accesses to the Solidity variables only access these memory ranges. Since this is mainly about the optimizer, these restrictions still need to be followed, even if the assembly block reverts or terminates. As an example, the following assembly snippet is not memory safe, because the value of ``returndatasize()`` may exceed the 64 byte scratch space: .. code-block:: solidity assembly { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } On the other hand, the following code *is* memory safe, because memory beyond the location pointed to by the free memory pointer can safely be used as temporary scratch space: .. code-block:: solidity assembly ("memory-safe") { let p := mload(0x40) returndatacopy(p, 0, returndatasize()) revert(p, returndatasize()) } Note that you do not need to update the free memory pointer if there is no following allocation, but you can only use memory starting from the current offset given by the free memory pointer. If the memory operations use a length of zero, it is also fine to just use any offset (not only if it falls into the scratch space): .. code-block:: solidity assembly ("memory-safe") { revert(0, 0) } Note that not only memory operations in inline assembly itself can be memory-unsafe, but also assignments to Solidity variables of reference type in memory. For example the following is not memory-safe: .. code-block:: solidity bytes memory x; assembly { x := 0x40 } x[0x20] = 0x42; Inline assembly that neither involves any operations that access memory nor assigns to any Solidity variables in memory is automatically considered memory-safe and does not need to be annotated. .. warning:: It is your responsibility to make sure that the assembly actually satisfies the memory model. If you annotate an assembly block as memory-safe, but violate one of the memory assumptions, this **will** lead to incorrect and undefined behavior that cannot easily be discovered by testing. In case you are developing a library that is meant to be compatible across multiple versions of Solidity, you can use a special comment to annotate an assembly block as memory-safe: .. code-block:: solidity /// @solidity memory-safe-assembly assembly { ... } .. warning:: The ``memory-safe-assembly`` special comment is deprecated and scheduled for removal. In new code targeting recent compilers, use the assembly block annotation. Advanced Safe Use of Memory --------------------------- Beyond the strict definition of memory-safety given above, there are cases in which you may want to use more than 64 bytes of scratch space starting at memory offset ``0``. If you are careful, it can be admissible to use memory up to (and not including) offset ``0x80`` and still safely declare the assembly block as ``memory-safe``. This is admissible under either of the following conditions: - By the end of the assembly block, the free memory pointer at offset ``0x40`` is restored to a sane value (i.e. it is either restored to its original value or an increment of it due to a manual memory allocation), and the memory word at offset ``0x60`` is restored to a value of zero. - The assembly block terminates, i.e. execution can never return to high-level Solidity code. This is the case, for example, if your assembly block unconditionally ends in calling the ``revert`` opcode. Furthermore, you need to be aware that the default-value of dynamic arrays in Solidity point to memory offset ``0x60``, so for the duration of temporarily changing the value at memory offset ``0x60``, you can no longer rely on getting accurate length values when reading dynamic arrays, until you restore the zero value at ``0x60``. To be more precise, we only guarantee safety when overwriting the zero pointer, if the remainder of the assembly snippet does not interact with the memory of high-level Solidity objects (including by reading from offsets previously stored in variables). ================================================ FILE: docs/brand-guide.rst ================================================ #################### Solidity Brand Guide #################### This brand guide features information on Solidity's brand policy and logo usage guidelines. The Solidity Brand ================== The Solidity programming language is an open-source, community project governed by a core team. The core team is sponsored by the `Ethereum Foundation `_. This document aims to provide information about how to best use the Solidity brand name and logo. We encourage you to read this document carefully before using the brand name or the logo. Your cooperation is highly appreciated! Solidity Brand Name =================== "Solidity" should be used to refer to the Solidity programming language solely. Please do not use "Solidity": - To refer to any other programming language. - In a way that is misleading or may imply association of unrelated modules, tools, documentation, or other resources with the Solidity programming language. - In ways that confuse the community as to whether the Solidity programming language is open-source and free to use. Solidity Logo License ===================== .. image:: https://i.creativecommons.org/l/by/4.0/88x31.png :width: 88 :alt: Creative Commons License The Solidity logo is distributed and licensed under a `Creative Commons Attribution 4.0 International License `_. This is the most permissive Creative Commons license and allows reuse and modifications for any purpose. You are free to: - **Share** — Copy and redistribute the material in any medium or format. - **Adapt** — Remix, transform, and build upon the material for any purpose, even commercially. Under the following terms: - **Attribution** — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests that the Solidity core team endorses you or your use. When using the Solidity logo, please respect the Solidity logo guidelines. Solidity Logo Guidelines ======================== .. image:: solidity_logo.svg :width: 256 *(Right click on the logo to download it.)* Please do not: - Change the ratio of the logo (do not stretch it or cut it). - Change the colors of the logo, unless it is absolutely necessary. Credits ======= This document was, in parts, derived from the `Python Software Foundation Trademark Usage Policy `_ and the `Rust Media Guide `_. ================================================ FILE: docs/bugs.json ================================================ [ { "uid": "SOL-2026-1", "name": "TransientStorageClearingHelperCollision", "summary": "Clearing both storage and transient storage variables in the same contract may result in only one of these locations being cleared.", "description": "The IR-based code generator provides a set of Yul helper functions for basic operations, such as clearing, copying, encoding or type conversions. Not all functions are used by every contract. The codegen appends them to the generated sources individually, only when an operation that would invoke one of them is encountered. Utility functions are often specialized for different types and locations. Since Yul does not support generic functions, specialization is done by generating multiple versions of the same function, with the information distinguishing the variants embedded in their names. However, if not all the necessary bits of distinguishing information are properly accounted for, two helpers may end up with the same name, causing a collision. In this situation the codegen includes only one of them, with calls to both variants invoking it. This happened with the ``set_to_zero`` helper used when an area of transient or persistent storage needs to be cleared. The helper name was missing the location information, which resulted in a collision between the persistent and transient storage variants for the same type. This meant that contracts clearing both locations would actually clear only one, leaving the other untouched. Which location ended up being cleared depended on the order in which the code generator processed the input. The necessary condition to trigger the bug was the use of ``delete`` operator on a transient storage variable. This was due to value types being the only types supported in transient storage and ``delete`` being the only operation invoking the helper allowed on such types. The other necessary condition was clearing of persistent storage and in this case the range of affected operations was wider: operator ``delete``, array ``pop()`` or assignment that resulted in a longer array being overwritten with a shorter one. The cleared variable itself also did not necessarily have to be of the same type. It was enough that a matching value type was nested in it. It also did not always have to be the exact same value type - clearing operations on reference types are usually performed at slot granularity, treating every slot as ``uint256`` rather than clearing every value packed into it individually. To trigger the bug both operations had to be present within the same piece of bytecode. Independent contracts, not related through inheritance, would not affect each other this way. The presence of one operation only in creation code and the other only in deployed code would not trigger the bug either.", "link": "https://blog.soliditylang.org/2026/02/18/transient-storage-clearing-helper-collision-bug/", "introduced": "0.8.28", "fixed": "0.8.34", "severity": "high", "conditions": { "viaIR": true, "evmVersion": ">=cancun" } }, { "uid": "SOL-2025-1", "name": "LostStorageArrayWriteOnSlotOverflow", "summary": "Operations that involve clearing or copying from arrays that straddle the end of storage could result in silent data retention.", "description": "Solidity makes it possible to define variables that extend past the last (2**256-th) slot of storage, which results in wrap-around back to slot zero. Since EVM uses 256-bit integer arithmetic, most operations on such variables just work. The only situation which requires special attention is iteration against absolute slot addresses: the invariant that the last slot belonging to a variable has the highest address does not hold. When implemented incorrectly, a loop over an array will immediately terminate if the container spans the end of storage - due to the initial position already being greater than the end position. This affected storage array clearing loops generated by both evmasm and IR pipelines. Additionally, (only in the evmasm pipeline) copying operations whose source was an array straddling the end of storage were also affected. At the language level, the buggy code would be generated for array assignment, array initialization, delete operator, .pop() and .push(). Note that a clearing loop is inserted by the compiler not only for invocations of the delete operator, but also to zero storage when overwriting a longer array with a shorter one, popping an element or even pushing an empty element to a dynamic array. Since clearing is a separate loop, it is possible for the bug to only affect it and not the copy operation it follows (which is always the case in the IR pipeline). The bug is extremely unlikely to be triggered accidentally due to the probabilistic impossibility of a short dynamic array being allocated right at the storage boundary. On the other hand, scenarios in which a user may place a static array there intentionally do not seem realistic and are limited to unusual layouts, in which a contract does not place any storage variables at slot zero (otherwise they would overlap the array).", "link": "https://blog.soliditylang.org/2025/12/18/lost-storage-array-write-on-slot-overflow-bug/", "introduced": "0.1.0", "fixed": "0.8.32", "severity": "low" }, { "uid": "SOL-2023-3", "name": "VerbatimInvalidDeduplication", "summary": "All ``verbatim`` blocks are considered identical by deduplicator and can incorrectly be unified when surrounded by identical opcodes.", "description": "The block deduplicator is a step of the opcode-based optimizer which identifies equivalent assembly blocks and merges them into a single one. However, when blocks contained ``verbatim``, their comparison was performed incorrectly, leading to the collapse of assembly blocks which are identical except for the contents of the ``verbatim`` items. Since ``verbatim`` is only available in Yul, compilation of Solidity sources is not affected.", "link": "https://blog.soliditylang.org/2023/11/08/verbatim-invalid-deduplication-bug/", "introduced": "0.8.5", "fixed": "0.8.23", "severity": "low" }, { "uid": "SOL-2023-2", "name": "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "summary": "Optimizer sequences containing FullInliner do not preserve the evaluation order of arguments of inlined function calls in code that is not in expression-split form.", "description": "Function call arguments in Yul are evaluated right to left. This order matters when the argument expressions have side-effects, and changing it may change contract behavior. FullInliner is an optimizer step that can replace a function call with the body of that function. The transformation involves assigning argument expressions to temporary variables, which imposes an explicit evaluation order. FullInliner was written with the assumption that this order does not necessarily have to match usual argument evaluation order because the argument expressions have no side-effects. In most circumstances this assumption is true because the default optimization step sequence contains the ExpressionSplitter step. ExpressionSplitter ensures that the code is in *expression-split form*, which means that function calls cannot appear nested inside expressions, and all function call arguments have to be variables. The assumption is, however, not guaranteed to be true in general. Version 0.6.7 introduced a setting allowing users to specify an arbitrary optimization step sequence, making it possible for the FullInliner to actually encounter argument expressions with side-effects, which can result in behavior differences between optimized and unoptimized bytecode. Contracts compiled without optimization or with the default optimization sequence are not affected. To trigger the bug the user has to explicitly choose compiler settings that contain a sequence with FullInliner step not preceded by ExpressionSplitter.", "link": "https://blog.soliditylang.org/2023/07/19/full-inliner-non-expression-split-argument-evaluation-order-bug/", "introduced": "0.6.7", "fixed": "0.8.21", "severity": "low", "conditions": { "yulOptimizer": true } }, { "uid": "SOL-2023-1", "name": "MissingSideEffectsOnSelectorAccess", "summary": "Accessing the ``.selector`` member on complex expressions leaves the expression unevaluated in the legacy code generation.", "description": "When accessing the ``.selector`` member on an expression with side-effects, like an assignment, a function call or a conditional, the expression would not be evaluated in the legacy code generation. This would happen in expressions where the functions used in the expression were all known at compilation time, regardless of whether the whole expression could be evaluated at compilation time or not. Note that the code generated by the IR pipeline was unaffected and would behave as expected.", "link": "https://blog.soliditylang.org/2023/07/19/missing-side-effects-on-selector-access-bug/", "introduced": "0.6.2", "fixed": "0.8.21", "severity": "low", "conditions": { "viaIR": false } }, { "uid": "SOL-2022-7", "name": "StorageWriteRemovalBeforeConditionalTermination", "summary": "Calling functions that conditionally terminate the external EVM call using the assembly statements ``return(...)`` or ``stop()`` may result in incorrect removals of prior storage writes.", "description": "A call to a Yul function that conditionally terminates the external EVM call could result in prior storage writes being incorrectly removed by the Yul optimizer. This used to happen in cases in which it would have been valid to remove the store, if the Yul function in question never actually terminated the external call, and the control flow always returned back to the caller instead. Conditional termination within the same Yul block instead of within a called function was not affected. In Solidity with optimized via-IR code generation, any storage write before a function conditionally calling ``return(...)`` or ``stop()`` in inline assembly, may have been incorrectly removed, whenever it would have been valid to remove the write without the ``return(...)`` or ``stop()``. In optimized legacy code generation, only inline assembly that did not refer to any Solidity variables and that involved conditionally-terminating user-defined assembly functions could be affected.", "link": "https://blog.soliditylang.org/2022/09/08/storage-write-removal-before-conditional-termination/", "introduced": "0.8.13", "fixed": "0.8.17", "severity": "medium/high", "conditions": { "yulOptimizer": true } }, { "uid": "SOL-2022-6", "name": "AbiReencodingHeadOverflowWithStaticArrayCleanup", "summary": "ABI-encoding a tuple with a statically-sized calldata array in the last component would corrupt 32 leading bytes of its first dynamically encoded component.", "description": "When ABI-encoding a statically-sized calldata array, the compiler always pads the data area to a multiple of 32-bytes and ensures that the padding bytes are zeroed. In some cases, this cleanup used to be performed by always writing exactly 32 bytes, regardless of how many needed to be zeroed. This was done with the assumption that the data that would eventually occupy the area past the end of the array had not yet been written, because the encoder processes tuple components in the order they were given. While this assumption is mostly true, there is an important corner case: dynamically encoded tuple components are stored separately from the statically-sized ones in an area called the *tail* of the encoding and the tail immediately follows the *head*, which is where the statically-sized components are placed. The aforementioned cleanup, if performed for the last component of the head would cross into the tail and overwrite up to 32 bytes of the first component stored there with zeros. The only array type for which the cleanup could actually result in an overwrite were arrays with ``uint256`` or ``bytes32`` as the base element type and in this case the size of the corrupted area was always exactly 32 bytes. The problem affected tuples at any nesting level. This included also structs, which are encoded as tuples in the ABI. Note also that lists of parameters and return values of functions, events and errors are encoded as tuples.", "link": "https://blog.soliditylang.org/2022/08/08/calldata-tuple-reencoding-head-overflow-bug/", "introduced": "0.5.8", "fixed": "0.8.16", "severity": "medium", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2022-5", "name": "DirtyBytesArrayToStorage", "summary": "Copying ``bytes`` arrays from memory or calldata to storage may result in dirty storage values.", "description": "Copying ``bytes`` arrays from memory or calldata to storage is done in chunks of 32 bytes even if the length is not a multiple of 32. Thereby, extra bytes past the end of the array may be copied from calldata or memory to storage. These dirty bytes may then become observable after a ``.push()`` without arguments to the bytes array in storage, i.e. such a push will not result in a zero value at the end of the array as expected. This bug only affects the legacy code generation pipeline, the new code generation pipeline via IR is not affected.", "link": "https://blog.soliditylang.org/2022/06/15/dirty-bytes-array-to-storage-bug/", "introduced": "0.0.1", "fixed": "0.8.15", "severity": "low" }, { "uid": "SOL-2022-4", "name": "InlineAssemblyMemorySideEffects", "summary": "The Yul optimizer may incorrectly remove memory writes from inline assembly blocks, that do not access solidity variables.", "description": "The Yul optimizer considers all memory writes in the outermost Yul block that are never read from as unused and removes them. This is valid when that Yul block is the entire Yul program, which is always the case for the Yul code generated by the new via-IR pipeline. Inline assembly blocks are never optimized in isolation when using that pipeline. Instead they are optimized as a part of the whole Yul input. However, the legacy code generation pipeline (which is still the default) runs the Yul optimizer individually on an inline assembly block if the block does not refer to any local variables defined in the surrounding Solidity code. Consequently, memory writes in such inline assembly blocks are removed as well, if the written memory is never read from in the same assembly block, even if the written memory is accessed later, for example by a subsequent inline assembly block.", "link": "https://blog.soliditylang.org/2022/06/15/inline-assembly-memory-side-effects-bug/", "introduced": "0.8.13", "fixed": "0.8.15", "severity": "medium", "conditions": { "yulOptimizer": true } }, { "uid": "SOL-2022-3", "name": "DataLocationChangeInInternalOverride", "summary": "It was possible to change the data location of the parameters or return variables from ``calldata`` to ``memory`` and vice-versa while overriding internal and public functions. This caused invalid code to be generated when calling such a function internally through virtual function calls.", "description": "When calling external functions, it is irrelevant if the data location of the parameters is ``calldata`` or ``memory``, the encoding of the data does not change. Because of that, changing the data location when overriding external functions is allowed. The compiler incorrectly also allowed a change in the data location for overriding public and internal functions. Since public functions can be called internally as well as externally, this causes invalid code to be generated when such an incorrectly overridden function is called internally through the base contract. The caller provides a memory pointer, but the called function interprets it as a calldata pointer or vice-versa.", "link": "https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/", "introduced": "0.6.9", "fixed": "0.8.14", "severity": "very low" }, { "uid": "SOL-2022-2", "name": "NestedCalldataArrayAbiReencodingSizeValidation", "summary": "ABI-reencoding of nested dynamic calldata arrays did not always perform proper size checks against the size of calldata and could read beyond ``calldatasize()``.", "description": "Calldata validation for nested dynamic types is deferred until the first access to the nested values. Such an access may for example be a copy to memory or an index or member access to the outer type. While in most such accesses calldata validation correctly checks that the data area of the nested array is completely contained in the passed calldata (i.e. in the range [0, calldatasize()]), this check may not be performed, when ABI encoding such nested types again directly from calldata. For instance, this can happen, if a value in calldata with a nested dynamic array is passed to an external call, used in ``abi.encode`` or emitted as event. In such cases, if the data area of the nested array extends beyond ``calldatasize()``, ABI encoding it did not revert, but continued reading values from beyond ``calldatasize()`` (i.e. zero values).", "link": "https://blog.soliditylang.org/2022/05/17/calldata-reencode-size-check-bug/", "introduced": "0.5.8", "fixed": "0.8.14", "severity": "very low" }, { "uid": "SOL-2022-1", "name": "AbiEncodeCallLiteralAsFixedBytesBug", "summary": "Literals used for a fixed length bytes parameter in ``abi.encodeCall`` were encoded incorrectly.", "description": "For the encoding, the compiler only considered the types of the expressions in the second argument of ``abi.encodeCall`` itself, but not the parameter types of the function given as first argument. In almost all cases the abi encoding of the type of the expression matches the abi encoding of the parameter type of the given function. This is because the type checker ensures the expression is implicitly convertible to the respective parameter type. However this is not true for number literals used for fixed bytes types shorter than 32 bytes, nor for string literals used for any fixed bytes type. Number literals were encoded as numbers instead of being shifted to become left-aligned. String literals were encoded as dynamically sized memory strings instead of being converted to a left-aligned bytes value.", "link": "https://blog.soliditylang.org/2022/03/16/encodecall-bug/", "introduced": "0.8.11", "fixed": "0.8.13", "severity": "very low" }, { "uid": "SOL-2021-4", "name": "UserDefinedValueTypesBug", "summary": "User defined value types with underlying type shorter than 32 bytes used incorrect storage layout and wasted storage", "description": "The compiler did not correctly compute the storage layout of user defined value types based on types that are shorter than 32 bytes. It would always use a full storage slot for these types, even if the underlying type was shorter. This was wasteful and might have problems with tooling or contract upgrades.", "link": "https://blog.soliditylang.org/2021/09/29/user-defined-value-types-bug/", "introduced": "0.8.8", "fixed": "0.8.9", "severity": "very low" }, { "uid": "SOL-2021-3", "name": "SignedImmutables", "summary": "Immutable variables of signed integer type shorter than 256 bits can lead to values with invalid higher order bits if inline assembly is used.", "description": "When immutable variables of signed integer type shorter than 256 bits are read, their higher order bits were unconditionally set to zero. The correct operation would be to sign-extend the value, i.e. set the higher order bits to one if the sign bit is one. This sign-extension is performed by Solidity just prior to when it matters, i.e. when a value is stored in memory, when it is compared or when a division is performed. Because of that, to our knowledge, the only way to access the value in its unclean state is by reading it through inline assembly.", "link": "https://blog.soliditylang.org/2021/09/29/signed-immutables-bug/", "introduced": "0.6.5", "fixed": "0.8.9", "severity": "very low" }, { "uid": "SOL-2021-2", "name": "ABIDecodeTwoDimensionalArrayMemory", "summary": "If used on memory byte arrays, result of the function ``abi.decode`` can depend on the contents of memory outside of the actual byte array that is decoded.", "description": "The ABI specification uses pointers to data areas for everything that is dynamically-sized. When decoding data from memory (instead of calldata), the ABI decoder did not properly validate some of these pointers. More specifically, it was possible to use large values for the pointers inside arrays such that computing the offset resulted in an undetected overflow. This could lead to these pointers targeting areas in memory outside of the actual area to be decoded. This way, it was possible for ``abi.decode`` to return different values for the same encoded byte array.", "link": "https://blog.soliditylang.org/2021/04/21/decoding-from-memory-bug/", "introduced": "0.4.16", "fixed": "0.8.4", "conditions": { "ABIEncoderV2": true }, "severity": "very low" }, { "uid": "SOL-2021-1", "name": "KeccakCaching", "summary": "The bytecode optimizer incorrectly reused previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.", "description": "Solidity's bytecode optimizer has a step that can compute Keccak-256 hashes, if the contents of the memory are known during compilation time. This step also has a mechanism to determine that two Keccak-256 hashes are equal even if the values in memory are not known during compile time. This mechanism had a bug where Keccak-256 of the same memory content, but different sizes were considered equal. More specifically, ``keccak256(mpos1, length1)`` and ``keccak256(mpos2, length2)`` in some cases were considered equal if ``length1`` and ``length2``, when rounded up to nearest multiple of 32 were the same, and when the memory contents at ``mpos1`` and ``mpos2`` can be deduced to be equal. You maybe affected if you compute multiple Keccak-256 hashes of the same content, but with different lengths inside inline assembly. You are unaffected if your code uses ``keccak256`` with a length that is not a compile-time constant or if it is always a multiple of 32.", "link": "https://blog.soliditylang.org/2021/03/23/keccak-optimizer-bug/", "fixed": "0.8.3", "conditions": { "optimizer": true }, "severity": "medium" }, { "uid": "SOL-2020-11", "name": "EmptyByteArrayCopy", "summary": "Copying an empty byte array (or string) from memory or calldata to storage can result in data corruption if the target array's length is increased subsequently without storing new data.", "description": "The routine that copies byte arrays from memory or calldata to storage stores unrelated data from after the source array in the storage slot if the source array is empty. If the storage array's length is subsequently increased either by using ``.push()`` or by assigning to its ``.length`` attribute (only before 0.6.0), the newly created byte array elements will not be zero-initialized, but contain the unrelated data. You are not affected if you do not assign to ``.length`` and do not use ``.push()`` on byte arrays, or only use ``.push()`` or manually initialize the new elements.", "link": "https://blog.soliditylang.org/2020/10/19/empty-byte-array-copy-bug/", "fixed": "0.7.4", "severity": "medium" }, { "uid": "SOL-2020-10", "name": "DynamicArrayCleanup", "summary": "When assigning a dynamically-sized array with types of size at most 16 bytes in storage causing the assigned array to shrink, some parts of deleted slots were not zeroed out.", "description": "Consider a dynamically-sized array in storage whose base-type is small enough such that multiple values can be packed into a single slot, such as `uint128[]`. Let us define its length to be `l`. When this array gets assigned from another array with a smaller length, say `m`, the slots between elements `m` and `l` have to be cleaned by zeroing them out. However, this cleaning was not performed properly. Specifically, after the slot corresponding to `m`, only the first packed value was cleaned up. If this array gets resized to a length larger than `m`, the indices corresponding to the unclean parts of the slot contained the original value, instead of 0. The resizing here is performed by assigning to the array `length`, by a `push()` or via inline assembly. You are not affected if you are only using `.push()` or if you assign a value (even zero) to the new elements after increasing the length of the array.", "link": "https://blog.soliditylang.org/2020/10/07/solidity-dynamic-array-cleanup-bug/", "fixed": "0.7.3", "severity": "medium" }, { "uid": "SOL-2020-9", "name": "FreeFunctionRedefinition", "summary": "The compiler does not flag an error when two or more free functions with the same name and parameter types are defined in a source unit or when an imported free function alias shadows another free function with a different name but identical parameter types.", "description": "In contrast to functions defined inside contracts, free functions with identical names and parameter types did not create an error. Both definition of free functions with identical name and parameter types and an imported free function with an alias that shadows another function with a different name but identical parameter types were permitted due to which a call to either the multiply defined free function or the imported free function alias within a contract led to the execution of that free function which was defined first within the source unit. Subsequently defined identical free function definitions were silently ignored and their code generation was skipped.", "introduced": "0.7.1", "fixed": "0.7.2", "severity": "low" }, { "uid": "SOL-2020-8", "name": "UsingForCalldata", "summary": "Function calls to internal library functions with calldata parameters called via ``using for`` can result in invalid data being read.", "description": "Function calls to internal library functions using the ``using for`` mechanism copied all calldata parameters to memory first and passed them on like that, regardless of whether it was an internal or an external call. Due to that, the called function would receive a memory pointer that is interpreted as a calldata pointer. Since dynamically sized arrays are passed using two stack slots for calldata, but only one for memory, this can lead to stack corruption. An affected library call will consider the JUMPDEST to which it is supposed to return as part of its arguments and will instead jump out to whatever was on the stack before the call.", "introduced": "0.6.9", "fixed": "0.6.10", "severity": "very low" }, { "uid": "SOL-2020-7", "name": "MissingEscapingInFormatting", "summary": "String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.", "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intermediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.", "introduced": "0.5.14", "fixed": "0.6.8", "severity": "very low", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2020-6", "name": "ArraySliceDynamicallyEncodedBaseType", "summary": "Accessing array slices of arrays with dynamically encoded base types (e.g. multi-dimensional arrays) can result in invalid data being read.", "description": "For arrays with dynamically sized base types, index range accesses that use a start expression that is non-zero will result in invalid array slices. Any index access to such array slices will result in data being read from incorrect calldata offsets. Array slices are only supported for dynamic calldata types and all problematic type require ABIEncoderV2 to be enabled.", "introduced": "0.6.0", "fixed": "0.6.8", "severity": "very low", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2020-5", "name": "ImplicitConstructorCallvalueCheck", "summary": "The creation code of a contract that does not define a constructor but has a base that does define a constructor did not revert for calls with non-zero value.", "description": "Starting from Solidity 0.4.5 the creation code of contracts without explicit payable constructor is supposed to contain a callvalue check that results in contract creation reverting, if non-zero value is passed. However, this check was missing in case no explicit constructor was defined in a contract at all, but the contract has a base that does define a constructor. In these cases it is possible to send value in a contract creation transaction or using inline assembly without revert, even though the creation code is supposed to be non-payable.", "introduced": "0.4.5", "fixed": "0.6.8", "severity": "very low" }, { "uid": "SOL-2020-4", "name": "TupleAssignmentMultiStackSlotComponents", "summary": "Tuple assignments with components that occupy several stack slots, i.e. nested tuples, pointers to external functions or references to dynamically sized calldata arrays, can result in invalid values.", "description": "Tuple assignments did not correctly account for tuple components that occupy multiple stack slots in case the number of stack slots differs between left-hand-side and right-hand-side. This can either happen in the presence of nested tuples or if the right-hand-side contains external function pointers or references to dynamic calldata arrays, while the left-hand-side contains an omission.", "introduced": "0.1.6", "fixed": "0.6.6", "severity": "very low" }, { "uid": "SOL-2020-3", "name": "MemoryArrayCreationOverflow", "summary": "The creation of very large memory arrays can result in overlapping memory regions and thus memory corruption.", "description": "No runtime overflow checks were performed for the length of memory arrays during creation. In cases for which the memory size of an array in bytes, i.e. the array length times 32, is larger than 2^256-1, the memory allocation will overflow, potentially resulting in overlapping memory areas. The length of the array is still stored correctly, so copying or iterating over such an array will result in out-of-gas.", "link": "https://blog.soliditylang.org/2020/04/06/memory-creation-overflow-bug/", "introduced": "0.2.0", "fixed": "0.6.5", "severity": "low" }, { "uid": "SOL-2020-1", "name": "YulOptimizerRedundantAssignmentBreakContinue", "summary": "The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used. You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.", "description": "The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches. This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches. Variables declared outside of the respective for loop are not affected.", "introduced": "0.6.0", "fixed": "0.6.1", "severity": "medium", "conditions": { "yulOptimizer": true } }, { "uid": "SOL-2020-2", "name": "privateCanBeOverridden", "summary": "Private methods can be overridden by inheriting contracts.", "description": "While private methods of base contracts are not visible and cannot be called directly from the derived contract, it is still possible to declare a function of the same name and type and thus change the behaviour of the base contract's function.", "introduced": "0.3.0", "fixed": "0.5.17", "severity": "low" }, { "uid": "SOL-2020-1", "name": "YulOptimizerRedundantAssignmentBreakContinue0.5", "summary": "The Yul optimizer can remove essential assignments to variables declared inside for loops when Yul's continue or break statement is used. You are unlikely to be affected if you do not use inline assembly with for loops and continue and break statements.", "description": "The Yul optimizer has a stage that removes assignments to variables that are overwritten again or are not used in all following control-flow branches. This logic incorrectly removes such assignments to variables declared inside a for loop if they can be removed in a control-flow branch that ends with ``break`` or ``continue`` even though they cannot be removed in other control-flow branches. Variables declared outside of the respective for loop are not affected.", "introduced": "0.5.8", "fixed": "0.5.16", "severity": "low", "conditions": { "yulOptimizer": true } }, { "uid": "SOL-2019-10", "name": "ABIEncoderV2LoopYulOptimizer", "summary": "If both the experimental ABIEncoderV2 and the experimental Yul optimizer are activated, one component of the Yul optimizer may reuse data in memory that has been changed in the meantime.", "description": "The Yul optimizer incorrectly replaces ``mload`` and ``sload`` calls with values that have been previously written to the load location (and potentially changed in the meantime) if all of the following conditions are met: (1) there is a matching ``mstore`` or ``sstore`` call before; (2) the contents of memory or storage is only changed in a function that is called (directly or indirectly) in between the first store and the load call; (3) called function contains a for loop where the same memory location is changed in the condition or the post or body block. When used in Solidity mode, this can only happen if the experimental ABIEncoderV2 is activated and the experimental Yul optimizer has been activated manually in addition to the regular optimizer in the compiler settings.", "introduced": "0.5.14", "fixed": "0.5.15", "severity": "low", "conditions": { "ABIEncoderV2": true, "optimizer": true, "yulOptimizer": true } }, { "uid": "SOL-2019-9", "name": "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers", "summary": "Reading from calldata structs that contain dynamically encoded, but statically-sized members can result in incorrect values.", "description": "When a calldata struct contains a dynamically encoded, but statically-sized member, the offsets for all subsequent struct members are calculated incorrectly. All reads from such members will result in invalid values. Only calldata structs are affected, i.e. this occurs in external functions with such structs as argument. Using affected structs in storage or memory or as arguments to public functions on the other hand works correctly.", "introduced": "0.5.6", "fixed": "0.5.11", "severity": "low", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2019-8", "name": "SignedArrayStorageCopy", "summary": "Assigning an array of signed integers to a storage array of different type can lead to data corruption in that array.", "description": "In two's complement, negative integers have their higher order bits set. In order to fit into a shared storage slot, these have to be set to zero. When a conversion is done at the same time, the bits to set to zero were incorrectly determined from the source and not the target type. This means that such copy operations can lead to incorrect values being stored.", "link": "https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/", "introduced": "0.4.7", "fixed": "0.5.10", "severity": "low/medium" }, { "uid": "SOL-2019-7", "name": "ABIEncoderV2StorageArrayWithMultiSlotElement", "summary": "Storage arrays containing structs or other statically-sized arrays are not read properly when directly encoded in external function calls or in abi.encode*.", "description": "When storage arrays whose elements occupy more than a single storage slot are directly encoded in external function calls or using abi.encode*, their elements are read in an overlapping manner, i.e. the element pointer is not properly advanced between reads. This is not a problem when the storage data is first copied to a memory variable or if the storage array only contains value types or dynamically-sized arrays.", "link": "https://blog.soliditylang.org/2019/06/25/solidity-storage-array-bugs/", "introduced": "0.4.16", "fixed": "0.5.10", "severity": "low", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2019-6", "name": "DynamicConstructorArgumentsClippedABIV2", "summary": "A contract's constructor that takes structs or arrays that contain dynamically-sized arrays reverts or decodes to invalid data.", "description": "During construction of a contract, constructor parameters are copied from the code section to memory for decoding. The amount of bytes to copy was calculated incorrectly in case all parameters are statically-sized but contain dynamically-sized arrays as struct members or inner arrays. Such types are only available if ABIEncoderV2 is activated.", "introduced": "0.4.16", "fixed": "0.5.9", "severity": "very low", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2019-5", "name": "UninitializedFunctionPointerInConstructor", "summary": "Calling uninitialized internal function pointers created in the constructor does not always revert and can cause unexpected behaviour.", "description": "Uninitialized internal function pointers point to a special piece of code that causes a revert when called. Jump target positions are different during construction and after deployment, but the code for setting this special jump target only considered the situation after deployment.", "introduced": "0.5.0", "fixed": "0.5.8", "severity": "very low" }, { "uid": "SOL-2019-5", "name": "UninitializedFunctionPointerInConstructor_0.4.x", "summary": "Calling uninitialized internal function pointers created in the constructor does not always revert and can cause unexpected behaviour.", "description": "Uninitialized internal function pointers point to a special piece of code that causes a revert when called. Jump target positions are different during construction and after deployment, but the code for setting this special jump target only considered the situation after deployment.", "introduced": "0.4.5", "fixed": "0.4.26", "severity": "very low" }, { "uid": "SOL-2019-4", "name": "IncorrectEventSignatureInLibraries", "summary": "Contract types used in events in libraries cause an incorrect event signature hash", "description": "Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs.", "introduced": "0.5.0", "fixed": "0.5.8", "severity": "very low" }, { "uid": "SOL-2019-4", "name": "IncorrectEventSignatureInLibraries_0.4.x", "summary": "Contract types used in events in libraries cause an incorrect event signature hash", "description": "Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs.", "introduced": "0.3.0", "fixed": "0.4.26", "severity": "very low" }, { "uid": "SOL-2019-3", "name": "ABIEncoderV2PackedStorage", "summary": "Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2.", "description": "Elements of structs and arrays that are shorter than 32 bytes are not properly decoded from storage when encoded directly (i.e. not via a memory type) using ABIEncoderV2. This can cause corruption in the values themselves but can also overwrite other parts of the encoded data.", "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/", "introduced": "0.5.0", "fixed": "0.5.7", "severity": "low", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2019-3", "name": "ABIEncoderV2PackedStorage_0.4.x", "summary": "Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2.", "description": "Elements of structs and arrays that are shorter than 32 bytes are not properly decoded from storage when encoded directly (i.e. not via a memory type) using ABIEncoderV2. This can cause corruption in the values themselves but can also overwrite other parts of the encoded data.", "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/", "introduced": "0.4.19", "fixed": "0.4.26", "severity": "low", "conditions": { "ABIEncoderV2": true } }, { "uid": "SOL-2019-2", "name": "IncorrectByteInstructionOptimization", "summary": "The optimizer incorrectly handles byte opcodes whose second argument is 31 or a constant expression that evaluates to 31. This can result in unexpected values.", "description": "The optimizer incorrectly handles byte opcodes that use the constant 31 as second argument. This can happen when performing index access on bytesNN types with a compile-time constant value (not index) of 31 or when using the byte opcode in inline assembly.", "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/", "introduced": "0.5.5", "fixed": "0.5.7", "severity": "very low", "conditions": { "optimizer": true } }, { "uid": "SOL-2019-1", "name": "DoubleShiftSizeOverflow", "summary": "Double bitwise shifts by large constants whose sum overflows 256 bits can result in unexpected values.", "description": "Nested logical shift operations whose total shift size is 2**256 or more are incorrectly optimized. This only applies to shifts by numbers of bits that are compile-time constant expressions.", "link": "https://blog.soliditylang.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/", "introduced": "0.5.5", "fixed": "0.5.6", "severity": "low", "conditions": { "optimizer": true, "evmVersion": ">=constantinople" } }, { "uid": "SOL-2018-4", "name": "ExpExponentCleanup", "summary": "Using the ** operator with an exponent of type shorter than 256 bits can result in unexpected values.", "description": "Higher order bits in the exponent are not properly cleaned before the EXP opcode is applied if the type of the exponent expression is smaller than 256 bits and not smaller than the type of the base. In that case, the result might be larger than expected if the exponent is assumed to lie within the value range of the type. Literal numbers as exponents are unaffected as are exponents or bases of type uint256.", "link": "https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/", "fixed": "0.4.25", "severity": "medium/high", "check": {"regex-source": "[^/]\\*\\* *[^/0-9 ]"} }, { "uid": "SOL-2018-3", "name": "EventStructWrongData", "summary": "Using structs in events logged wrong data.", "description": "If a struct is used in an event, the address of the struct is logged instead of the actual data.", "link": "https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/", "introduced": "0.4.17", "fixed": "0.4.25", "severity": "very low", "check": {"ast-compact-json-path": "$..[?(@.nodeType === 'EventDefinition')]..[?(@.nodeType === 'UserDefinedTypeName' && @.typeDescriptions.typeString.startsWith('struct'))]"} }, { "uid": "SOL-2018-2", "name": "NestedArrayFunctionCallDecoder", "summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.", "description": "If Solidity code calls a function that returns a multi-dimensional fixed-size array, array elements are incorrectly interpreted as memory pointers and thus can cause memory corruption if the return values are accessed. Calling functions with multi-dimensional fixed-size arrays is unaffected as is returning fixed-size arrays from function calls. The regular expression only checks if such functions are present, not if they are called, which is required for the contract to be affected.", "link": "https://blog.soliditylang.org/2018/09/13/solidity-bugfix-release/", "introduced": "0.1.4", "fixed": "0.4.22", "severity": "medium", "check": {"regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"} }, { "uid": "SOL-2018-1", "name": "OneOfTwoConstructorsSkipped", "summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.", "description": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored. There will be a compiler warning about the old-style constructor, so contracts only using new-style constructors are fine.", "introduced": "0.4.22", "fixed": "0.4.23", "severity": "very low" }, { "uid": "SOL-2017-5", "name": "ZeroFunctionSelector", "summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.", "description": "If a function has a selector consisting only of zeros, is payable and part of a contract that does not have a fallback function and at most five external functions in total, this function is called instead of the fallback function if Ether is sent to the contract without data.", "fixed": "0.4.18", "severity": "very low" }, { "uid": "SOL-2017-4", "name": "DelegateCallReturnValue", "summary": "The low-level .delegatecall() does not return the execution outcome, but converts the value returned by the functioned called to a boolean instead.", "description": "The return value of the low-level .delegatecall() function is taken from a position in memory, where the call data or the return data resides. This value is interpreted as a boolean and put onto the stack. This means if the called function returns at least 32 zero bytes, .delegatecall() returns false even if the call was successful.", "introduced": "0.3.0", "fixed": "0.4.15", "severity": "low" }, { "uid": "SOL-2017-3", "name": "ECRecoverMalformedInput", "summary": "The ecrecover() builtin can return garbage for malformed input.", "description": "The ecrecover precompile does not properly signal failure for malformed input (especially in the 'v' argument) and thus the Solidity function can return data that was previously present in the return area in memory.", "fixed": "0.4.14", "severity": "medium" }, { "uid": "SOL-2017-2", "name": "SkipEmptyStringLiteral", "summary": "If \"\" is used in a function call, the following function arguments will not be correctly passed to the function.", "description": "If the empty string literal \"\" is used as an argument in a function call, it is skipped by the encoder. This has the effect that the encoding of all arguments following this is shifted left by 32 bytes and thus the function call data is corrupted.", "fixed": "0.4.12", "severity": "low" }, { "uid": "SOL-2017-1", "name": "ConstantOptimizerSubtraction", "summary": "In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers.", "description": "The optimizer tries to represent any number in the bytecode by routines that compute them with less gas. For some special numbers, an incorrect routine is generated. This could allow an attacker to e.g. trick victims about a specific amount of ether, or function calls to call different functions (or none at all).", "link": "https://blog.soliditylang.org/2017/05/03/solidity-optimizer-bug/", "fixed": "0.4.11", "severity": "low", "conditions": { "optimizer": true } }, { "uid": "SOL-2016-11", "name": "IdentityPrecompileReturnIgnored", "summary": "Failure of the identity precompile was ignored.", "description": "Calls to the identity contract, which is used for copying memory, ignored its return value. On the public chain, calls to the identity precompile can be made in a way that they never fail, but this might be different on private chains.", "severity": "low", "fixed": "0.4.7" }, { "uid": "SOL-2016-10", "name": "OptimizerStateKnowledgeNotResetForJumpdest", "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.", "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was simplified to just use the empty state, but this implementation was not done properly. This bug can cause data corruption.", "severity": "medium", "introduced": "0.4.5", "fixed": "0.4.6", "conditions": { "optimizer": true } }, { "uid": "SOL-2016-9", "name": "HighOrderByteCleanStorage", "summary": "For short types, the high order bytes were not cleaned properly and could overwrite existing data.", "description": "Types shorter than 32 bytes are packed together into the same 32 byte storage slot, but storage writes always write 32 bytes. For some types, the higher order bytes were not cleaned properly, which made it sometimes possible to overwrite a variable in storage when writing to another one.", "link": "https://blog.soliditylang.org/2016/11/01/security-alert-solidity-variables-can-overwritten-storage/", "severity": "high", "introduced": "0.1.6", "fixed": "0.4.4" }, { "uid": "SOL-2016-8", "name": "OptimizerStaleKnowledgeAboutSHA3", "summary": "The optimizer did not properly reset its knowledge about SHA3 operations resulting in some hashes (also used for storage variable positions) not being calculated correctly.", "description": "The optimizer performs symbolic execution in order to save re-evaluating expressions whose value is already known. This knowledge was not properly reset across control flow paths and thus the optimizer sometimes thought that the result of a SHA3 operation is already present on the stack. This could result in data corruption by accessing the wrong storage slot.", "severity": "medium", "fixed": "0.4.3", "conditions": { "optimizer": true } }, { "uid": "SOL-2016-7", "name": "LibrariesNotCallableFromPayableFunctions", "summary": "Library functions threw an exception when called from a call that received Ether.", "description": "Library functions are protected against sending them Ether through a call. Since the DELEGATECALL opcode forwards the information about how much Ether was sent with a call, the library function incorrectly assumed that Ether was sent to the library and threw an exception.", "severity": "low", "introduced": "0.4.0", "fixed": "0.4.2" }, { "uid": "SOL-2016-6", "name": "SendFailsForZeroEther", "summary": "The send function did not provide enough gas to the recipient if no Ether was sent with it.", "description": "The recipient of an Ether transfer automatically receives a certain amount of gas from the EVM to handle the transfer. In the case of a zero-transfer, this gas is not provided which causes the recipient to throw an exception.", "severity": "low", "fixed": "0.4.0" }, { "uid": "SOL-2016-5", "name": "DynamicAllocationInfiniteLoop", "summary": "Dynamic allocation of an empty memory array caused an infinite loop and thus an exception.", "description": "Memory arrays can be created provided a length. If this length is zero, code was generated that did not terminate and thus consumed all gas.", "severity": "low", "fixed": "0.3.6" }, { "uid": "SOL-2016-4", "name": "OptimizerClearStateOnCodePathJoin", "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.", "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was not done correctly. This bug can cause data corruption, but it is probably quite hard to use for targeted attacks.", "severity": "low", "fixed": "0.3.6", "conditions": { "optimizer": true } }, { "uid": "SOL-2016-3", "name": "CleanBytesHigherOrderBits", "summary": "The higher order bits of short bytesNN types were not cleaned before comparison.", "description": "Two variables of type bytesNN were considered different if their higher order bits, which are not part of the actual value, were different. An attacker might use this to reach seemingly unreachable code paths by providing incorrectly formatted input data.", "severity": "medium/high", "fixed": "0.3.3" }, { "uid": "SOL-2016-2", "name": "ArrayAccessCleanHigherOrderBits", "summary": "Access to array elements for arrays of types with less than 32 bytes did not correctly clean the higher order bits, causing corruption in other array elements.", "description": "Multiple elements of an array of values that are shorter than 17 bytes are packed into the same storage slot. Writing to a single element of such an array did not properly clean the higher order bytes and thus could lead to data corruption.", "severity": "medium/high", "fixed": "0.3.1" }, { "uid": "SOL-2016-1", "name": "AncientCompiler", "summary": "This compiler version is ancient and might contain several undocumented or undiscovered bugs.", "description": "The list of bugs is only kept for compiler versions starting from 0.3.0, so older versions might contain undocumented bugs.", "severity": "high", "fixed": "0.3.0" } ] ================================================ FILE: docs/bugs.rst ================================================ .. index:: Bugs .. _known_bugs: ################## List of Known Bugs ################## Below, you can find a JSON-formatted list of some of the known security-relevant bugs in the Solidity compiler. The file itself is hosted in the `GitHub repository `_. The list stretches back as far as version 0.3.0, bugs known to be present only in versions preceding that are not listed. There is another file called `bugs_by_version.json `_, which can be used to check which bugs affect a specific version of the compiler. Contract source verification tools and also other tools interacting with contracts should consult this list according to the following criteria: - It is mildly suspicious if a contract was compiled with a nightly compiler version instead of a released version. This list does not keep track of unreleased or nightly versions. - It is also mildly suspicious if a contract was compiled with a version that was not the most recent at the time the contract was created. For contracts created from other contracts, you have to follow the creation chain back to a transaction and use the date of that transaction as creation date. - It is highly suspicious if a contract was compiled with a compiler that contains a known bug and the contract was created at a time where a newer compiler version containing a fix was already released. The JSON file of known bugs below is an array of objects, one for each bug, with the following keys: uid Unique identifier given to the bug in the form of ``SOL--``. It is possible that multiple entries exists with the same uid. This means multiple version ranges are affected by the same bug. name Unique name given to the bug summary Short description of the bug description Detailed description of the bug link URL of a website with more detailed information, optional introduced The first published compiler version that contained the bug, optional fixed The first published compiler version that did not contain the bug anymore publish The date at which the bug became known publicly, optional severity Severity of the bug: very low, low, medium, high. Takes into account discoverability in contract tests, likelihood of occurrence and potential damage by exploits. conditions Conditions that have to be met to trigger the bug. The following keys can be used: ``optimizer``, Boolean value which means that the optimizer has to be switched on to enable the bug. ``evmVersion``, a string that indicates which EVM version compiler settings trigger the bug. The string can contain comparison operators. For example, ``">=constantinople"`` means that the bug is present when the EVM version is set to ``constantinople`` or later. If no conditions are given, assume that the bug is present. check This field contains different checks that report whether the smart contract contains the bug or not. The first type of check are JavaScript regular expressions that are to be matched against the source code ("source-regex") if the bug is present. If there is no match, then the bug is very likely not present. If there is a match, the bug might be present. For improved accuracy, the checks should be applied to the source code after stripping comments. The second type of check are patterns to be checked on the compact AST of the Solidity program ("ast-compact-json-path"). The specified search query is a `JsonPath `_ expression. If at least one path of the Solidity AST matches the query, the bug is likely present. .. literalinclude:: bugs.json :language: js ================================================ FILE: docs/bugs_by_version.json ================================================ { "0.1.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-07-10" }, "0.1.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-08-04" }, "0.1.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-08-20" }, "0.1.3": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ExpExponentCleanup", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-09-25" }, "0.1.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-09-30" }, "0.1.5": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-10-07" }, "0.1.6": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-10-16" }, "0.1.7": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-11-17" }, "0.2.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2015-12-02" }, "0.2.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2016-01-30" }, "0.2.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits", "AncientCompiler" ], "released": "2016-02-17" }, "0.3.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits", "ArrayAccessCleanHigherOrderBits" ], "released": "2016-03-11" }, "0.3.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits" ], "released": "2016-03-31" }, "0.3.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin", "CleanBytesHigherOrderBits" ], "released": "2016-04-18" }, "0.3.3": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" ], "released": "2016-05-27" }, "0.3.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" ], "released": "2016-05-31" }, "0.3.5": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther", "DynamicAllocationInfiniteLoop", "OptimizerClearStateOnCodePathJoin" ], "released": "2016-06-10" }, "0.3.6": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "SendFailsForZeroEther" ], "released": "2016-08-10" }, "0.4.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "LibrariesNotCallableFromPayableFunctions" ], "released": "2016-09-08" }, "0.4.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3", "LibrariesNotCallableFromPayableFunctions" ], "released": "2016-09-09" }, "0.4.10": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2017-03-15" }, "0.4.11": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral" ], "released": "2017-05-03" }, "0.4.12": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" ], "released": "2017-07-03" }, "0.4.13": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" ], "released": "2017-07-06" }, "0.4.14": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue" ], "released": "2017-07-31" }, "0.4.15": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-08-08" }, "0.4.16": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-08-24" }, "0.4.17": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "EventStructWrongData", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-09-21" }, "0.4.18": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "EventStructWrongData", "NestedArrayFunctionCallDecoder" ], "released": "2017-10-18" }, "0.4.19": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ABIEncoderV2PackedStorage_0.4.x", "ExpExponentCleanup", "EventStructWrongData", "NestedArrayFunctionCallDecoder" ], "released": "2017-11-30" }, "0.4.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", "OptimizerStaleKnowledgeAboutSHA3" ], "released": "2016-09-17" }, "0.4.20": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ABIEncoderV2PackedStorage_0.4.x", "ExpExponentCleanup", "EventStructWrongData", "NestedArrayFunctionCallDecoder" ], "released": "2018-02-14" }, "0.4.21": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ABIEncoderV2PackedStorage_0.4.x", "ExpExponentCleanup", "EventStructWrongData", "NestedArrayFunctionCallDecoder" ], "released": "2018-03-07" }, "0.4.22": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ABIEncoderV2PackedStorage_0.4.x", "ExpExponentCleanup", "EventStructWrongData", "OneOfTwoConstructorsSkipped" ], "released": "2018-04-16" }, "0.4.23": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ABIEncoderV2PackedStorage_0.4.x", "ExpExponentCleanup", "EventStructWrongData" ], "released": "2018-04-19" }, "0.4.24": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ABIEncoderV2PackedStorage_0.4.x", "ExpExponentCleanup", "EventStructWrongData" ], "released": "2018-05-16" }, "0.4.25": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ABIEncoderV2PackedStorage_0.4.x" ], "released": "2018-09-12" }, "0.4.26": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2" ], "released": "2019-04-29" }, "0.4.3": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage" ], "released": "2016-10-25" }, "0.4.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" ], "released": "2016-10-31" }, "0.4.5": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStateKnowledgeNotResetForJumpdest" ], "released": "2016-11-21" }, "0.4.6": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" ], "released": "2016-11-22" }, "0.4.7": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2016-12-15" }, "0.4.8": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2017-01-13" }, "0.4.9": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "UninitializedFunctionPointerInConstructor_0.4.x", "IncorrectEventSignatureInLibraries_0.4.x", "ExpExponentCleanup", "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2017-01-31" }, "0.5.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries", "ABIEncoderV2PackedStorage" ], "released": "2018-11-13" }, "0.5.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries", "ABIEncoderV2PackedStorage" ], "released": "2018-12-03" }, "0.5.10": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5", "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers" ], "released": "2019-06-25" }, "0.5.11": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5" ], "released": "2019-08-12" }, "0.5.12": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5" ], "released": "2019-10-01" }, "0.5.13": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5" ], "released": "2019-11-14" }, "0.5.14": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5", "ABIEncoderV2LoopYulOptimizer" ], "released": "2019-12-09" }, "0.5.15": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5" ], "released": "2019-12-17" }, "0.5.16": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden" ], "released": "2020-01-02" }, "0.5.17": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow" ], "released": "2020-03-17" }, "0.5.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries", "ABIEncoderV2PackedStorage" ], "released": "2018-12-19" }, "0.5.3": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries", "ABIEncoderV2PackedStorage" ], "released": "2019-01-22" }, "0.5.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries", "ABIEncoderV2PackedStorage" ], "released": "2019-02-12" }, "0.5.5": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries", "ABIEncoderV2PackedStorage", "IncorrectByteInstructionOptimization", "DoubleShiftSizeOverflow" ], "released": "2019-03-05" }, "0.5.6": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries", "ABIEncoderV2PackedStorage", "IncorrectByteInstructionOptimization" ], "released": "2019-03-13" }, "0.5.7": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2", "UninitializedFunctionPointerInConstructor", "IncorrectEventSignatureInLibraries" ], "released": "2019-03-26" }, "0.5.8": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5", "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement", "DynamicConstructorArgumentsClippedABIV2" ], "released": "2019-04-30" }, "0.5.9": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "privateCanBeOverridden", "YulOptimizerRedundantAssignmentBreakContinue0.5", "ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers", "SignedArrayStorageCopy", "ABIEncoderV2StorageArrayWithMultiSlotElement" ], "released": "2019-05-28" }, "0.6.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow", "YulOptimizerRedundantAssignmentBreakContinue" ], "released": "2019-12-17" }, "0.6.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow" ], "released": "2020-01-02" }, "0.6.10": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup" ], "released": "2020-06-11" }, "0.6.11": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup" ], "released": "2020-07-07" }, "0.6.12": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup" ], "released": "2020-07-22" }, "0.6.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow" ], "released": "2020-01-27" }, "0.6.3": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow" ], "released": "2020-02-18" }, "0.6.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents", "MemoryArrayCreationOverflow" ], "released": "2020-03-10" }, "0.6.5": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck", "TupleAssignmentMultiStackSlotComponents" ], "released": "2020-04-06" }, "0.6.6": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck" ], "released": "2020-04-09" }, "0.6.7": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "MissingEscapingInFormatting", "ArraySliceDynamicallyEncodedBaseType", "ImplicitConstructorCallvalueCheck" ], "released": "2020-05-04" }, "0.6.8": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup" ], "released": "2020-05-14" }, "0.6.9": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "UsingForCalldata" ], "released": "2020-06-04" }, "0.7.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup" ], "released": "2020-07-28" }, "0.7.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup", "FreeFunctionRedefinition" ], "released": "2020-09-02" }, "0.7.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy", "DynamicArrayCleanup" ], "released": "2020-09-28" }, "0.7.3": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", "EmptyByteArrayCopy" ], "released": "2020-10-07" }, "0.7.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching" ], "released": "2020-10-19" }, "0.7.5": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching" ], "released": "2020-11-18" }, "0.7.6": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching" ], "released": "2020-12-16" }, "0.8.0": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching" ], "released": "2020-12-16" }, "0.8.1": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching" ], "released": "2021-01-27" }, "0.8.10": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation" ], "released": "2021-11-09" }, "0.8.11": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "AbiEncodeCallLiteralAsFixedBytesBug" ], "released": "2021-12-20" }, "0.8.12": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "AbiEncodeCallLiteralAsFixedBytesBug" ], "released": "2022-02-16" }, "0.8.13": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "StorageWriteRemovalBeforeConditionalTermination", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "InlineAssemblyMemorySideEffects", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation" ], "released": "2022-03-16" }, "0.8.14": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "StorageWriteRemovalBeforeConditionalTermination", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "InlineAssemblyMemorySideEffects" ], "released": "2022-05-17" }, "0.8.15": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "StorageWriteRemovalBeforeConditionalTermination", "AbiReencodingHeadOverflowWithStaticArrayCleanup" ], "released": "2022-06-15" }, "0.8.16": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "StorageWriteRemovalBeforeConditionalTermination" ], "released": "2022-08-08" }, "0.8.17": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" ], "released": "2022-09-08" }, "0.8.18": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" ], "released": "2023-02-01" }, "0.8.19": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" ], "released": "2023-02-22" }, "0.8.2": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching" ], "released": "2021-03-02" }, "0.8.20": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" ], "released": "2023-05-10" }, "0.8.21": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication" ], "released": "2023-07-19" }, "0.8.22": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication" ], "released": "2023-10-25" }, "0.8.23": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow" ], "released": "2023-11-08" }, "0.8.24": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow" ], "released": "2024-01-25" }, "0.8.25": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow" ], "released": "2024-03-14" }, "0.8.26": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow" ], "released": "2024-05-21" }, "0.8.27": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow" ], "released": "2024-09-04" }, "0.8.28": { "bugs": [ "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2024-10-09" }, "0.8.29": { "bugs": [ "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2025-03-12" }, "0.8.3": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables", "ABIDecodeTwoDimensionalArrayMemory" ], "released": "2021-03-23" }, "0.8.30": { "bugs": [ "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2025-05-07" }, "0.8.31": { "bugs": [ "TransientStorageClearingHelperCollision", "LostStorageArrayWriteOnSlotOverflow" ], "released": "2025-12-03" }, "0.8.32": { "bugs": [ "TransientStorageClearingHelperCollision" ], "released": "2025-12-18" }, "0.8.33": { "bugs": [ "TransientStorageClearingHelperCollision" ], "released": "2025-12-18" }, "0.8.34": { "bugs": [], "released": "2026-02-18" }, "0.8.4": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables" ], "released": "2021-04-21" }, "0.8.5": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables" ], "released": "2021-06-10" }, "0.8.6": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables" ], "released": "2021-06-22" }, "0.8.7": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "SignedImmutables" ], "released": "2021-08-11" }, "0.8.8": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation", "UserDefinedValueTypesBug", "SignedImmutables" ], "released": "2021-09-27" }, "0.8.9": { "bugs": [ "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "DataLocationChangeInInternalOverride", "NestedCalldataArrayAbiReencodingSizeValidation" ], "released": "2021-09-29" } } ================================================ FILE: docs/cheatsheet.rst ================================================ ********** Cheatsheet ********** .. index:: operator;precedence Order of Precedence of Operators ================================ .. include:: types/operator-precedence-table.rst .. index:: abi;decode, abi;encode, abi;encodePacked, abi;encodeWithSelector, abi;encodeCall, abi;encodeWithSignature ABI Encoding and Decoding Functions =================================== - ``abi.decode(bytes memory encodedData, (...)) returns (...)``: :ref:`ABI `-decodes the provided data. The types are given in parentheses as second argument. Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))`` - ``abi.encode(...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments - ``abi.encodePacked(...) returns (bytes memory)``: Performs :ref:`packed encoding ` of the given arguments. Note that this encoding can be ambiguous! - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments starting from the second and prepends the given four-byte selector - ``abi.encodeCall(function functionPointer, (...)) returns (bytes memory)``: ABI-encodes a call to ``functionPointer`` with the arguments found in the tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, ...)`` - ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`` .. index:: bytes;concat, string;concat Members of ``bytes`` and ``string`` ==================================== - ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of arguments to one byte array` - ``string.concat(...) returns (string memory)``: :ref:`Concatenates variable number of arguments to one string array` .. index:: address;balance, address;codehash, address;send, address;code, address;transfer Members of ``address`` ====================== - ``
.balance`` (``uint256``): balance of the :ref:`address` in Wei - ``
.code`` (``bytes memory``): code at the :ref:`address` (can be empty) - ``
.codehash`` (``bytes32``): the codehash of the :ref:`address` - ``
.call(bytes memory) returns (bool, bytes memory)``: issue low-level ``CALL`` with the given payload, returns success condition and return data - ``
.delegatecall(bytes memory) returns (bool, bytes memory)``: issue low-level ``DELEGATECALL`` with the given payload, returns success condition and return data - ``
.staticcall(bytes memory) returns (bool, bytes memory)``: issue low-level ``STATICCALL`` with the given payload, returns success condition and return data - ``
.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure (deprecated) - ``
.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure (deprecated) .. index:: blockhash, blobhash, block, block;basefee, block;blobbasefee, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;timestamp .. index:: gasleft, msg;data, msg;sender, msg;sig, msg;value, tx;gasprice, tx;origin Block and Transaction Properties ================================ - ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks - ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction. A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes of the SHA256 hash of the KZG commitment (`EIP-4844 `_). Returns zero if no blob with the given index exists. - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) - ``block.chainid`` (``uint``): current chain id - ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` that will be removed in the next breaking release - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number - ``block.prevrandao`` (``uint``): random number provided by the beacon chain (``EVM >= Paris``) (see `EIP-4399 `_ ) - ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch - ``gasleft() returns (uint256)``: remaining gas - ``msg.data`` (``bytes``): complete calldata - ``msg.sender`` (``address``): sender of the message (current call) - ``msg.sig`` (``bytes4``): first four bytes of the calldata (i.e. function identifier) - ``msg.value`` (``uint``): number of wei sent with the message - ``tx.gasprice`` (``uint``): gas price of the transaction - ``tx.origin`` (``address``): sender of the transaction (full call chain) .. index:: assert, require, revert Validations and Assertions ========================== - ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error) - ``require(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component) - ``require(bool condition, string memory message)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component). Also provide error message. - ``revert()``: abort execution and revert state changes - ``revert(string memory message)``: abort execution and revert state changes providing an explanatory string .. index:: cryptography, keccak256, sha256, ripemd160, ecrecover, addmod, mulmod, erc7201 Mathematical and Cryptographic Functions ======================================== - ``keccak256(bytes memory) returns (bytes32)``: compute the Keccak-256 hash of the input - ``sha256(bytes memory) returns (bytes32)``: compute the SHA-256 hash of the input - ``ripemd160(bytes memory) returns (bytes20)``: compute the RIPEMD-160 hash of the input - ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error - ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. - ``erc7201(string memory id) returns (uint)``: compute the base slot of an ``erc7201`` storage namespace. Can be used in compile time context. .. index:: this, super, selfdestruct Contract-related ================ - ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` or ``address payable`` - ``super``: a contract one level higher in the inheritance hierarchy - ``selfdestruct(address payable recipient)``: send all funds to the given address and (only on EVMs before Cancun or when invoked within the transaction creating the contract) destroy the contract. .. index:: type;name, type;creationCode, type;runtimeCode, type;interfaceId, type;min, type;max Type Information ================ - ``type(C).name`` (``string``): the name of the contract - ``type(C).creationCode`` (``bytes memory``): creation bytecode of the given contract, see :ref:`Type Information`. - ``type(C).runtimeCode`` (``bytes memory``): runtime bytecode of the given contract, see :ref:`Type Information`. - ``type(I).interfaceId`` (``bytes4``): value containing the EIP-165 interface identifier of the given interface, see :ref:`Type Information`. - ``type(T).min`` (``T``): the minimum value representable by the integer type ``T``, see :ref:`Type Information`. - ``type(T).max`` (``T``): the maximum value representable by the integer type ``T``, see :ref:`Type Information`. .. index:: visibility, public, private, external, internal Function Visibility Specifiers ============================== .. code-block:: solidity :force: function myFunction() returns (bool) { return true; } - ``public``: visible externally and internally (creates a :ref:`getter function` for storage/state variables) - ``private``: only visible in the current contract - ``external``: only visible externally (only for functions) - i.e. can only be message-called (via ``this.func``) - ``internal``: only visible internally .. index:: modifiers, pure, view, payable, constant, anonymous, indexed Modifiers ========= - ``pure`` for functions: Disallows modification or access of state. - ``view`` for functions: Disallows modification of state. - ``payable`` for functions: Allows them to receive Ether together with a call. - ``constant`` for state variables: Disallows assignment (except initialization), does not occupy storage slot. - ``immutable`` for state variables: Allows assignment at construction time and is constant when deployed. Is stored in code. - ``anonymous`` for events: Does not store event signature as topic. - ``indexed`` for event parameters: Stores the parameter as topic. - ``virtual`` for functions and modifiers: Allows the function's or modifier's behavior to be changed in derived contracts. - ``override``: States that this function, modifier or public state variable changes the behavior of a function or modifier in a base contract. ================================================ FILE: docs/common-patterns.rst ================================================ ############### Common Patterns ############### .. index:: withdrawal .. _withdrawal_pattern: ************************* Withdrawal from Contracts ************************* The recommended method of sending funds after an effect is using the withdrawal pattern. Although the most intuitive method of sending Ether, as a result of an effect, is a direct ``transfer`` call, this is not recommended as it introduces a potential security risk. You may read more about this on the :ref:`security_considerations` page. The following is an example of the withdrawal pattern in practice in a contract where the goal is to send the most of some compensation, e.g. Ether, to the contract in order to become the "richest", inspired by `King of the Ether `_. In the following contract, if you are no longer the richest, you receive the funds of the person who is now the richest. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract WithdrawalContract { address public richest; uint public mostSent; mapping(address => uint) pendingWithdrawals; /// The amount of Ether sent was not higher than /// the currently highest amount. error NotEnoughEther(); constructor() payable { richest = msg.sender; mostSent = msg.value; } function becomeRichest() public payable { if (msg.value <= mostSent) revert NotEnoughEther(); pendingWithdrawals[richest] += msg.value; richest = msg.sender; mostSent = msg.value; } function withdraw() public { uint amount = pendingWithdrawals[msg.sender]; // Remember to zero the pending refund before // sending to prevent reentrancy attacks pendingWithdrawals[msg.sender] = 0; (bool success, ) = payable(msg.sender).call{value: amount}(""); require(success); } } This is as opposed to the more intuitive sending pattern: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract SendContract { address payable public richest; uint public mostSent; /// The amount of Ether sent was not higher than /// the currently highest amount. error NotEnoughEther(); constructor() payable { richest = payable(msg.sender); mostSent = msg.value; } function becomeRichest() public payable { if (msg.value <= mostSent) revert NotEnoughEther(); // This line can cause problems (explained below). (bool success, ) = richest.call{value: msg.value}(""); require(success); richest = payable(msg.sender); mostSent = msg.value; } } Notice that, in this example, an attacker could trap the contract into an unusable state by causing ``richest`` to be the address of a contract that has a receive or fallback function which fails (e.g. by using ``revert()`` or by just consuming more than the 2300 gas stipend transferred to them). That way, whenever ``transfer`` is called to deliver funds to the "poisoned" contract, it will fail and thus also ``becomeRichest`` will fail, with the contract being stuck forever. In contrast, if you use the "withdraw" pattern from the first example, the attacker can only cause his or her own withdraw to fail and not the rest of the contract's workings. .. index:: access;restricting ****************** Restricting Access ****************** Restricting access is a common pattern for contracts. Note that you can never restrict any human or computer from reading the content of your transactions or your contract's state. You can make it a bit harder by using encryption, but if your contract is supposed to read the data, so will everyone else. You can restrict read access to your contract's state by **other contracts**. That is actually the default unless you declare your state variables ``public``. Furthermore, you can restrict who can make modifications to your contract's state or call your contract's functions and this is what this section is about. .. index:: function;modifier The use of **function modifiers** makes these restrictions highly readable. .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract AccessRestriction { // These will be assigned at the construction // phase, where `msg.sender` is the account // creating this contract. address public owner = msg.sender; uint public creationTime = block.timestamp; // Now follows a list of errors that // this contract can generate together // with a textual explanation in special // comments. /// Sender not authorized for this /// operation. error Unauthorized(); /// Function called too early. error TooEarly(); /// Not enough Ether sent with function call. error NotEnoughEther(); // Modifiers can be used to change // the body of a function. // If this modifier is used, it will // prepend a check that only passes // if the function is called from // a certain address. modifier onlyBy(address account) { if (msg.sender != account) revert Unauthorized(); // Do not forget the "_;"! It will // be replaced by the actual function // body when the modifier is used. _; } /// Make `newOwner` the new owner of this /// contract. function changeOwner(address newOwner) public onlyBy(owner) { owner = newOwner; } modifier onlyAfter(uint time) { if (block.timestamp < time) revert TooEarly(); _; } /// Erase ownership information. /// May only be called 6 weeks after /// the contract has been created. function disown() public onlyBy(owner) onlyAfter(creationTime + 6 weeks) { delete owner; } // This modifier requires a certain // fee being associated with a function call. // If the caller sent too much, he or she is // refunded, but only after the function body. // This was dangerous before Solidity version 0.4.0, // where it was possible to skip the part after `_;`. modifier costs(uint amount) { if (msg.value < amount) revert NotEnoughEther(); _; if (msg.value > amount) { (bool success, ) = payable(msg.sender).call{value: msg.value - amount}(""); require(success); } } function forceOwnerChange(address newOwner) public payable costs(200 ether) { owner = newOwner; // just some example condition if (uint160(owner) & 0 == 1) // This did not refund for Solidity // before version 0.4.0. return; // refund overpaid fees } } A more specialised way in which access to function calls can be restricted will be discussed in the next example. .. index:: state machine ************* State Machine ************* Contracts often act as a state machine, which means that they have certain **stages** in which they behave differently or in which different functions can be called. A function call often ends a stage and transitions the contract into the next stage (especially if the contract models **interaction**). It is also common that some stages are automatically reached at a certain point in **time**. An example for this is a blind auction contract which starts in the stage "accepting blinded bids", then transitions to "revealing bids" which is ended by "determine auction outcome". .. index:: function;modifier Function modifiers can be used in this situation to model the states and guard against incorrect usage of the contract. Example ======= In the following example, the modifier ``atStage`` ensures that the function can only be called at a certain stage. Automatic timed transitions are handled by the modifier ``timedTransitions``, which should be used for all functions. .. note:: **Modifier Order Matters**. If atStage is combined with timedTransitions, make sure that you mention it after the latter, so that the new stage is taken into account. Finally, the modifier ``transitionNext`` can be used to automatically go to the next stage when the function finishes. .. note:: **Modifier May be Skipped**. This only applies to Solidity before version 0.4.0: Since modifiers are applied by simply replacing code and not by using a function call, the code in the transitionNext modifier can be skipped if the function itself uses return. If you want to do that, make sure to call nextStage manually from those functions. Starting with version 0.4.0, modifier code will run even if the function explicitly returns. .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract StateMachine { enum Stages { AcceptingBlindedBids, RevealBids, AnotherStage, AreWeDoneYet, Finished } /// Function cannot be called at this time. error FunctionInvalidAtThisStage(); // This is the current stage. Stages public stage = Stages.AcceptingBlindedBids; uint public creationTime = block.timestamp; modifier atStage(Stages stage_) { if (stage != stage_) revert FunctionInvalidAtThisStage(); _; } function nextStage() internal { stage = Stages(uint(stage) + 1); } // Perform timed transitions. Be sure to mention // this modifier first, otherwise the guards // will not take the new stage into account. modifier timedTransitions() { if (stage == Stages.AcceptingBlindedBids && block.timestamp >= creationTime + 10 days) nextStage(); if (stage == Stages.RevealBids && block.timestamp >= creationTime + 12 days) nextStage(); // The other stages transition by transaction _; } // Order of the modifiers matters here! function bid() public payable timedTransitions atStage(Stages.AcceptingBlindedBids) { // We will not implement that here } function reveal() public timedTransitions atStage(Stages.RevealBids) { } // This modifier goes to the next stage // after the function is done. modifier transitionNext() { _; nextStage(); } function g() public timedTransitions atStage(Stages.AnotherStage) transitionNext { } function h() public timedTransitions atStage(Stages.AreWeDoneYet) transitionNext { } function i() public timedTransitions atStage(Stages.Finished) { } } ================================================ FILE: docs/conf.py ================================================ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Solidity documentation build configuration file, created by # sphinx-quickstart on Mon Dec 7 12:32:57 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os import re from pygments_lexer_solidity import SolidityLexer, YulLexer # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. ROOT_PATH = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(ROOT_PATH, 'ext')) def setup(sphinx): sphinx.add_lexer('Solidity', SolidityLexer) sphinx.add_lexer('Yul', YulLexer) sphinx.add_css_file('css/fonts.css') sphinx.add_css_file('css/custom.css') sphinx.add_css_file('css/custom-dark.css') sphinx.add_css_file('css/pygments.css') # -- RTD GitHub configuration --------------------------------------------- # Taken from: # https://github.com/readthedocs/readthedocs.org/blob/e366e7fc8649fbcf1b6d06ecc12c5f7766144c46/readthedocs/projects/constants.py#L350 GITHUB_REGEXS = [ re.compile(r"github.com/(.+)/(.+)(?:\.git){1}$"), # This must come before the one without a / to make sure we don't capture the / re.compile(r"github.com/(.+)/(.+)/"), re.compile(r"github.com/(.+)/(.+)"), re.compile(r"github.com:(.+)/(.+)\.git$"), ] # Taken and adapted from: # https://github.com/readthedocs/readthedocs.org/blob/e366e7fc8649fbcf1b6d06ecc12c5f7766144c46/readthedocs/builds/utils.py#L24 def get_github_username_repo(url): if "github" in url: for regex in GITHUB_REGEXS: match = regex.search(url) if match: return match.groups() return (None, None) display_github = False # NOTE: RTD_DISPLAY_GITHUB, RTD_GITHUB_USER and RTD_GITHUB_REPO are set in the RTD project settings github_user = os.getenv("RTD_GITHUB_USER") github_repo = os.getenv("RTD_GITHUB_REPO") if github_user and github_repo: display_github = True else: git_clone_url = os.getenv("READTHEDOCS_GIT_CLONE_URL") if git_clone_url: github_user, github_repo = get_github_username_repo(git_clone_url) if github_user and github_repo: display_github = True display_github_env = os.getenv("RTD_DISPLAY_GITHUB") if display_github_env: display_github = display_github_env.lower() == "true" html_context = { "display_github": display_github, "github_user": github_user, "github_repo": github_repo, "github_version": os.getenv("READTHEDOCS_VERSION", "develop"), "conf_py_path": "/docs/", } # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx_syntax', 'html_extra_template_renderer', 'remix_code_links', 'sphinx.ext.imgconverter', ] syntax_base_path = 'grammar' # generate link anchors compatible with Sphinx-A4Doc’s naming syntax_a4doc_compat_links = True # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = 'Solidity' project_copyright = '2016-2025, The Solidity Authors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. with open('../CMakeLists.txt', 'r', encoding='utf8') as f: version = re.search('PROJECT_VERSION "([^"]+)"', f.read()).group(1) # The full version, including alpha/beta/rc tags. if os.path.isfile('../prerelease.txt') and os.path.getsize('../prerelease.txt') == 0: release = version elif os.path.isfile('../prerelease.txt'): with open('../prerelease.txt', 'r', encoding='utf8') as prerelease_file: release = version + '-' + prerelease_file.read() else: release = version + '-develop' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build', 'contracts', 'types', 'examples', 'grammar'] # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' highlight_language = 'Solidity' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False suppress_warnings = [ # Suppress sphinx-syntax warnings, in particular `diagram descriptions can't have custom resolver_data` 'sphinx_syntax', ] # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { 'logo_only': True, 'version_selector': True, 'language_selector': True, } # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = "logo.svg" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. html_favicon = "_static/img/favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] html_css_files = ["css/toggle.css"] html_js_files = ["js/constants.js", "js/initialize.js", "js/toggle.js"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. html_extra_path = ["_static/css"] # List of templates of static files to be included in the HTML output. # Keys represent paths to input files and values are dicts containing: # - target: The path where the rendered template should be placed. # - context: A dictionary listing variables that can be used inside the template. # All paths must be absolute. # Rendered templates are automatically added to html_extra_path setting. html_extra_templates = { os.path.join(ROOT_PATH, "robots.txt.template"): { 'target': os.path.join(ROOT_PATH, "_static/robots.txt"), 'context': {'LATEST_VERSION': version}, } } # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. html_show_sphinx = False # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Soliditydoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'solidity.tex', 'Solidity Documentation', 'Ethereum', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False ================================================ FILE: docs/contracts/abstract-contracts.rst ================================================ .. index:: ! contract;abstract, ! abstract contract .. _abstract-contract: ****************** Abstract Contracts ****************** Contracts must be marked as abstract when at least one of their functions is not implemented or when they do not provide arguments for all of their base contract constructors. Even if this is not the case, a contract may still be marked abstract, such as when you do not intend for the contract to be created directly. Abstract contracts are similar to :ref:`interfaces` but an interface is more limited in what it can declare. An abstract contract is declared using the ``abstract`` keyword as shown in the following example. Note that this contract needs to be defined as abstract, because the function ``utterance()`` is declared, but no implementation was provided (no implementation body ``{ }`` was given). .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; abstract contract Feline { function utterance() public virtual returns (bytes32); } Such abstract contracts can not be instantiated directly. This is also true, if an abstract contract itself does implement all defined functions. The usage of an abstract contract as a base class is shown in the following example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; abstract contract Feline { function utterance() public pure virtual returns (bytes32); } contract Cat is Feline { function utterance() public pure override returns (bytes32) { return "miaow"; } } If a contract inherits from an abstract contract and does not implement all non-implemented functions by overriding, it needs to be marked as abstract as well. Note that a function without implementation is different from a :ref:`Function Type ` even though their syntax looks very similar. Example of function without implementation (a function declaration): .. code-block:: solidity function foo(address) external returns (address); Example of a declaration of a variable whose type is a function type: .. code-block:: solidity function(address) external returns (address) foo; Abstract contracts decouple the definition of a contract from its implementation providing better extensibility and self-documentation and facilitating patterns like the `Template method `_ and removing code duplication. Abstract contracts are useful in the same way that defining methods in an interface is useful. It is a way for the designer of the abstract contract to say "any child of mine must implement this method". .. note:: Abstract contracts cannot override an implemented virtual function with an unimplemented one. ================================================ FILE: docs/contracts/constant-state-variables.rst ================================================ .. index:: ! constant .. _constants: ************************************** Constant and Immutable State Variables ************************************** State variables can be declared as ``constant`` or ``immutable``. In both cases, the variables cannot be modified after the contract has been constructed. For ``constant`` variables, the value has to be fixed at compile-time, while for ``immutable``, it can still be assigned at construction time. It is also possible to define ``constant`` variables at the file level. Every occurrence of such a variable in the source is replaced by its underlying value and the compiler does not reserve a storage slot for it. It cannot be assigned a slot in transient storage using the ``transient`` keyword either. Compared to regular state variables, the gas costs of constant and immutable variables are much lower. For a constant variable, the expression assigned to it is copied to all the places where it is accessed and also re-evaluated each time. This allows for local optimizations. Immutable variables are evaluated once at construction time and their value is copied to all the places in the code where they are accessed. For these values, 32 bytes are reserved, even if they would fit in fewer bytes. Due to this, constant values can sometimes be cheaper than immutable values. Not all types for constants and immutables are implemented at this time. The only supported types are :ref:`strings ` (only for constants) and :ref:`value types `. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.21; uint constant X = 32**22 + 8; contract C { string constant TEXT = "abc"; bytes32 constant MY_HASH = keccak256("abc"); uint immutable decimals = 18; uint immutable maxBalance; address immutable owner = msg.sender; constructor(uint decimals_, address ref) { if (decimals_ != 0) // Immutables are only immutable when deployed. // At construction time they can be assigned to any number of times. decimals = decimals_; // Assignments to immutables can even access the environment. maxBalance = ref.balance; } function isBalanceTooHigh(address other) public view returns (bool) { return other.balance > maxBalance; } } Constant ======== For ``constant`` variables, the value has to be a constant at compile time and it has to be assigned where the variable is declared. Any expression that accesses storage, blockchain data (e.g. ``block.timestamp``, ``address(this).balance`` or ``block.number``) or execution data (``msg.value`` or ``gasleft()``) or makes calls to external contracts is disallowed. Expressions that might have a side-effect on memory allocation are allowed, but those that might have a side-effect on other memory objects are not. The built-in functions ``keccak256``, ``sha256``, ``ripemd160``, ``ecrecover``, ``addmod`` and ``mulmod`` are allowed (even though, with the exception of ``keccak256``, they do call external contracts). The reason behind allowing side-effects on the memory allocator is that it should be possible to construct complex objects like e.g. lookup-tables. This feature is not yet fully usable. Immutable ========= Variables declared as ``immutable`` are a bit less restricted than those declared as ``constant``: Immutable variables can be assigned a value at construction time. The value can be changed at any time before deployment and then it becomes permanent. One additional restriction is that immutables can only be assigned to inside expressions for which there is no possibility of being executed after creation. This excludes all modifier definitions and functions other than constructors. There are no restrictions on reading immutable variables. The read is even allowed to happen before the variable is written to for the first time because variables in Solidity always have a well-defined initial value. For this reason it is also allowed to never explicitly assign a value to an immutable. .. warning:: When accessing immutables at construction time, please keep the :ref:`initialization order ` in mind. Even if you provide an explicit initializer, some expressions may end up being evaluated before that initializer, especially when they are at a different level in inheritance hierarchy. .. note:: Before Solidity 0.8.21 initialization of immutable variables was more restrictive. Such variables had to be initialized exactly once at construction time and could not be read before then. The contract creation code generated by the compiler will modify the contract's runtime code before it is returned by replacing all references to immutables with the values assigned to them. This is important if you are comparing the runtime code generated by the compiler with the one actually stored in the blockchain. The compiler outputs where these immutables are located in the deployed bytecode in the ``immutableReferences`` field of the :ref:`compiler JSON standard output `. ================================================ FILE: docs/contracts/creating-contracts.rst ================================================ .. index:: ! contract;creation, constructor ****************** Creating Contracts ****************** Contracts can be created "from outside" via Ethereum transactions or from within Solidity contracts. IDEs, such as `Remix `_, make the creation process seamless using UI elements. One way to create contracts programmatically on Ethereum is via the JavaScript API `web3.js `_. It has a function called `web3.eth.Contract `_ to facilitate contract creation. When a contract is created, its :ref:`constructor ` (a function declared with the ``constructor`` keyword) is executed once. A constructor is optional. Only one constructor is allowed, which means overloading is not supported. After the constructor has executed, the final code of the contract is stored on the blockchain. This code includes all public and external functions and all functions that are reachable from there through function calls. The deployed code does not include the constructor code or internal functions only called from the constructor. .. index:: constructor;arguments Internally, constructor arguments are passed :ref:`ABI encoded ` after the code of the contract itself, but you do not have to care about this if you use ``web3.js``. If a contract wants to create another contract, the source code (and the binary) of the created contract has to be known to the creator. This means that cyclic creation dependencies are impossible. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract OwnedToken { // `TokenCreator` is a contract type that is defined below. // It is fine to reference it as long as it is not used // to create a new contract. TokenCreator creator; address owner; bytes32 name; // This is the constructor which registers the // creator and the assigned name. constructor(bytes32 name_) { // State variables are accessed via their name // and not via e.g. `this.owner`. Functions can // be accessed directly or through `this.f`, // but the latter provides an external view // to the function. Especially in the constructor, // you should not access functions externally, // because the function does not exist yet. // See the next section for details. owner = msg.sender; // We perform an explicit type conversion from `address` // to `TokenCreator` and assume that the type of // the calling contract is `TokenCreator`, there is // no real way to verify that. // This does not create a new contract. creator = TokenCreator(msg.sender); name = name_; } function changeName(bytes32 newName) public { // Only the creator can alter the name. // We compare the contract based on its // address which can be retrieved by // explicit conversion to address. if (msg.sender == address(creator)) name = newName; } function transfer(address newOwner) public { // Only the current owner can transfer the token. if (msg.sender != owner) return; // We ask the creator contract if the transfer // should proceed by using a function of the // `TokenCreator` contract defined below. If // the call fails (e.g. due to out-of-gas), // the execution also fails here. if (creator.isTokenTransferOK(owner, newOwner)) owner = newOwner; } } contract TokenCreator { function createToken(bytes32 name) public returns (OwnedToken tokenAddress) { // Create a new `Token` contract and return its address. // From the JavaScript side, the return type // of this function is `address`, as this is // the closest type available in the ABI. return new OwnedToken(name); } function changeName(OwnedToken tokenAddress, bytes32 name) public { // Again, the external type of `tokenAddress` is // simply `address`. tokenAddress.changeName(name); } // Perform checks to determine if transferring a token to the // `OwnedToken` contract should proceed function isTokenTransferOK(address currentOwner, address newOwner) public pure returns (bool ok) { // Check an arbitrary condition to see if transfer should proceed return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; } } ================================================ FILE: docs/contracts/custom-storage-layout.rst ================================================ .. index:: ! custom storage layout, ! storage layout specifier, ! layout at, ! base slot .. _custom-storage-layout: ********************* Custom Storage Layout ********************* A contract can define an arbitrary location for its storage using the ``layout`` specifier. The contract's state variables, including those inherited from base contracts, start from the specified base slot instead of the default slot zero. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.29; contract C layout at 0xAAAA + 0x11 { uint[3] x; // Occupies slots 0xAABB..0xAABD } As the above example shows, the specifier uses the ``layout at `` syntax and is located in the header of a contract definition. The layout specifier can be placed either before or after the inheritance specifier, and can appear at most once. The ``base-slot-expression`` must be an :ref:`integer literal` expression that can be evaluated at compilation time and yields a value in the range of ``uint256``. The use of constants initialized using such expressions and the :ref:`built-in function erc7201` is also allowed. A custom layout cannot make contract's storage "wrap around". If the selected base slot would push the static variables past the end of storage, the compiler will issue an error. Note that the data areas of dynamic arrays and mappings are not affected by this check because their layout is not linear. Regardless of the base slot used, their locations are calculated in a way that always puts them within the range of ``uint256`` and their sizes are not known at compilation time. While there are no other limits placed on the base slot, it is recommended to avoid locations that are too close to the end of the address space. Leaving too little space may complicate contract upgrades or cause problems for contracts that store additional values past their allocated space using inline assembly. The storage layout can only be specified for the topmost contract of an inheritance tree, and affects locations of all the storage variables in all the contracts in that tree. Variables are laid out according to the order of their definitions and the positions of their contracts in the :ref:`linearized inheritance hierarchy` and a custom base slot preserves their relative positions, shifting them all by the same amount. The storage layout cannot be specified for abstract contracts, interfaces and libraries. Also, it is important to note that it does *not* affect transient state variables. For details about storage layout and the effect of the layout specifier on it see :ref:`layout of storage variables`. .. warning:: The identifiers ``layout`` and ``at`` are not yet reserved as keywords in the language. It is strongly recommended to avoid using them since they will become reserved in a future breaking release. ================================================ FILE: docs/contracts/errors.rst ================================================ .. index:: ! error, revert, require, ! selector; of an error .. _errors: ************* Custom Errors ************* Errors in Solidity provide a convenient and gas-efficient way to explain to the user why an operation failed. They can be defined inside and outside of contracts (including interfaces and libraries). They have to be used together with the :ref:`revert statement ` or the :ref:`require function `. In the case of ``revert`` statements, or ``require`` calls where the condition is evaluated to be false, all changes in the current call are reverted, and the error data passed back to the caller. The example below shows custom error usage with the ``revert`` statement in function ``transferWithRevertError``, as well as the newer approach with ``require`` in function ``transferWithRequireError``. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.27; /// Insufficient balance for transfer. Needed `required` but only /// `available` available. /// @param available balance available. /// @param required requested amount to transfer. error InsufficientBalance(uint256 available, uint256 required); contract TestToken { mapping(address => uint) balance; function transferWithRevertError(address to, uint256 amount) public { if (amount > balance[msg.sender]) revert InsufficientBalance({ available: balance[msg.sender], required: amount }); balance[msg.sender] -= amount; balance[to] += amount; } function transferWithRequireError(address to, uint256 amount) public { require(amount <= balance[msg.sender], InsufficientBalance(balance[msg.sender], amount)); balance[msg.sender] -= amount; balance[to] += amount; } // ... } Another important detail to mention when it comes to using ``require`` with custom errors, is that memory allocation for the error-based revert reason will only happen in the reverting case, which, along with optimization of constants and string literals makes this about as gas-efficient as the ``if (!condition) revert CustomError(args)`` pattern. Errors cannot be overloaded or overridden but are inherited. The same error can be defined in multiple places as long as the scopes are distinct. Instances of errors can only be created using ``revert`` statements, or as the second argument to ``require`` functions. The error creates data that is then passed to the caller with the revert operation to either return to the off-chain component or catch it in a :ref:`try/catch statement `. Note that an error can only be caught when coming from an external call, reverts happening in internal calls or inside the same function cannot be caught. If you do not provide any parameters, the error only needs four bytes of data and you can use :ref:`NatSpec ` as above to further explain the reasons behind the error, which is not stored on chain. This makes this a very cheap and convenient error-reporting feature at the same time. More specifically, an error instance is ABI-encoded in the same way as a function call to a function of the same name and types would be and then used as the return data in the ``revert`` opcode. This means that the data consists of a 4-byte selector followed by :ref:`ABI-encoded` data. The selector consists of the first four bytes of the keccak256-hash of the signature of the error type. .. note:: It is possible for a contract to revert with different errors of the same name or even with errors defined in different places that are indistinguishable by the caller. For the outside, i.e. the ABI, only the name of the error is relevant, not the contract or file where it is defined. The statement ``require(condition, "description");`` would be equivalent to ``if (!condition) revert Error("description")`` if you could define ``error Error(string)``. Note, however, that ``Error`` is a built-in type and cannot be defined in user-supplied code. Similarly, a failing ``assert`` or similar conditions will revert with an error of the built-in type ``Panic(uint256)``. .. note:: Error data should only be used to give an indication of failure, but not as a means for control-flow. The reason is that the revert data of inner calls is propagated back through the chain of external calls by default. This means that an inner call can "forge" revert data that looks like it could have come from the contract that called it. Members of Errors ================= - ``error.selector``: A ``bytes4`` value containing the error selector. ================================================ FILE: docs/contracts/events.rst ================================================ .. index:: ! event, ! event; anonymous, ! event; indexed, ! event; topic .. _events: ****** Events ****** Solidity events give an abstraction on top of the EVM's logging functionality. Applications can subscribe and listen to these events through the RPC interface of an Ethereum client. Events can be defined at file level or as inheritable members of contracts (including interfaces and libraries). When you call them, they cause the arguments to be stored in the transaction's log - a special data structure in the blockchain. These logs are associated with the address of the contract that emitted them, are incorporated into the blockchain, and stay there as long as a block is accessible (forever as of now, but this might change in the future). The Log and its event data are not accessible from within contracts (not even from the contract that created them). It is possible to request a Merkle proof for logs, so if an external entity supplies a contract with such a proof, it can check that the log actually exists inside the blockchain. You have to supply block headers because the contract can only see the last 256 block hashes. You can add the attribute ``indexed`` to up to three parameters which adds them to a special data structure known as :ref:`"topics" ` instead of the data part of the log. A topic can only hold a single word (32 bytes) so if you use a :ref:`reference type ` for an indexed argument, the Keccak-256 hash of the value is stored as a topic instead. All parameters without the ``indexed`` attribute are :ref:`ABI-encoded ` into the data part of the log. Topics allow you to search for events, for example when filtering a sequence of blocks for certain events. You can also filter events by the address of the contract that emitted the event. For example, the code below uses the web3.js ``subscribe("logs")`` `method `_ to filter logs that match a topic with a certain address value: .. code-block:: javascript var options = { fromBlock: 0, address: web3.eth.defaultAccount, topics: ["0x0000000000000000000000000000000000000000000000000000000000000000", null, null] }; web3.eth.subscribe('logs', options, function (error, result) { if (!error) console.log(result); }) .on("data", function (log) { console.log(log); }) .on("changed", function (log) { }); The hash of the signature of the event is one of the topics, except if you declared the event with the ``anonymous`` specifier. This means that it is not possible to filter for specific anonymous events by name, you can only filter by the contract address. The advantage of anonymous events is that they are cheaper to deploy and call. It also allows you to declare four indexed arguments rather than three. .. note:: Since the transaction log only stores the event data and not the type, you have to know the type of the event, including which parameter is indexed and if the event is anonymous in order to correctly interpret the data. In particular, it is possible to "fake" the signature of another event using an anonymous event. .. index:: ! selector; of an event Members of Events ================= - ``event.selector``: For non-anonymous events, this is a ``bytes32`` value containing the ``keccak256`` hash of the event signature, as used in the default topic. Example ======= .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.21 <0.9.0; contract ClientReceipt { event Deposit( address indexed from, bytes32 indexed id, uint value ); function deposit(bytes32 id) public payable { // Events are emitted using `emit`, followed by // the name of the event and the arguments // (if any) in parentheses. Any such invocation // (even deeply nested) can be detected from // the JavaScript API by filtering for `Deposit`. emit Deposit(msg.sender, id, msg.value); } } The use in the JavaScript API is as follows: .. code-block:: javascript var abi = /* abi as generated by the compiler */; var ClientReceipt = web3.eth.contract(abi); var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */); var depositEvent = clientReceipt.Deposit(); // watch for changes depositEvent.watch(function(error, result){ // result contains non-indexed arguments and topics // given to the `Deposit` call. if (!error) console.log(result); }); // Or pass a callback to start watching immediately var depositEvent = clientReceipt.Deposit(function(error, result) { if (!error) console.log(result); }); The output of the above looks like the following (trimmed): .. code-block:: json { "returnValues": { "from": "0x1111…FFFFCCCC", "id": "0x50…sd5adb20", "value": "0x420042" }, "raw": { "data": "0x7f…91385", "topics": ["0xfd4…b4ead7", "0x7f…1a91385"] } } Additional Resources for Understanding Events ============================================= - `JavaScript documentation `_ - `Example usage of events `_ - `How to access them in js `_ ================================================ FILE: docs/contracts/function-modifiers.rst ================================================ .. index:: ! function;modifier .. _modifiers: ****************** Function Modifiers ****************** Modifiers can be used to change the behavior of functions in a declarative way. For example, you can use a modifier to automatically check a condition prior to executing the function. Modifiers are inheritable properties of contracts and may be overridden by derived contracts, but only if they are marked ``virtual``. For details, please see :ref:`Modifier Overriding `. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1 <0.9.0; contract owned { constructor() { owner = payable(msg.sender); } address payable owner; // This contract only defines a modifier but does not use // it: it will be used in derived contracts. // The function body is inserted where the special symbol // `_;` in the definition of a modifier appears. // This means that if the owner calls this function, the // function is executed and otherwise, an exception is // thrown. modifier onlyOwner { require( msg.sender == owner, "Only owner can call this function." ); _; } } contract priced { // Modifiers can receive arguments: modifier costs(uint price) { if (msg.value >= price) { _; } } } contract Register is priced, owned { mapping(address => bool) registeredAddresses; uint price; constructor(uint initialPrice) { price = initialPrice; } // It is important to also provide the // `payable` keyword here, otherwise the function will // automatically reject all Ether sent to it. function register() public payable costs(price) { registeredAddresses[msg.sender] = true; } // This contract inherits the `onlyOwner` modifier from // the `owned` contract. As a result, calls to `changePrice` will // only take effect if they are made by the stored owner. function changePrice(uint price_) public onlyOwner { price = price_; } } contract Mutex { bool locked; modifier noReentrancy() { require( !locked, "Reentrant call." ); locked = true; _; locked = false; } /// This function is protected by a mutex, which means that /// reentrant calls from within `msg.sender.call` cannot call `f` again. /// The `return 7` statement assigns 7 to the return value but still /// executes the statement `locked = false` in the modifier. function f() public noReentrancy returns (uint) { (bool success,) = msg.sender.call(""); require(success); return 7; } } If you want to access a modifier ``m`` defined in a contract ``C``, you can use ``C.m`` to reference it without virtual lookup. It is only possible to use modifiers defined in the current contract or its base contracts. Modifiers can also be defined in libraries but their use is limited to functions of the same library. Multiple modifiers are applied to a function by specifying them in a whitespace-separated list and are evaluated in the order presented. Modifiers cannot implicitly access or change the arguments and return values of functions they modify. Their values can only be passed to them explicitly at the point of invocation. In function modifiers, it is necessary to specify when you want the function to which the modifier is applied to be run. The placeholder statement (denoted by a single underscore character ``_``) is used to denote where the body of the function being modified should be inserted. Note that the placeholder operator is different from using underscores as leading or trailing characters in variable names, which is a stylistic choice. Explicit returns from a modifier or function body only leave the current modifier or function body. Return variables are assigned and control flow continues after the ``_`` in the preceding modifier. .. warning:: In an earlier version of Solidity, ``return`` statements in functions having modifiers behaved differently. An explicit return from a modifier with ``return;`` does not affect the values returned by the function. The modifier can, however, choose not to execute the function body at all and in that case the return variables are set to their :ref:`default values` just as if the function had an empty body. The ``_`` symbol can appear in the modifier multiple times. Each occurrence is replaced with the function body, and the function returns the return value of the final occurrence. Arbitrary expressions are allowed for modifier arguments and in this context, all symbols visible from the function are visible in the modifier. Symbols introduced in the modifier are not visible in the function (as they might change by overriding). ================================================ FILE: docs/contracts/functions.rst ================================================ .. index:: ! functions, ! function;free .. _functions: ********* Functions ********* Functions can be defined inside and outside of contracts. Functions outside of a contract, also called "free functions", always have implicit ``internal`` :ref:`visibility`. Their code is included in all contracts that call them, similar to internal library functions. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1 <0.9.0; function sum(uint[] memory arr) pure returns (uint s) { for (uint i = 0; i < arr.length; i++) s += arr[i]; } contract ArrayExample { bool found; function f(uint[] memory arr) public { // This calls the free function internally. // The compiler will add its code to the contract. uint s = sum(arr); require(s >= 10); found = true; } } .. note:: Functions defined outside a contract are still always executed in the context of a contract. They still can call other contracts, send them Ether and destroy the contract that called them, among other things. The main difference to functions defined inside a contract is that free functions do not have direct access to the variable ``this``, storage variables and functions not in their scope. .. _function-parameters-return-variables: Function Parameters and Return Variables ======================================== Functions take typed parameters as input and may, unlike in many other languages, also return an arbitrary number of values as output. Function Parameters ------------------- Function parameters are declared the same way as variables, and the name of unused parameters can be omitted. For example, if you want your contract to accept one kind of external call with two integers, you would use something like the following: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract Simple { uint sum; function taker(uint a, uint b) public { sum = a + b; } } Function parameters can be used as any other local variable and they can also be assigned to. .. index:: return array, return string, array, string, array of strings, dynamic array, variably sized array, return struct, struct Return Variables ---------------- Function return variables are declared with the same syntax after the ``returns`` keyword. For example, suppose you want to return two results: the sum and the product of two integers passed as function parameters, then you use something like: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract Simple { function arithmetic(uint a, uint b) public pure returns (uint sum, uint product) { sum = a + b; product = a * b; } } The names of return variables can be omitted. Return variables can be used as any other local variable and they are initialized with their :ref:`default value ` and have that value until they are (re-)assigned. You can either explicitly assign to return variables and then leave the function as above, or you can provide return values (either a single or :ref:`multiple ones`) directly with the ``return`` statement: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract Simple { function arithmetic(uint a, uint b) public pure returns (uint sum, uint product) { return (a + b, a * b); } } If you use an early ``return`` to leave a function that has return variables, you must provide return values together with the return statement. .. note:: You cannot return some types from non-internal functions. This includes the types listed below and any composite types that recursively contain them: - mappings, - internal function types, - reference types with location set to ``storage``, - multi-dimensional arrays (applies only to :ref:`ABI coder v1 `), - structs (applies only to :ref:`ABI coder v1 `). This restriction does not apply to library functions because of their different :ref:`internal ABI `. .. _multi-return: Returning Multiple Values ------------------------- When a function has multiple return types, the statement ``return (v0, v1, ..., vn)`` can be used to return multiple values. The number of components must be the same as the number of return variables and their types have to match, potentially after an :ref:`implicit conversion `. .. _state-mutability: State Mutability ================ .. index:: ! view function, function;view .. _view-functions: View Functions -------------- Functions can be declared ``view`` in which case they promise not to modify the state. .. note:: If the compiler's EVM target is Byzantium or newer (default) the opcode ``STATICCALL`` is used when ``view`` functions are called, which enforces the state to stay unmodified as part of the EVM execution. For library ``view`` functions ``DELEGATECALL`` is used, because there is no combined ``DELEGATECALL`` and ``STATICCALL``. This means library ``view`` functions do not have run-time checks that prevent state modifications. This should not impact security negatively because library code is usually known at compile-time and the static checker performs compile-time checks. The following statements are considered modifying the state: #. Writing to state variables (storage and transient storage). #. :ref:`Emitting events `. #. :ref:`Creating other contracts `. #. Using ``selfdestruct``. #. Sending Ether via calls. #. Calling any function not marked ``view`` or ``pure``. #. Using low-level calls. #. Using inline assembly that contains certain opcodes. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; contract C { function f(uint a, uint b) public view returns (uint) { return a * (b + 42) + block.timestamp; } } .. note:: ``constant`` on functions used to be an alias to ``view``, but this was dropped in version 0.5.0. .. note:: Getter methods are automatically marked ``view``. .. note:: Prior to version 0.5.0, the compiler did not use the ``STATICCALL`` opcode for ``view`` functions. This enabled state modifications in ``view`` functions through the use of invalid explicit type conversions. By using ``STATICCALL`` for ``view`` functions, modifications to the state are prevented on the level of the EVM. .. index:: ! pure function, function;pure .. _pure-functions: Pure Functions -------------- Functions can be declared ``pure`` in which case they promise not to read from or modify the state. In particular, it should be possible to evaluate a ``pure`` function at compile-time given only its inputs and ``msg.data``, but without any knowledge of the current blockchain state. This means that reading from ``immutable`` variables can be a non-pure operation. .. note:: If the compiler's EVM target is Byzantium or newer (default) the opcode ``STATICCALL`` is used, which does not guarantee that the state is not read, but at least that it is not modified. In addition to the list of state modifying statements explained above, the following are considered reading from the state: #. Reading from state variables (storage and transient storage). #. Accessing ``address(this).balance`` or ``
.balance``. #. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``). #. Calling any function not marked ``pure``. #. Using inline assembly that contains certain opcodes. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; contract C { function f(uint a, uint b) public pure returns (uint) { return a * (b + 42); } } Pure functions are able to use the ``revert()`` and ``require()`` functions to revert potential state changes when an :ref:`error occurs `. Reverting a state change is not considered a "state modification", as only changes to the state made previously in code that did not have the ``view`` or ``pure`` restriction are reverted and that code has the option to catch the ``revert`` and not pass it on. This behavior is also in line with the ``STATICCALL`` opcode. .. warning:: It is not possible to prevent functions from reading the state at the level of the EVM, it is only possible to prevent them from writing to the state (i.e. only ``view`` can be enforced at the EVM level, ``pure`` can not). .. note:: Prior to version 0.5.0, the compiler did not use the ``STATICCALL`` opcode for ``pure`` functions. This enabled state modifications in ``pure`` functions through the use of invalid explicit type conversions. By using ``STATICCALL`` for ``pure`` functions, modifications to the state are prevented on the level of the EVM. .. note:: Prior to version 0.4.17 the compiler did not enforce that ``pure`` is not reading the state. It is a compile-time type check, which can be circumvented by doing invalid explicit conversions between contract types, because the compiler can verify that the type of the contract does not do state-changing operations, but it cannot check that the contract that will be called at runtime is actually of that type. .. _special-functions: Special Functions ================= .. index:: ! receive ether function, function;receive, ! receive .. _receive-ether-function: Receive Ether Function ---------------------- A contract can have at most one ``receive`` function, declared using ``receive() external payable { ... }`` (without the ``function`` keyword). This function cannot have arguments, cannot return anything and must have ``external`` visibility and ``payable`` state mutability. It can be virtual, can override and can have modifiers. The receive function is executed on a call to the contract with empty calldata. This is the function that is executed on plain Ether transfers (e.g. via ``.send()`` or ``.transfer()``). If no such function exists, but a payable :ref:`fallback function ` exists, the fallback function will be called on a plain Ether transfer. If neither a receive Ether nor a payable fallback function is present, the contract cannot receive Ether through a transaction that does not represent a payable function call and throws an exception. In the worst case, the ``receive`` function can only rely on 2300 gas being available (for example when ``send`` or ``transfer`` is used), leaving little room to perform other operations except basic logging. The following operations will consume more gas than the 2300 gas stipend: - Writing to storage - Creating a contract - Calling an external function which consumes a large amount of gas - Sending Ether .. warning:: ``send()`` and ``transfer()`` are deprecated and scheduled for removal. See the section on :ref:`send ` and :ref:`transfer ` for more information. .. warning:: When Ether is sent directly to a contract (without a function call, i.e. sender uses ``send`` or ``transfer``) but the receiving contract does not define a receive Ether function or a payable fallback function, an exception will be thrown, sending back the Ether (this was different before Solidity v0.4.0). If you want your contract to receive Ether, you have to implement a receive Ether function (using payable fallback functions for receiving Ether is not recommended, since the fallback is invoked and would not fail for interface confusions on the part of the sender). .. warning:: A contract without a receive Ether function can receive Ether as a recipient of a *coinbase transaction* (aka *miner block reward*) or as a destination of a ``selfdestruct``. A contract cannot react to such Ether transfers and thus also cannot reject them. This is a design choice of the EVM and Solidity cannot work around it. It also means that ``address(this).balance`` can be higher than the sum of some manual accounting implemented in a contract (i.e. having a counter updated in the receive Ether function). Below you can see an example of a Sink contract that uses function ``receive``. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; // This contract keeps all Ether sent to it with no way // to get it back. contract Sink { event Received(address, uint); receive() external payable { emit Received(msg.sender, msg.value); } } .. index:: ! fallback function, function;fallback .. _fallback-function: Fallback Function ----------------- A contract can have at most one ``fallback`` function, declared using either ``fallback () external [payable]`` or ``fallback (bytes calldata input) external [payable] returns (bytes memory output)`` (both without the ``function`` keyword). This function must have ``external`` visibility. A fallback function can be virtual, can override and can have modifiers. The fallback function is executed on a call to the contract if none of the other functions match the given function signature, or if no data was supplied at all and there is no :ref:`receive Ether function `. The fallback function always receives data, but in order to also receive Ether it must be marked ``payable``. If the version with parameters is used, ``input`` will contain the full data sent to the contract (equal to ``msg.data``) and can return data in ``output``. The returned data will not be ABI-encoded. Instead it will be returned without modifications (not even padding). In the worst case, if a payable fallback function is also used in place of a receive function, it can only rely on 2300 gas being available (see :ref:`receive Ether function ` for a brief description of the implications of this). Like any function, the fallback function can execute complex operations as long as there is enough gas passed on to it. .. warning:: A ``payable`` fallback function is also executed for plain Ether transfers, if no :ref:`receive Ether function ` is present. It is recommended to always define a receive Ether function as well, if you define a payable fallback function to distinguish Ether transfers from interface confusions. .. note:: If you want to decode the input data, you can check the first four bytes for the function selector and then you can use ``abi.decode`` together with the array slice syntax to decode ABI-encoded data: ``(c, d) = abi.decode(input[4:], (uint256, uint256));`` Note that this should only be used as a last resort and proper functions should be used instead. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; contract Test { uint x; // This function is called for all messages sent to // this contract (there is no other function). // Sending Ether to this contract will cause an exception, // because the fallback function does not have the `payable` // modifier. fallback() external { x = 1; } } contract TestPayable { uint x; uint y; // This function is called for all messages sent to // this contract, except plain Ether transfers // (there is no other function except the receive function). // Any call with non-empty calldata to this contract will execute // the fallback function (even if Ether is sent along with the call). fallback() external payable { x = 1; y = msg.value; } // This function is called for plain Ether transfers, i.e. // for every call with empty calldata. receive() external payable { x = 2; y = msg.value; } } contract Caller { function callTest(Test test) public returns (bool) { (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); require(success); // results in test.x becoming == 1. // address(test) will not allow to call ``send`` directly, since ``test`` has no payable // fallback function. // It has to be converted to the ``address payable`` type to even allow calling ``send`` on it. address payable testPayable = payable(address(test)); // If someone sends Ether to that contract, // the transfer will fail, i.e. this returns false here. // This will report a warning (deprecation) return testPayable.send(2 ether); } function callTestPayable(TestPayable test) public returns (bool) { (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); require(success); // results in test.x becoming == 1 and test.y becoming 0. (success,) = address(test).call{value: 1}(abi.encodeWithSignature("nonExistingFunction()")); require(success); // results in test.x becoming == 1 and test.y becoming 1. // If someone sends Ether to that contract, the receive function in TestPayable will be called. // Since that function writes to storage, it takes more gas than is available with a // simple ``send`` or ``transfer``. Because of that, we have to use a low-level call. (success,) = address(test).call{value: 2 ether}(""); require(success); // results in test.x becoming == 2 and test.y becoming 2 ether. return true; } } .. index:: ! overload .. _overload-function: Function Overloading ==================== A contract can have multiple functions of the same name but with different parameter types. This process is called "overloading" and also applies to inherited functions. The following example shows overloading of the function ``f`` in the scope of contract ``A``. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract A { function f(uint value) public pure returns (uint out) { out = value; } function f(uint value, bool really) public pure returns (uint out) { if (really) out = value; } } Overloaded functions are also present in the external interface. It is an error if two externally visible functions differ by their Solidity types but not by their external types. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; // This will not compile contract A { function f(B value) public pure returns (B out) { out = value; } function f(address value) public pure returns (address out) { out = value; } } contract B { } Both ``f`` function overloads above end up accepting the address type for the ABI although they are considered different inside Solidity. Overload resolution and Argument matching ----------------------------------------- Overloaded functions are selected by matching the function declarations in the current scope to the arguments supplied in the function call. Functions are selected as overload candidates if all arguments can be implicitly converted to the expected types. If there is not exactly one candidate, resolution fails. .. note:: Return parameters are not taken into account for overload resolution. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract A { function f(uint8 val) public pure returns (uint8 out) { out = val; } function f(uint256 val) public pure returns (uint256 out) { out = val; } } Calling ``f(50)`` would create a type error since ``50`` can be implicitly converted both to ``uint8`` and ``uint256`` types. On another hand ``f(256)`` would resolve to ``f(uint256)`` overload as ``256`` cannot be implicitly converted to ``uint8``. ================================================ FILE: docs/contracts/inheritance.rst ================================================ .. index:: ! inheritance, ! base class, ! contract;base, ! deriving *********** Inheritance *********** Solidity supports multiple inheritance including polymorphism. Polymorphism means that a function call (internal and external) always executes the function of the same name (and parameter types) in the most derived contract in the inheritance hierarchy. This has to be explicitly enabled on each function in the hierarchy using the ``virtual`` and ``override`` keywords. See :ref:`Function Overriding ` for more details. It is possible to call functions further up in the inheritance hierarchy internally by explicitly specifying the contract using ``ContractName.functionName()`` or using ``super.functionName()`` if you want to call the function one level higher up in the flattened inheritance hierarchy (see below). When a contract inherits from other contracts, only a single contract is created on the blockchain, and the code from all the base contracts is compiled into the created contract. This means that all internal calls to functions of base contracts also just use internal function calls (``super.f(..)`` will use JUMP and not a message call). State variable shadowing is considered as an error. A derived contract can only declare a state variable ``x``, if there is no visible state variable with the same name in any of its bases. The general inheritance system is very similar to `Python's `_, especially concerning multiple inheritance, but there are also some :ref:`differences `. Details are given in the following example. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Owned { address payable owner; constructor() { owner = payable(msg.sender); } } // Use `is` to derive from another contract. Derived // contracts can access all non-private members including // internal functions and state variables. These cannot be // accessed externally via `this`, though. contract Emittable is Owned { event Emitted(); // The keyword `virtual` means that the function can change // its behavior in derived classes ("overriding"). function emitEvent() virtual public { if (msg.sender == owner) emit Emitted(); } } // These abstract contracts are only provided to make the // interface known to the compiler. Note the function // without body. If a contract does not implement all // functions it can only be used as an interface. abstract contract Config { function lookup(uint id) public virtual returns (address adr); } abstract contract NameReg { function register(bytes32 name) public virtual; function unregister() public virtual; } // Multiple inheritance is possible. Note that `Owned` is // also a base class of `Emittable`, yet there is only a single // instance of `Owned` (as for virtual inheritance in C++). contract Named is Owned, Emittable { constructor(bytes32 name) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).register(name); } // Functions can be overridden by another function with the same name and // the same number/types of inputs. If the overriding function has different // types of output parameters, that causes an error. // Both local and message-based function calls take these overrides // into account. // If you want the function to override, you need to use the // `override` keyword. You need to specify the `virtual` keyword again // if you want this function to be overridden again. function emitEvent() public virtual override { if (msg.sender == owner) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).unregister(); // It is still possible to call a specific // overridden function. Emittable.emitEvent(); } } } // If a constructor takes an argument, it needs to be // provided in the header or modifier-invocation-style at // the constructor of the derived contract (see below). contract PriceFeed is Owned, Emittable, Named("GoldFeed") { uint info; function updateInfo(uint newInfo) public { if (msg.sender == owner) info = newInfo; } // Here, we only specify `override` and not `virtual`. // This means that contracts deriving from `PriceFeed` // cannot change the behavior of `emitEvent` anymore. function emitEvent() public override(Emittable, Named) { Named.emitEvent(); } function get() public view returns(uint r) { return info; } } Note that above, we call ``Emittable.emitEvent()`` to "forward" the emit event request. The way this is done is problematic, as seen in the following example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Owned { address payable owner; constructor() { owner = payable(msg.sender); } } contract Emittable is Owned { event Emitted(); function emitEvent() virtual public { if (msg.sender == owner) { emit Emitted(); } } } contract Base1 is Emittable { event Base1Emitted(); function emitEvent() public virtual override { /* Here, we emit an event to simulate some Base1 logic */ emit Base1Emitted(); Emittable.emitEvent(); } } contract Base2 is Emittable { event Base2Emitted(); function emitEvent() public virtual override { /* Here, we emit an event to simulate some Base2 logic */ emit Base2Emitted(); Emittable.emitEvent(); } } contract Final is Base1, Base2 { event FinalEmitted(); function emitEvent() public override(Base1, Base2) { /* Here, we emit an event to simulate some Final logic */ emit FinalEmitted(); Base2.emitEvent(); } } A call to ``Final.emitEvent()`` will call ``Base2.emitEvent`` because we specify it explicitly in the final override, but this function will bypass ``Base1.emitEvent``, resulting in the following sequence of events: ``FinalEmitted -> Base2Emitted -> Emitted``, instead of the expected sequence: ``FinalEmitted -> Base2Emitted -> Base1Emitted -> Emitted``. The way around this is to use ``super``: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Owned { address payable owner; constructor() { owner = payable(msg.sender); } } contract Emittable is Owned { event Emitted(); function emitEvent() virtual public { if (msg.sender == owner) { emit Emitted(); } } } contract Base1 is Emittable { event Base1Emitted(); function emitEvent() public virtual override { /* Here, we emit an event to simulate some Base1 logic */ emit Base1Emitted(); super.emitEvent(); } } contract Base2 is Emittable { event Base2Emitted(); function emitEvent() public virtual override { /* Here, we emit an event to simulate some Base2 logic */ emit Base2Emitted(); super.emitEvent(); } } contract Final is Base1, Base2 { event FinalEmitted(); function emitEvent() public override(Base1, Base2) { /* Here, we emit an event to simulate some Final logic */ emit FinalEmitted(); super.emitEvent(); } } If ``Final`` calls a function of ``super``, it does not simply call this function on one of its base contracts. Rather, it calls this function on the next base contract in the final inheritance graph, so it will call ``Base1.emitEvent()`` (note that the final inheritance sequence is -- starting with the most derived contract: Final, Base2, Base1, Emittable, Owned). The actual function that is called when using super is not known in the context of the class where it is used, although its type is known. This is similar for ordinary virtual method lookup. .. index:: ! overriding;function .. _function-overriding: Function Overriding =================== Base functions can be overridden by inheriting contracts to change their behavior if they are marked as ``virtual``. The overriding function must then use the ``override`` keyword in the function header. The overriding function may only change the visibility of the overridden function from ``external`` to ``public``. The mutability may be changed to a more strict one following the order: ``nonpayable`` can be overridden by ``view`` and ``pure``. ``view`` can be overridden by ``pure``. ``payable`` is an exception and cannot be changed to any other mutability. The following example demonstrates changing mutability and visibility: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Base { function foo() virtual external view {} } contract Middle is Base {} contract Inherited is Middle { function foo() override public pure {} } For multiple inheritance, the most derived base contracts that define the same function must be specified explicitly after the ``override`` keyword. In other words, you have to specify all base contracts that define the same function and have not yet been overridden by another base contract (on some path through the inheritance graph). Additionally, if a contract inherits the same function from multiple (unrelated) bases, it has to explicitly override it: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; contract Base1 { function foo() virtual public {} } contract Base2 { function foo() virtual public {} } contract Inherited is Base1, Base2 { // Derives from multiple bases defining foo(), so we must explicitly // override it function foo() public override(Base1, Base2) {} } An explicit override specifier is not required if the function is defined in a common base contract or if there is a unique function in a common base contract that already overrides all other functions. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; contract A { function f() public pure{} } contract B is A {} contract C is A {} // No explicit override required contract D is B, C {} More formally, it is not required to override a function (directly or indirectly) inherited from multiple bases if there is a base contract that is part of all override paths for the signature, and (1) that base implements the function and no paths from the current contract to the base mentions a function with that signature or (2) that base does not implement the function and there is at most one mention of the function in all paths from the current contract to that base. In this sense, an override path for a signature is a path through the inheritance graph that starts at the contract under consideration and ends at a contract mentioning a function with that signature that does not override. If you do not mark a function that overrides as ``virtual``, derived contracts can no longer change the behavior of that function. .. note:: Functions with the ``private`` visibility cannot be ``virtual``. .. note:: Functions without implementation have to be marked ``virtual`` outside of interfaces. In interfaces, all functions are automatically considered ``virtual``. .. note:: Starting from Solidity 0.8.8, the ``override`` keyword is not required when overriding an interface function, except for the case where the function is defined in multiple bases. Public state variables can override external functions if the parameter and return types of the function matches the getter function of the variable: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; contract A { function f() external view virtual returns(uint) { return 5; } } contract B is A { uint public override f; } .. note:: While public state variables can override external functions, they themselves cannot be overridden. .. index:: ! overriding;modifier .. _modifier-overriding: Modifier Overriding (deprecated) ================================ Function modifiers can override each other. This works in the same way as :ref:`function overriding ` (except that there is no overloading for modifiers). The ``virtual`` keyword must be used on the overridden modifier and the ``override`` keyword must be used in the overriding modifier: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; contract Base { // This will report a warning (deprecation) modifier foo() virtual {_;} } contract Inherited is Base { modifier foo() override {_;} } In case of multiple inheritance, all direct base contracts must be specified explicitly: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; contract Base1 { // This will report a warning (deprecation) modifier foo() virtual {_;} } contract Base2 { // This will report a warning (deprecation) modifier foo() virtual {_;} } contract Inherited is Base1, Base2 { modifier foo() override(Base1, Base2) {_;} } .. warning:: ``virtual`` modifiers are deprecated and scheduled for removal. .. index:: ! constructor .. _constructor: Constructors ============ A constructor is an optional function declared with the ``constructor`` keyword which is executed upon contract creation, and where you can run contract initialization code. Before the constructor code is executed, state variables are initialised to their specified value if you initialise them inline, or their :ref:`default value` if you do not. After the constructor has run, the final code of the contract is deployed to the blockchain. The deployment of the code costs additional gas linear to the length of the code. This code includes all functions that are part of the public interface and all functions that are reachable from there through function calls. It does not include the constructor code or internal functions that are only called from the constructor. If there is no constructor, the contract will assume the default constructor, which is equivalent to ``constructor() {}``. For example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; abstract contract A { uint public a; constructor(uint a_) { a = a_; } } contract B is A(1) { constructor() {} } You can use internal parameters in a constructor (for example storage pointers). In this case, the contract has to be marked :ref:`abstract `, because these parameters cannot be assigned valid values from outside but only through the constructors of derived contracts. .. warning:: Prior to version 0.4.22, constructors were defined as functions with the same name as the contract. This syntax was deprecated and is not allowed anymore in version 0.5.0. .. warning:: Prior to version 0.7.0, you had to specify the visibility of constructors as either ``internal`` or ``public``. .. index:: ! base;constructor, inheritance list, contract;abstract, abstract contract Arguments for Base Constructors =============================== The constructors of all the base contracts will be called following the linearization rules explained below. If the base constructors have arguments, derived contracts need to specify all of them. This can be done in two ways: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Base { uint x; constructor(uint x_) { x = x_; } } // Either directly specify in the inheritance list... contract Derived1 is Base(7) { constructor() {} } // or through a "modifier" of the derived constructor... contract Derived2 is Base { constructor(uint y) Base(y * y) {} } // or declare abstract... abstract contract Derived3 is Base { } // and have the next concrete derived contract initialize it. contract DerivedFromDerived is Derived3 { constructor() Base(10 + 10) {} } One way is directly in the inheritance list (``is Base(7)``). The other is in the way a modifier is invoked as part of the derived constructor (``Base(y * y)``). The first way to do it is more convenient if the constructor argument is a constant and defines the behavior of the contract or describes it. The second way has to be used if the constructor arguments of the base depend on those of the derived contract. Arguments have to be given either in the inheritance list or in modifier-style in the derived constructor. Specifying arguments in both places is an error. If a derived contract does not specify the arguments to all of its base contracts' constructors, it must be declared abstract. In that case, when another contract derives from it, that other contract's inheritance list or constructor must provide the necessary parameters for all base classes that haven't had their parameters specified (otherwise, that other contract must be declared abstract as well). For example, in the above code snippet, see ``Derived3`` and ``DerivedFromDerived``. .. index:: ! inheritance;multiple, ! linearization, ! C3 linearization .. _multi-inheritance: Multiple Inheritance and Linearization ====================================== Languages that allow multiple inheritance have to deal with several problems. One is the `Diamond Problem `_. Solidity is similar to Python in that it uses C3 Linearization to force a specific order in the directed acyclic graph (DAG) of base classes. This results in the desirable property of monotonicity but disallows some inheritance graphs. Especially, the order in which the base classes are given in the ``is`` directive is important: You have to list the direct base contracts in the order from "most base-like" to "most derived". Note that this order is the reverse of the one used in Python. Another simplifying way to explain this is that when a function is called that is defined multiple times in different contracts, the given bases are searched from right to left (left to right in Python) in a depth-first manner, stopping at the first match. If a base contract has already been searched, it is skipped. In the following code, Solidity will give the error "Linearization of inheritance graph impossible". .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract X {} contract A is X {} // This will not compile contract C is A, X {} The reason for this is that ``C`` requests ``X`` to override ``A`` (by specifying ``A, X`` in this order), but ``A`` itself requests to override ``X``, which is a contradiction that cannot be resolved. Due to the fact that you have to explicitly override a function that is inherited from multiple bases without a unique override, C3 linearization is not too important in practice. One area where inheritance linearization is especially important and perhaps not as clear is when there are multiple constructors in the inheritance hierarchy. The constructors will always be executed in the linearized order, regardless of the order in which their arguments are provided in the inheriting contract's constructor. For example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Base1 { constructor() {} } contract Base2 { constructor() {} } // Constructors are executed in the following order: // 1 - Base1 // 2 - Base2 // 3 - Derived1 contract Derived1 is Base1, Base2 { constructor() Base1() Base2() {} } // Constructors are executed in the following order: // 1 - Base2 // 2 - Base1 // 3 - Derived2 contract Derived2 is Base2, Base1 { constructor() Base2() Base1() {} } // Constructors are still executed in the following order: // 1 - Base2 // 2 - Base1 // 3 - Derived3 contract Derived3 is Base2, Base1 { constructor() Base1() Base2() {} } Inheriting Different Kinds of Members of the Same Name ====================================================== The only situations where, due to inheritance, a contract may contain multiple definitions sharing the same name are: - Overloading of functions. - Overriding of virtual functions. - Overriding of external virtual functions by state variable getters. - Overriding of virtual modifiers. - Overloading of events. ================================================ FILE: docs/contracts/interfaces.rst ================================================ .. index:: ! contract;interface, ! interface contract .. _interfaces: ********** Interfaces ********** Interfaces are similar to abstract contracts, but they cannot have any functions implemented. There are further restrictions: - They cannot inherit from other contracts, but they can inherit from other interfaces. - All declared functions must be external in the interface, even if they are public in the contract. - They cannot declare a constructor. - They cannot declare state variables. - They cannot declare modifiers. Some of these restrictions might be lifted in the future. Interfaces are basically limited to what the Contract ABI can represent, and the conversion between the ABI and an interface should be possible without any information loss. Interfaces are denoted by their own keyword: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; interface Token { enum TokenType { Fungible, NonFungible } struct Coin { string obverse; string reverse; } function transfer(address recipient, uint amount) external; } Contracts can inherit interfaces as they would inherit other contracts. All functions declared in interfaces are implicitly ``virtual`` and any functions that override them do not need the ``override`` keyword. This does not automatically mean that an overriding function can be overridden again - this is only possible if the overriding function is marked ``virtual``. Interfaces can inherit from other interfaces. This has the same rules as normal inheritance. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; interface ParentA { function test() external returns (uint256); } interface ParentB { function test() external returns (uint256); } interface SubInterface is ParentA, ParentB { // Must redefine test in order to assert that the parent // meanings are compatible. function test() external override(ParentA, ParentB) returns (uint256); } Types defined inside interfaces and other contract-like structures can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``. .. warning:: Interfaces have supported ``enum`` types since :doc:`Solidity version 0.5.0 <050-breaking-changes>`, make sure the pragma version specifies this version as a minimum. ================================================ FILE: docs/contracts/libraries.rst ================================================ .. index:: ! library, callcode, delegatecall .. _libraries: ********* Libraries ********* Libraries are similar to contracts, but their purpose is that they are deployed only once at a specific address and their code is reused using the ``DELEGATECALL`` (``CALLCODE`` until Homestead) feature of the EVM. This means that if library functions are called, their code is executed in the context of the calling contract, i.e. ``this`` points to the calling contract, and especially the storage from the calling contract can be accessed. As a library is an isolated piece of source code, it can only access state variables of the calling contract if they are explicitly supplied (it would have no way to name them, otherwise). Library functions can only be called directly (i.e. without the use of ``DELEGATECALL``) if they do not modify the state (i.e. if they are ``view`` or ``pure`` functions), because libraries are assumed to be stateless. In particular, it is not possible to destroy a library. .. note:: Until version 0.4.20, it was possible to destroy libraries by circumventing Solidity's type system. Starting from that version, libraries contain a :ref:`mechanism` that disallows state-modifying functions to be called directly (i.e. without ``DELEGATECALL``). Libraries can be seen as implicit base contracts of the contracts that use them. They will not be explicitly visible in the inheritance hierarchy, but calls to library functions look just like calls to functions of explicit base contracts (using qualified access like ``L.f()``). Of course, calls to internal functions use the internal calling convention, which means that all internal types can be passed and types :ref:`stored in memory ` will be passed by reference and not copied. To realize this in the EVM, the code of internal library functions that are called from a contract and all functions called from therein will at compile time be included in the calling contract, and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``. .. note:: The inheritance analogy breaks down when it comes to public functions. Calling a public library function with ``L.f()`` results in an external call (``DELEGATECALL`` to be precise). In contrast, ``A.f()`` is an internal call when ``A`` is a base contract of the current contract. .. index:: using for, set The following example illustrates how to use libraries (but using a manual method, be sure to check out :ref:`using for ` for a more advanced example to implement a set). .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; // We define a new struct datatype that will be used to // hold its data in the calling contract. struct Data { mapping(uint => bool) flags; } library Set { // Note that the first parameter is of type "storage // reference" and thus only its storage address and not // its contents is passed as part of the call. This is a // special feature of library functions. It is idiomatic // to call the first parameter `self`, if the function can // be seen as a method of that object. function insert(Data storage self, uint value) public returns (bool) { if (self.flags[value]) return false; // already there self.flags[value] = true; return true; } function remove(Data storage self, uint value) public returns (bool) { if (!self.flags[value]) return false; // not there self.flags[value] = false; return true; } function contains(Data storage self, uint value) public view returns (bool) { return self.flags[value]; } } contract C { Data knownValues; function register(uint value) public { // The library functions can be called without a // specific instance of the library, since the // "instance" will be the current contract. require(Set.insert(knownValues, value)); } // In this contract, we can also directly access knownValues.flags, if we want. } Of course, you do not have to follow this way to use libraries: they can also be used without defining struct data types. Functions also work without any storage reference parameters, and they can have multiple storage reference parameters and in any position. The calls to ``Set.contains``, ``Set.insert`` and ``Set.remove`` are all compiled as calls (``DELEGATECALL``) to an external contract/library. If you use libraries, be aware that an actual external function call is performed. ``msg.sender``, ``msg.value`` and ``this`` will retain their values in this call, though (prior to Homestead, because of the use of ``CALLCODE``, ``msg.sender`` and ``msg.value`` changed, though). The following example shows how to use :ref:`types stored in memory ` and internal functions in libraries in order to implement custom types without the overhead of external function calls: .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; struct bigint { uint[] limbs; } library BigInt { function fromUint(uint x) internal pure returns (bigint memory r) { r.limbs = new uint[](1); r.limbs[0] = x; } function add(bigint memory a, bigint memory b) internal pure returns (bigint memory r) { r.limbs = new uint[](max(a.limbs.length, b.limbs.length)); uint carry = 0; for (uint i = 0; i < r.limbs.length; ++i) { uint limbA = limb(a, i); uint limbB = limb(b, i); unchecked { r.limbs[i] = limbA + limbB + carry; if (limbA + limbB < limbA || (limbA + limbB == type(uint).max && carry > 0)) carry = 1; else carry = 0; } } if (carry > 0) { // too bad, we have to add a limb uint[] memory newLimbs = new uint[](r.limbs.length + 1); uint i; for (i = 0; i < r.limbs.length; ++i) newLimbs[i] = r.limbs[i]; newLimbs[i] = carry; r.limbs = newLimbs; } } function limb(bigint memory a, uint index) internal pure returns (uint) { return index < a.limbs.length ? a.limbs[index] : 0; } function max(uint a, uint b) private pure returns (uint) { return a > b ? a : b; } } contract C { using BigInt for bigint; function f() public pure { bigint memory x = BigInt.fromUint(7); bigint memory y = BigInt.fromUint(type(uint).max); bigint memory z = x.add(y); assert(z.limb(1) > 0); } } It is possible to obtain the address of a library by converting the library type to the ``address`` type, i.e. using ``address(LibraryName)``. As the compiler does not know the address where the library will be deployed, the compiled hex code will contain placeholders of the form ``__$30bbc0abd4d6364515865950d3e0d10953$__`` `(format was different `_. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name, which would be for example ``libraries/bigint.sol:BigInt`` if the library was stored in a file called ``bigint.sol`` in a ``libraries/`` directory. Such bytecode is incomplete and should not be deployed. Placeholders need to be replaced with actual addresses. You can do that by either passing them to the compiler when the library is being compiled or by using the linker to update an already compiled binary. See :ref:`library-linking` for information on how to use the commandline compiler for linking. In comparison to contracts, libraries are restricted in the following ways: - they cannot have state variables - they cannot inherit nor be inherited - they cannot receive Ether - they cannot be destroyed (These might be lifted at a later point.) .. _library-selectors: .. index:: ! selector; of a library function Function Signatures and Selectors in Libraries ============================================== While external calls to public or external library functions are possible, the calling convention for such calls is considered to be internal to Solidity and not the same as specified for the regular :ref:`contract ABI`. External library functions support more argument types than external contract functions, for example recursive structs and storage pointers. For that reason, the function signatures used to compute the 4-byte selector are computed following an internal naming schema and arguments of types not supported in the contract ABI use an internal encoding. The following identifiers are used for the types in the signatures: - Value types, non-storage ``string`` and non-storage ``bytes`` use the same identifiers as in the contract ABI. - Non-storage array types follow the same convention as in the contract ABI, i.e. ``[]`` for dynamic arrays and ``[M]`` for fixed-size arrays of ``M`` elements. - Non-storage structs are referred to by their fully qualified name, i.e. ``C.S`` for ``contract C { struct S { ... } }``. - Storage pointer mappings use ``mapping( => ) storage`` where ```` and ```` are the identifiers for the key and value types of the mapping, respectively. - Other storage pointer types use the type identifier of their corresponding non-storage type, but append a single space followed by ``storage`` to it. The argument encoding is the same as for the regular contract ABI, except for storage pointers, which are encoded as a ``uint256`` value referring to the storage slot to which they point. Similarly to the contract ABI, the selector consists of the first four bytes of the Keccak256-hash of the signature. Its value can be obtained from Solidity using the ``.selector`` member as follows: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.14 <0.9.0; library L { function f(uint256) external {} } contract C { function g() public pure returns (bytes4) { return L.f.selector; } } .. _call-protection: Call Protection For Libraries ============================= As mentioned in the introduction, if a library's code is executed using a ``CALL`` instead of a ``DELEGATECALL`` or ``CALLCODE``, it will revert unless a ``view`` or ``pure`` function is called. The EVM does not provide a direct way for a contract to detect whether it was called using ``CALL`` or not, but a contract can use the ``ADDRESS`` opcode to find out "where" it is currently running. The generated code compares this address to the address used at construction time to determine the mode of calling. More specifically, the runtime code of a library always starts with a push instruction, which is a zero of 20 bytes at compilation time. When the deploy code runs, this constant is replaced in memory by the current address and this modified code is stored in the contract. At runtime, this causes the deploy time address to be the first constant to be pushed onto the stack and the dispatcher code compares the current address against this constant for any non-view and non-pure function. This means that the actual code stored on chain for a library is different from the code reported by the compiler as ``deployedBytecode``. ================================================ FILE: docs/contracts/transient-storage.rst ================================================ .. index:: ! transient storage, ! transient, tstore, tload .. _transient-storage: ***************** Transient Storage ***************** Transient storage is another data location besides memory, storage, calldata (and return-data and code) which was introduced alongside its respective opcodes ``TSTORE`` and ``TLOAD`` by `EIP-1153 `_. This new data location behaves as a key-value store similar to storage with the main difference being that data in transient storage is not permanent, but is scoped to the current transaction only, after which it will be reset to zero. Since the content of transient storage has very limited lifetime and size, it does not need to be stored permanently as a part of state and the associated gas costs are much lower than in case of storage. EVM version ``cancun`` or newer is required for transient storage to be available. Transient storage variables cannot be initialized in place, i.e., they cannot be assigned to upon declaration, since the value would be cleared at the end of the creation transaction, rendering the initialization ineffective. Transient variables will be :ref:`default value` initialized depending on their underlying type. ``constant`` and ``immutable`` variables conflict with transient storage, since their values are either inlined or directly stored in code. Transient storage variables have completely independent address space from storage, so that the order of transient state variables does not affect the layout of storage state variables and vice-versa. They do need distinct names though because all state variables share the same namespace. It is also important to note that the values in transient storage are packed in the same fashion as those in persistent storage. See :ref:`Storage Layout ` for more information. Besides that, transient variables can have visibility as well and ``public`` ones will have a getter function generated automatically as usual. Note that, currently, such use of ``transient`` as a data location is only allowed for :ref:`value type ` state variable declarations. Reference types, such as arrays, mappings and structs, as well as local or parameter variables are not yet supported. An expected canonical use case for transient storage is cheaper reentrancy locks, which can be readily implemented with the opcodes as showcased next. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; contract Generosity { mapping(address => bool) sentGifts; bool transient locked; modifier nonReentrant { require(!locked, "Reentrancy attempt"); locked = true; _; // Unlocks the guard, making the pattern composable. // After the function exits, it can be called again, even in the same transaction. locked = false; } function claimGift() nonReentrant public { require(address(this).balance >= 1 ether); require(!sentGifts[msg.sender]); (bool success, ) = msg.sender.call{value: 1 ether}(""); require(success); // In a reentrant function, doing this last would open up the vulnerability sentGifts[msg.sender] = true; } } Transient storage is private to the contract that owns it, in the same way as persistent storage. Only owning contract frames may access their transient storage, and when they do, all the frames access the same transient store. Transient storage is part of the EVM state and is subject to the same mutability enforcements as persistent storage. As such, any read access to it is not ``pure`` and writing access is not ``view``. If the ``TSTORE`` opcode is called within the context of a ``STATICCALL``, it will result in an exception instead of performing the modification. ``TLOAD`` is allowed within the context of a ``STATICCALL``. When transient storage is used in the context of ``DELEGATECALL`` or ``CALLCODE``, then the owning contract of the transient storage is the contract that issued ``DELEGATECALL`` or ``CALLCODE`` instruction (the caller) as with persistent storage. When transient storage is used in the context of ``CALL`` or ``STATICCALL``, then the owning contract of the transient storage is the contract that is the target of the ``CALL`` or ``STATICCALL`` instruction (the callee). .. note:: In the case of ``DELEGATECALL``, since references to transient storage variables are currently not supported, it is not possible to pass those into library calls. In libraries, access to transient storage is only possible using inline assembly. If a frame reverts, all writes to transient storage that took place between entry to the frame and the return are reverted, including those that took place in inner calls. The caller of an external call may employ a ``try ... catch`` block to prevent reverts bubbling up from the inner calls. ********************************************************************* Composability of Smart Contracts and the Caveats of Transient Storage ********************************************************************* Given the caveats mentioned in the specification of EIP-1153, in order to preserve the composability of your smart contract, utmost care is recommended for more advanced use cases of transient storage. For smart contracts, composability is a very important design principle to achieve self-contained behaviour, such that multiple calls into individual smart contracts can be composed to more complex applications. So far the EVM largely guaranteed composable behaviour, since multiple calls into a smart contract within a complex transaction are virtually indistinguishable from multiple calls to the contract stretched over several transactions. However, transient storage allows a violation of this principle, and incorrect use may lead to complex bugs that only surface when used across several calls. Let's illustrate the problem with a simple example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; contract MulService { uint transient multiplier; function setMultiplier(uint mul) external { multiplier = mul; } function multiply(uint value) external view returns (uint) { return value * multiplier; } } and a sequence of external calls: .. code-block:: solidity setMultiplier(42); multiply(1); multiply(2); If the example used memory or storage to store the multiplier, it would be fully composable. It would not matter whether you split the sequence into separate transactions or grouped them in some way. You would always get the same result: after ``multiplier`` is set to ``42``, the subsequent calls would return ``42`` and ``84`` respectively. This enables use cases such as batching calls from multiple transactions together to reduce gas costs. Transient storage potentially breaks such use cases since composability can no longer be taken for granted. In the example, if the calls are not executed in the same transaction, then ``multiplier`` is reset and the next calls to function ``multiply`` would always return ``0``. As another example, since transient storage is constructed as a relatively cheap key-value store, a smart contract author may be tempted to use transient storage as a replacement for in-memory mappings without keeping track of the modified keys in the mapping and thereby without clearing the mapping at the end of the call. This, however, can easily lead to unexpected behaviour in complex transactions, in which values set by a previous call into the contract within the same transaction remain. The use of transient storage for reentrancy locks that are cleared at the end of the call frame into the contract, is safe. However, be sure to resist the temptation to save the 100 gas used for resetting the reentrancy lock, since failing to do so, will restrict your contract to only one call within a transaction, preventing its use in complex composed transactions, which have been a cornerstone for complex applications on chain. It is recommend to generally always clear transient storage completely at the end of a call into your smart contract to avoid these kinds of issues and to simplify the analysis of the behaviour of your contract within complex transactions. Check the `Security Considerations section of EIP-1153 `_ for further details. ================================================ FILE: docs/contracts/using-for.rst ================================================ .. index:: ! using for, library, ! operator;user-defined, function;free .. _using-for: ********* Using For ********* The directive ``using A for B`` can be used to attach functions (``A``) as operators to user-defined value types or as member functions to any type (``B``). The member functions receive the object they are called on as their first parameter (like the ``self`` variable in Python). The operator functions receive operands as parameters. It is valid either at file level or inside a contract, at contract level. The first part, ``A``, can be one of: - A list of functions, optionally with an operator name assigned (e.g. ``using {f, g as +, h, L.t} for uint``). If no operator is specified, the function can be either a library function or a free function and is attached to the type as a member function. Otherwise it must be a free function and it becomes the definition of that operator on the type. - The name of a library (e.g. ``using L for uint``) - all non-private functions of the library are attached to the type as member functions At file level, the second part, ``B``, has to be an explicit type (without data location specifier). Inside contracts, you can also use ``*`` in place of the type (e.g. ``using L for *;``), which has the effect that all functions of the library ``L`` are attached to *all* types. If you specify a library, *all* non-private functions in the library get attached, even those where the type of the first parameter does not match the type of the object. The type is checked at the point the function is called and function overload resolution is performed. If you use a list of functions (e.g. ``using {f, g, h, L.t} for uint``), then the type (``uint``) has to be implicitly convertible to the first parameter of each of these functions. This check is performed even if none of these functions are called. Note that private library functions can only be specified when ``using for`` is inside a library. If you define an operator (e.g. ``using {f as +} for T``), then the type (``T``) must be a :ref:`user-defined value type ` and the definition must be a ``pure`` function. Operator definitions must be global. The following operators can be defined this way: +------------+----------+---------------------------------------------+ | Category | Operator | Possible signatures | +============+==========+=============================================+ | Bitwise | ``&`` | ``function (T, T) pure returns (T)`` | | +----------+---------------------------------------------+ | | ``|`` | ``function (T, T) pure returns (T)`` | | +----------+---------------------------------------------+ | | ``^`` | ``function (T, T) pure returns (T)`` | | +----------+---------------------------------------------+ | | ``~`` | ``function (T) pure returns (T)`` | +------------+----------+---------------------------------------------+ | Arithmetic | ``+`` | ``function (T, T) pure returns (T)`` | | +----------+---------------------------------------------+ | | ``-`` | ``function (T, T) pure returns (T)`` | | + +---------------------------------------------+ | | | ``function (T) pure returns (T)`` | | +----------+---------------------------------------------+ | | ``*`` | ``function (T, T) pure returns (T)`` | | +----------+---------------------------------------------+ | | ``/`` | ``function (T, T) pure returns (T)`` | | +----------+---------------------------------------------+ | | ``%`` | ``function (T, T) pure returns (T)`` | +------------+----------+---------------------------------------------+ | Comparison | ``==`` | ``function (T, T) pure returns (bool)`` | | +----------+---------------------------------------------+ | | ``!=`` | ``function (T, T) pure returns (bool)`` | | +----------+---------------------------------------------+ | | ``<`` | ``function (T, T) pure returns (bool)`` | | +----------+---------------------------------------------+ | | ``<=`` | ``function (T, T) pure returns (bool)`` | | +----------+---------------------------------------------+ | | ``>`` | ``function (T, T) pure returns (bool)`` | | +----------+---------------------------------------------+ | | ``>=`` | ``function (T, T) pure returns (bool)`` | +------------+----------+---------------------------------------------+ Note that unary and binary ``-`` need separate definitions. The compiler will choose the right definition based on how the operator is invoked. The ``using A for B;`` directive is active only within the current scope (either the contract or the current module/source unit), including within all of its functions, and has no effect outside of the contract or module in which it is used. When the directive is used at file level and applied to a user-defined type which was defined at file level in the same file, the word ``global`` can be added at the end. This will have the effect that the functions and operators are attached to the type everywhere the type is available (including other files), not only in the scope of the using statement. Let us rewrite the set example from the :ref:`libraries` section in this way, using file-level functions instead of library functions. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; struct Data { mapping(uint => bool) flags; } // Now we attach functions to the type. // The attached functions can be used throughout the rest of the module. // If you import the module, you have to // repeat the using directive there, for example as // import "flags.sol" as Flags; // using {Flags.insert, Flags.remove, Flags.contains} // for Flags.Data; using {insert, remove, contains} for Data; function insert(Data storage self, uint value) returns (bool) { if (self.flags[value]) return false; // already there self.flags[value] = true; return true; } function remove(Data storage self, uint value) returns (bool) { if (!self.flags[value]) return false; // not there self.flags[value] = false; return true; } function contains(Data storage self, uint value) view returns (bool) { return self.flags[value]; } contract C { Data knownValues; function register(uint value) public { // Here, all variables of type Data have // corresponding member functions. // The following function call is identical to // `Set.insert(knownValues, value)` require(knownValues.insert(value)); } } It is also possible to extend built-in types in that way. In this example, we will use a library. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.13; library Search { function indexOf(uint[] storage self, uint value) public view returns (uint) { for (uint i = 0; i < self.length; i++) if (self[i] == value) return i; return type(uint).max; } } using Search for uint[]; contract C { uint[] data; function append(uint value) public { data.push(value); } function replace(uint from, uint to) public { // This performs the library function call uint index = data.indexOf(from); if (index == type(uint).max) data.push(to); else data[index] = to; } } Note that all external library calls are actual EVM function calls. This means that if you pass memory or value types, a copy will be performed, even in case of the ``self`` variable. The only situation where no copy will be performed is when storage reference variables are used or when internal library functions are called. Another example shows how to define a custom operator for a user-defined type: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.19; type UFixed16x2 is uint16; using { add as +, div as / } for UFixed16x2 global; uint32 constant SCALE = 100; function add(UFixed16x2 a, UFixed16x2 b) pure returns (UFixed16x2) { return UFixed16x2.wrap(UFixed16x2.unwrap(a) + UFixed16x2.unwrap(b)); } function div(UFixed16x2 a, UFixed16x2 b) pure returns (UFixed16x2) { uint32 a32 = UFixed16x2.unwrap(a); uint32 b32 = UFixed16x2.unwrap(b); uint32 result32 = a32 * SCALE / b32; require(result32 <= type(uint16).max, "Divide overflow"); return UFixed16x2.wrap(uint16(a32 * SCALE / b32)); } contract Math { function avg(UFixed16x2 a, UFixed16x2 b) public pure returns (UFixed16x2) { return (a + b) / UFixed16x2.wrap(200); } } ================================================ FILE: docs/contracts/visibility-and-getters.rst ================================================ .. index:: ! visibility, external, public, private, internal .. |visibility-caveat| replace:: Making something ``private`` or ``internal`` only prevents other contracts from reading or modifying the information, but it will still be visible to the whole world outside of the blockchain. .. _visibility-and-getters: ********************** Visibility and Getters ********************** State Variable Visibility ========================= ``public`` Public state variables differ from internal ones only in that the compiler automatically generates :ref:`getter functions` for them, which allows other contracts to read their values. When used within the same contract, the external access (e.g. ``this.x``) invokes the getter while internal access (e.g. ``x``) gets the variable value directly from storage. Setter functions are not generated so other contracts cannot directly modify their values. ``internal`` Internal state variables can only be accessed from within the contract they are defined in and in derived contracts. They cannot be accessed externally. This is the default visibility level for state variables. ``private`` Private state variables are like internal ones but they are not visible in derived contracts. .. warning:: |visibility-caveat| Function Visibility =================== Solidity knows two kinds of function calls: external ones that do create an actual EVM message call and internal ones that do not. Furthermore, internal functions can be made inaccessible to derived contracts. This gives rise to four types of visibility for functions. ``external`` External functions are part of the contract interface, which means they can be called from other contracts and via transactions. An external function ``f`` cannot be called internally (i.e. ``f()`` does not work, but ``this.f()`` works). ``public`` Public functions are part of the contract interface and can be either called internally or via message calls. ``internal`` Internal functions can only be accessed from within the current contract or contracts deriving from it. They cannot be accessed externally. Since they are not exposed to the outside through the contract's ABI, they can take parameters of internal types like mappings or storage references. ``private`` Private functions are like internal ones but they are not visible in derived contracts. .. warning:: |visibility-caveat| The visibility specifier is given after the type for state variables and between parameter list and return parameter list for functions. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract C { function f(uint a) private pure returns (uint b) { return a + 1; } function setData(uint a) internal { data = a; } uint public data; } In the following example, ``D``, can call ``c.getData()`` to retrieve the value of ``data`` in state storage, but is not able to call ``f``. Contract ``E`` is derived from ``C`` and, thus, can call ``compute``. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract C { uint private data; function f(uint a) private pure returns(uint b) { return a + 1; } function setData(uint a) public { data = a; } function getData() public view returns(uint) { return data; } function compute(uint a, uint b) internal pure returns (uint) { return a + b; } } // This will not compile contract D { function readData() public { C c = new C(); uint local = c.f(7); // error: member `f` is not visible c.setData(3); local = c.getData(); local = c.compute(3, 5); // error: member `compute` is not visible } } contract E is C { function g() public { C c = new C(); uint val = compute(3, 5); // access to internal member (from derived to parent contract) } } .. index:: ! getter;function, ! function;getter .. _getter-functions: Getter Functions ================ The compiler automatically creates getter functions for all **public** state variables. For the contract given below, the compiler will generate a function called ``data`` that does not take any arguments and returns a ``uint``, the value of the state variable ``data``. State variables can be initialized when they are declared. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract C { uint public data = 42; } contract Caller { C c = new C(); function f() public view returns (uint) { return c.data(); } } The getter functions have external visibility. If the symbol is accessed internally (i.e. without ``this.``), it evaluates to a state variable. If it is accessed externally (i.e. with ``this.``), it evaluates to a function. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract C { uint public data; function x() public returns (uint) { data = 3; // internal access return this.data(); // external access } } If you have a ``public`` state variable of array type, then you can only retrieve single elements of the array via the generated getter function. This mechanism exists to avoid high gas costs when returning an entire array. You can use arguments to specify which individual element to return, for example ``myArray(0)``. If you want to return an entire array in one call, then you need to write a function, for example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract arrayExample { // public state variable uint[] public myArray; // Getter function generated by the compiler /* function myArray(uint i) public view returns (uint) { return myArray[i]; } */ // function that returns entire array function getArray() public view returns (uint[] memory) { return myArray; } } Now you can use ``getArray()`` to retrieve the entire array, instead of ``myArray(i)``, which returns a single element per call. The next example is more complex: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract Complex { struct Data { uint a; bytes3 b; mapping(uint => uint) map; uint[3] c; uint[] d; bytes e; } mapping(uint => mapping(bool => Data[])) public data; } It generates a function of the following form. The mapping and arrays (with the exception of byte arrays) in the struct are omitted because there is no good way to select individual struct members or provide a key for the mapping: .. code-block:: solidity function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b, bytes memory e) { a = data[arg1][arg2][arg3].a; b = data[arg1][arg2][arg3].b; e = data[arg1][arg2][arg3].e; } ================================================ FILE: docs/contracts.rst ================================================ .. index:: ! contract .. _contracts: ########## Contracts ########## Contracts in Solidity are similar to classes in object-oriented languages. They contain persistent data in state variables, and functions that can modify these variables. Calling a function on a different contract (instance) will perform an EVM function call and thus switch the context such that state variables in the calling contract are inaccessible. A contract and its functions need to be called for anything to happen. There is no "cron" concept in Ethereum to call a function at a particular event automatically. .. include:: contracts/creating-contracts.rst .. include:: contracts/visibility-and-getters.rst .. include:: contracts/function-modifiers.rst .. include:: contracts/transient-storage.rst .. include:: contracts/constant-state-variables.rst .. include:: contracts/custom-storage-layout.rst .. include:: contracts/functions.rst .. include:: contracts/events.rst .. include:: contracts/errors.rst .. include:: contracts/inheritance.rst .. include:: contracts/abstract-contracts.rst .. include:: contracts/interfaces.rst .. include:: contracts/libraries.rst .. include:: contracts/using-for.rst ================================================ FILE: docs/contributing.rst ================================================ ############ Contributing ############ Help is always welcome and there are plenty of options to contribute to Solidity. In particular, we appreciate support in the following areas: * Reporting issues. * Fixing and responding to `Solidity's GitHub issues `_, especially those tagged as `"good first issue" `_ which are meant as introductory issues for external contributors. * Improving the documentation. * `Translating `_ the documentation into more languages. * Responding to questions from other users on `StackExchange `_ and the `Solidity Gitter Chat `_. * Getting involved in the language design process by proposing language changes or new features in the `Solidity forum `_ and providing feedback. To get started, you can try :ref:`building-from-source` in order to familiarize yourself with the components of Solidity and the build process. Also, it may be useful to become well-versed at writing smart-contracts in Solidity. Please note that this project is released with a `Contributor Code of Conduct `_. By participating in this project — in the issues, pull requests, or Gitter channels — you agree to abide by its terms. Team Calls ========== If you have issues or pull requests to discuss, or are interested in hearing what the team and contributors are working on, you can join our public team call: - Wednesdays at 3PM CET/CEST. The call takes place on `Jitsi `_. New topics can be freely added to the `agenda `_ and will be scheduled for discussion on the nearest call. How to Report Issues ==================== To report an issue, please use the `GitHub issues tracker `_. When reporting issues, please mention the following details: * Solidity version. * Source code (if applicable). * Operating system. * Steps to reproduce the issue. * Actual vs. expected behavior. Reducing the source code that caused the issue to a bare minimum is always very helpful, and sometimes even clarifies a misunderstanding. For technical discussions about language design, a post in the `Solidity forum `_ is the correct place (see :ref:`solidity_language_design`). Workflow for Pull Requests ========================== In order to contribute, please fork off of the ``develop`` branch and make your changes there. Your commit messages should detail *why* you made your change in addition to *what* you did (unless it is a tiny change). If you need to pull in any changes from ``develop`` after making your fork (for example, to resolve potential merge conflicts), please avoid using ``git merge`` and instead, ``git rebase`` your branch. This will help us review your change more easily. Additionally, if you are writing a new feature, please ensure you add appropriate test cases under ``test/`` (see below). However, if you are making a larger change, please consult with the `Solidity Development Gitter channel `_ (different from the one mentioned above — this one is focused on compiler and language development instead of language usage) first. New features and bugfixes should be added to the ``Changelog.md`` file: please follow the style of previous entries, when applicable. Finally, please make sure you respect the `coding style `_ for this project. Also, even though we do CI testing, please test your code and ensure that it builds locally before submitting a pull request. We highly recommend going through our `review checklist `_ before submitting the pull request. We thoroughly review every PR and will help you get it right, but there are many common problems that can be easily avoided, making the review much smoother. Thank you for your help! Running the Compiler Tests ========================== Prerequisites ------------- For running all compiler tests you may want to optionally install a few dependencies (`evmone `_, `z3 `_, `Eldarica `_, `cvc5 `). On macOS systems, some of the testing scripts expect GNU coreutils to be installed. This can be easiest accomplished using Homebrew: ``brew install coreutils``. On Windows systems, make sure that you have a privilege to create symlinks, otherwise several tests may fail. Administrators should have that privilege, but you may also `grant it to other users `_ or `enable Developer Mode `_. Running the Tests ----------------- Solidity includes different types of tests, most of them bundled into the `Boost C++ Test Framework `_ application ``soltest``. Running ``build/test/soltest`` or its wrapper ``scripts/soltest.sh`` is sufficient for most changes. The ``./scripts/tests.sh`` script executes most Solidity tests automatically, including those bundled into the `Boost C++ Test Framework `_ application ``soltest`` (or its wrapper ``scripts/soltest.sh``), as well as command-line tests and compilation tests. The test system automatically tries to discover the location of the `evmone `_ for running the semantic tests. The ``evmone`` library must be located in the ``deps`` or ``deps/lib`` directory relative to the current working directory, to its parent or its parent's parent. Alternatively, an explicit location for the ``evmone`` shared object can be specified via the ``ETH_EVMONE`` environment variable. ``evmone`` is needed mainly for running semantic and gas tests. If you do not have it installed, you can skip these tests by passing the ``--no-semantic-tests`` flag to ``scripts/soltest.sh``. The ``evmone`` library should end with the file name extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. For running SMT tests, the ``z3`` executable must be present in ``PATH``. A few SMT tests use ``Eldarica`` instead of ``z3``. These require its executable (``eld``) to be present in ``PATH`` for the tests to pass. However, if ``Eldarica`` is not found, these tests will be automatically skipped. If ``z3`` is not present on your system, you should disable the SMT tests by exporting ``SMT_FLAGS=--no-smt`` before running ``./scripts/tests.sh`` or running ``./scripts/soltest.sh --no-smt``. These tests are ``libsolidity/smtCheckerTests``. .. note:: To get a list of all unit tests run by Soltest, run ``./build/test/soltest --list_content=HRF``. For quicker results you can run a subset of, or specific tests. To run a subset of tests, you can use filters: ``./scripts/soltest.sh -t TestSuite/TestName``, where ``TestName`` can be a wildcard ``*``. Or, for example, to run all the tests for the yul disambiguator: ``./scripts/soltest.sh -t "yulOptimizerTests/disambiguator/*" --no-smt``. ``./build/test/soltest --help`` has extensive help on all of the options available. See especially: - `show_progress (-p) `_ to show test completion, - `run_test (-t) `_ to run specific tests cases, and - `report-level (-r) `_ give a more detailed report. .. note:: Those working in a Windows environment wanting to run the above basic sets without z3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``. If you are running this in plain Command Prompt, use ``.\build\test\Release\soltest.exe -- --no-smt``. If you want to debug using GDB, make sure you build differently than the "usual". For example, you could run the following command in your ``build`` folder: .. code-block:: bash cmake -DCMAKE_BUILD_TYPE=Debug .. make This creates symbols so that when you debug a test using the ``--debug`` flag, you have access to functions and variables in which you can break or print with. The CI runs additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target. Writing and Running Syntax Tests -------------------------------- Syntax tests check that the compiler generates the correct error messages for invalid code and properly accepts valid code. They are stored in individual files inside the ``tests/libsolidity/syntaxTests`` folder. These files must contain annotations, stating the expected result(s) of the respective test. The test suite compiles and checks them against the given expectations. For example: ``./test/libsolidity/syntaxTests/double_stateVariable_declaration.sol`` .. code-block:: solidity contract test { uint256 variable; uint128 variable; } // ---- // DeclarationError: (36-52): Identifier already declared. A syntax test must contain at least the contract under test itself, followed by the separator ``// ----``. The comments that follow the separator are used to describe the expected compiler errors or warnings. The number range denotes the location in the source where the error occurred. If you want the contract to compile without any errors or warning you can leave out the separator and the comments that follow it. In the above example, the state variable ``variable`` was declared twice, which is not allowed. This results in a ``DeclarationError`` stating that the identifier was already declared. The ``isoltest`` tool is used for these tests and you can find it under ``./build/test/tools/``. It is an interactive tool which allows editing of failing contracts using your preferred text editor. Let's try to break this test by removing the second declaration of ``variable``: .. code-block:: solidity contract test { uint256 variable; } // ---- // DeclarationError: (36-52): Identifier already declared. Running ``./build/test/tools/isoltest`` again results in a test failure: .. code-block:: text syntaxTests/double_stateVariable_declaration.sol: FAIL Contract: contract test { uint256 variable; } Expected result: DeclarationError: (36-52): Identifier already declared. Obtained result: Success ``isoltest`` prints the expected result next to the obtained result, and also provides a way to edit, update or skip the current contract file, or quit the application. It offers several options for failing tests: - ``edit``: ``isoltest`` tries to open the contract in an editor so you can adjust it. It either uses the editor given on the command-line (as ``isoltest --editor /path/to/editor``), in the environment variable ``EDITOR`` or just ``/usr/bin/editor`` (in that order). - ``update``: Updates the expectations for contract under test. This updates the annotations by removing unmet expectations and adding missing expectations. The test is then run again. - ``skip``: Skips the execution of this particular test. - ``quit``: Quits ``isoltest``. All of these options apply to the current contract, except ``quit`` which stops the entire testing process. Automatically updating the test above changes it to .. code-block:: solidity contract test { uint256 variable; } // ---- and re-run the test. It now passes again: .. code-block:: text Re-running test case... syntaxTests/double_stateVariable_declaration.sol: OK .. note:: Choose a name for the contract file that explains what it tests, e.g. ``double_variable_declaration.sol``. Do not put more than one contract into a single file, unless you are testing inheritance or cross-contract calls. Each file should test one aspect of your new feature. Command-line Tests ------------------ Our suite of end-to-end command-line tests checks the behaviour of the compiler binary as a whole in various scenarios. These tests are located in `test/cmdlineTests/ `_, one per subdirectory, and can be executed using the ``cmdlineTests.sh`` script. By default the script runs all available tests. You can also provide one or more `file name patterns `_, in which case only the tests matching at least one pattern will be executed. It is also possible to exclude files matching a specific pattern by prefixing it with ``--exclude``. By default the script assumes that a ``solc`` binary is available inside the ``build/`` subdirectory inside the working copy. If you build the compiler outside of the source tree, you can use the ``SOLIDITY_BUILD_DIR`` environment variable to specify a different location for the build directory. Example: .. code-block:: bash export SOLIDITY_BUILD_DIR=~/solidity/build/ test/cmdlineTests.sh "standard_*" "*_yul_*" --exclude "standard_yul_*" The commands above will run tests from directories starting with ``test/cmdlineTests/standard_`` and subdirectories of ``test/cmdlineTests/`` that have ``_yul_`` somewhere in the name, but no test whose name starts with ``standard_yul_`` will be executed. It will also assume that the file ``solidity/build/solc/solc`` inside your home directory is the compiler binary (unless you are on Windows -- then ``solidity/build/solc/Release/solc.exe``). There are several kinds of command-line tests: - *Standard JSON test*: contains at least an ``input.json`` file. In general may contain: - ``input.json``: input file to be passed to the ``--standard-json`` option on the command line. - ``output.json``: expected Standard JSON output. - ``args``: extra command-line arguments passed to ``solc``. - *CLI test*: contains at least an ``input.*`` file (other than ``input.json``). In general may contain: - ``input.*``: a single input file, whose name will be supplied to ``solc`` on the command line. Usually ``input.sol`` or ``input.yul``. - ``args``: extra command-line arguments passed to ``solc``. - ``stdin``: content to be passed to ``solc`` via standard input. - ``output``: expected content of the standard output. - ``err``: expected content of the standard error output. - ``exit``: expected exit code. If not provided, zero is expected. - *Script test*: contains a ``test.*`` file. In general may contain: - ``test.*``: a single script to run, usually ``test.sh`` or ``test.py``. The script must be executable. Running the Fuzzer via AFL ========================== Fuzzing is a technique that runs programs on more or less random inputs to find exceptional execution states (segmentation faults, exceptions, etc). Modern fuzzers are clever and run a directed search inside the input. We have a specialized binary called ``solfuzzer`` which takes source code as input and fails whenever it encounters an internal compiler error, segmentation fault or similar, but does not fail if e.g., the code contains an error. This way, fuzzing tools can find internal problems in the compiler. We mainly use `AFL `_ for fuzzing. You need to download and install the AFL packages from your repositories (afl, afl-clang) or build them manually. Next, build Solidity (or just the ``solfuzzer`` binary) with AFL as your compiler: .. code-block:: bash cd build # if needed make clean cmake .. -DCMAKE_C_COMPILER=path/to/afl-gcc -DCMAKE_CXX_COMPILER=path/to/afl-g++ make solfuzzer At this stage, you should be able to see a message similar to the following: .. code-block:: text Scanning dependencies of target solfuzzer [ 98%] Building CXX object test/tools/CMakeFiles/solfuzzer.dir/fuzzer.cpp.o afl-cc 2.52b by afl-as 2.52b by [+] Instrumented 1949 locations (64-bit, non-hardened mode, ratio 100%). [100%] Linking CXX executable solfuzzer If the instrumentation messages did not appear, try switching the cmake flags pointing to AFL's clang binaries: .. code-block:: bash # if previously failed make clean cmake .. -DCMAKE_C_COMPILER=path/to/afl-clang -DCMAKE_CXX_COMPILER=path/to/afl-clang++ make solfuzzer Otherwise, upon execution the fuzzer halts with an error saying binary is not instrumented: .. code-block:: text afl-fuzz 2.52b by ... (truncated messages) [*] Validating target binary... [-] Looks like the target binary is not instrumented! The fuzzer depends on compile-time instrumentation to isolate interesting test cases while mutating the input data. For more information, and for tips on how to instrument binaries, please see /usr/share/doc/afl-doc/docs/README. When source code is not available, you may be able to leverage QEMU mode support. Consult the README for tips on how to enable this. (It is also possible to use afl-fuzz as a traditional, "dumb" fuzzer. For that, you can use the -n option - but expect much worse results.) [-] PROGRAM ABORT : No instrumentation detected Location : check_binary(), afl-fuzz.c:6920 Next, you need some example source files. This makes it much easier for the fuzzer to find errors. You can either copy some files from the syntax tests or extract test files from the documentation or the other tests: .. code-block:: bash mkdir /tmp/test_cases cd /tmp/test_cases # extract from tests: path/to/solidity/scripts/isolate_tests.py path/to/solidity/test/libsolidity/SolidityEndToEndTest.cpp # extract from documentation: path/to/solidity/scripts/isolate_tests.py path/to/solidity/docs The AFL documentation states that the corpus (the initial input files) should not be too large. The files themselves should not be larger than 1 kB and there should be at most one input file per functionality, so better start with a small number of. There is also a tool called ``afl-cmin`` that can trim input files that result in similar behavior of the binary. Now run the fuzzer (the ``-m`` extends the size of memory to 60 MB): .. code-block:: bash afl-fuzz -m 60 -i /tmp/test_cases -o /tmp/fuzzer_reports -- /path/to/solfuzzer The fuzzer creates source files that lead to failures in ``/tmp/fuzzer_reports``. Often it finds many similar source files that produce the same error. You can use the tool ``scripts/uniqueErrors.sh`` to filter out the unique errors. Whiskers ======== *Whiskers* is a string templating system similar to `Mustache `_. It is used by the compiler in various places to aid readability, and thus maintainability and verifiability, of the code. The syntax comes with a substantial difference to Mustache. The template markers ``{{`` and ``}}`` are replaced by ``<`` and ``>`` in order to aid parsing and avoid conflicts with :ref:`yul` (The symbols ``<`` and ``>`` are invalid in inline assembly, while ``{`` and ``}`` are used to delimit blocks). Another limitation is that lists are only resolved one depth and they do not recurse. This may change in the future. A rough specification is the following: Any occurrence of ```` is replaced by the string-value of the supplied variable ``name`` without any escaping and without iterated replacements. An area can be delimited by ``<#name>...``. It is replaced by as many concatenations of its contents as there were sets of variables supplied to the template system, each time replacing any ```` items by their respective value. Top-level variables can also be used inside such areas. There are also conditionals of the form ``......``, where template replacements continue recursively either in the first or the second segment depending on the value of the boolean parameter ``name``. If ``......`` is used, then the check is whether the string parameter ``name`` is non-empty. .. _documentation-style: Documentation Style Guide ========================= In the following section you find style recommendations specifically focusing on documentation contributions to Solidity. English Language ---------------- Use International English, unless using project or brand names. Try to reduce the usage of local slang and references, making your language as clear to all readers as possible. Below are some references to help: * `Simplified technical English `_ * `International English `_ .. note:: While the official Solidity documentation is written in English, there are community contributed :ref:`translations` in other languages available. Please refer to the `translation guide `_ for information on how to contribute to the community translations. Title Case for Headings ----------------------- Use `title case `_ for headings. This means capitalise all principal words in titles, but not articles, conjunctions, and prepositions unless they start the title. For example, the following are all correct: * Title Case for Headings. * For Headings Use Title Case. * Local and State Variable Names. * Order of Layout. Expand Contractions ------------------- Use expanded contractions for words, for example: * "Do not" instead of "Don't". * "Can not" instead of "Can't". Active and Passive Voice ------------------------ Active voice is typically recommended for tutorial style documentation as it helps the reader understand who or what is performing a task. However, as the Solidity documentation is a mixture of tutorials and reference content, passive voice is sometimes more applicable. As a summary: * Use passive voice for technical reference, for example language definition and internals of the Ethereum VM. * Use active voice when describing recommendations on how to apply an aspect of Solidity. For example, the below is in passive voice as it specifies an aspect of Solidity: Functions can be declared ``pure`` in which case they promise not to read from or modify the state. For example, the below is in active voice as it discusses an application of Solidity: When invoking the compiler, you can specify how to discover the first element of a path, and also path prefix remappings. Common Terms ------------ * "Function parameters" and "return variables", not input and output parameters. Code Examples ------------- A CI process tests all code block formatted code examples that begin with ``pragma solidity``, ``contract``, ``library`` or ``interface`` using the ``./test/cmdlineTests.sh`` script when you create a PR. If you are adding new code examples, ensure they work and pass tests before creating the PR. Ensure that all code examples begin with a ``pragma`` version that spans the largest where the contract code is valid. For example ``pragma solidity >=0.4.0 <0.9.0;``. Running Documentation Tests --------------------------- Make sure your contributions pass our documentation tests by running ``./docs/docs.sh`` that installs dependencies needed for documentation and checks for any problems such as broken links or syntax issues. .. _solidity_language_design: Solidity Language Design ======================== To actively get involved in the language design process and to share your ideas concerning the future of Solidity, please join the `Solidity forum `_. The Solidity forum serves as the place to propose and discuss new language features and their implementation in the early stages of ideation or modifications of existing features. As soon as proposals get more tangible, their implementation will also be discussed in the `Solidity GitHub repository `_ in the form of issues. In addition to the forum and issue discussions, we regularly host language design discussion calls in which selected topics, issues or feature implementations are debated in detail. The invitation to those calls is shared via the forum. We are also sharing feedback surveys and other content that is relevant to language design in the forum. If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. For ad-hoc cases and questions, you can reach out to us via the `Solidity-dev Gitter channel `_ — a dedicated chatroom for conversations around the Solidity compiler and language development. We are happy to hear your thoughts on how we can improve the language design process to be even more collaborative and transparent. ================================================ FILE: docs/control-structures.rst ================================================ ################################## Expressions and Control Structures ################################## .. index:: ! parameter, parameter;input, parameter;output, function parameter, parameter;function, return variable, variable;return, return .. index:: if, else, while, do/while, for, break, continue, return, switch, goto Control Structures =================== Most of the control structures known from curly-braces languages are available in Solidity: There is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, with the usual semantics known from C or JavaScript. Solidity also supports exception handling in the form of ``try``/``catch``-statements, but only for :ref:`external function calls ` and contract creation calls. Errors can be created using the :ref:`revert statement `. Parentheses can *not* be omitted for conditionals, but curly braces can be omitted around single-statement bodies. Note that there is no type conversion from non-boolean to boolean types as there is in C and JavaScript, so ``if (1) { ... }`` is *not* valid Solidity. .. index:: ! function;call, function;internal, function;external .. _function-calls: Function Calls ============== .. _internal-function-calls: Internal Function Calls ----------------------- Functions of the current contract can be called directly ("internally"), also recursively, as seen in this nonsensical example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; // This will report a warning contract C { function g(uint a) public pure returns (uint ret) { return a + f(); } function f() internal pure returns (uint ret) { return g(7) + f(); } } These function calls are translated into simple jumps inside the EVM. This has the effect that the current memory is not cleared, i.e. passing memory references to internally-called functions is very efficient. Only functions of the same contract instance can be called internally. You should still avoid excessive recursion, as every internal function call uses up at least one stack slot and there are only 1024 slots available. .. _external-function-calls: External Function Calls ----------------------- Functions can also be called using the ``this.g(8);`` and ``c.g(2);`` notation, where ``c`` is a contract instance and ``g`` is a function belonging to ``c``. Calling the function ``g`` via either way results in it being called "externally", using a message call and not directly via jumps. Please note that function calls on ``this`` cannot be used in the constructor, as the actual contract has not been created yet. Functions of other contracts have to be called externally. For an external call, all function arguments have to be copied to memory. .. note:: A function call from one contract to another does not create its own transaction, it is a message call as part of the overall transaction. When calling functions of other contracts, you can specify the amount of Wei or gas sent with the call with the special options ``{value: 10, gas: 10000}``. Note that it is discouraged to specify gas values explicitly, since the gas costs of opcodes can change in the future. Any Wei you send to the contract is added to the total balance of that contract: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; contract InfoFeed { function info() public payable returns (uint ret) { return 42; } } contract Consumer { InfoFeed feed; function setFeed(InfoFeed addr) public { feed = addr; } function callFeed() public { feed.info{value: 10, gas: 800}(); } } You need to use the modifier ``payable`` with the ``info`` function because otherwise, the ``value`` option would not be available. .. warning:: Be careful that ``feed.info{value: 10, gas: 800}`` only locally sets the ``value`` and amount of ``gas`` sent with the function call, and the parentheses at the end perform the actual call. So ``feed.info{value: 10, gas: 800}`` does not call the function and the ``value`` and ``gas`` settings are lost, only ``feed.info{value: 10, gas: 800}()`` performs the function call. .. warning:: Due to the fact that the EVM considers a call to a non-existing contract to always succeed, Solidity uses the ``extcodesize`` opcode to check that the contract that is about to be called actually exists (it contains code) and causes an exception if it does not. This check is skipped if the return data will be decoded after the call and thus the ABI decoder will catch the case of a non-existing contract. This check is not performed in case of :ref:`low-level calls ` which operate on addresses rather than contract instances. .. warning:: Be careful when using high-level calls to :ref:`precompiled contracts `, since the compiler considers them non-existing according to the above logic even though they execute code and can return data. .. note:: Since the version 0.8.10, the compiler does not check ``extcodesize`` on high-level external calls if return data is expected, because an empty code will be unable to return data, and the ABI decoder will revert. As a consequence, this allows high-level external calls to precompiled contracts, since they can return data despite having no code associated with their addresses. Read about :ref:`precompiled contracts ` and :ref:`low-level calls ` for more information. Function calls also cause exceptions if the called contract itself throws an exception or goes out of gas. .. warning:: Any interaction with another contract imposes a potential danger, especially if the source code of the contract is not known in advance. The current contract hands over control to the called contract and that may potentially do just about anything. Even if the called contract inherits from a known parent contract, the inheriting contract is only required to have a correct interface. The implementation of the contract, however, can be completely arbitrary and thus, pose a danger. In addition, be prepared in case it calls into other contracts of your system or even back into the calling contract before the first call returns. This means that the called contract can change state variables of the calling contract via its functions. Write your functions in a way that, for example, calls to external functions happen after any changes to state variables in your contract so your contract is not vulnerable to a reentrancy exploit. .. note:: Before Solidity 0.6.2, the recommended way to specify the value and gas was to use ``f.value(x).gas(g)()``. This was deprecated in Solidity 0.6.2 and is no longer possible since Solidity 0.7.0. Function Calls with Named Parameters ------------------------------------ Function call arguments can be given by name, in any order, if they are enclosed in ``{ }`` as can be seen in the following example. The argument list has to coincide by name with the list of parameters from the function declaration, but can be in arbitrary order. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract C { mapping(uint => uint) data; function f() public { set({value: 2, key: 3}); } function set(uint key, uint value) public { data[key] = value; } } Omitted Names in Function Definitions ------------------------------------- The names of parameters and return values in the function declaration can be omitted. Those items with omitted names will still be present on the stack, but they are inaccessible by name. An omitted return value name can still return a value to the caller by use of the ``return`` statement. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract C { // omitted name for parameter function func(uint k, uint) public pure returns(uint) { return k; } } .. index:: ! new, contracts;creating .. _creating-contracts: Creating Contracts via ``new`` ============================== A contract can create other contracts using the ``new`` keyword. The full code of the contract being created has to be known when the creating contract is compiled so recursive creation-dependencies are not possible. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract D { uint public x; constructor(uint a) payable { x = a; } } contract C { D d = new D(4); // will be executed as part of C's constructor function createD(uint arg) public { D newD = new D(arg); newD.x(); } function createAndEndowD(uint arg, uint amount) public payable { // Send ether along with the creation D newD = new D{value: amount}(arg); newD.x(); } } As seen in the example, it is possible to send Ether while creating an instance of ``D`` using the ``value`` option, but it is not possible to limit the amount of gas. If the creation fails (due to out-of-stack, not enough balance or other problems), an exception is thrown. .. _salted-contract-creations: Salted contract creations / create2 ----------------------------------- When creating a contract, the address of the contract is computed from the address of the creating contract and a counter that is increased with each contract creation. If you specify the option ``salt`` (a bytes32 value), then contract creation will use a different mechanism to come up with the address of the new contract: It will compute the address from the address of the creating contract, the given salt value, the (creation) bytecode of the created contract and the constructor arguments. In particular, the counter ("nonce") is not used. This allows for more flexibility in creating contracts: You are able to derive the address of the new contract before it is created. Furthermore, you can rely on this address also in case the creating contracts creates other contracts in the meantime. The main use-case here is contracts that act as judges for off-chain interactions, which only need to be created if there is a dispute. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract D { uint public x; constructor(uint a) { x = a; } } contract C { function createDSalted(bytes32 salt, uint arg) public { // This complicated expression just tells you how the address // can be pre-computed. It is just there for illustration. // You actually only need ``new D{salt: salt}(arg)``. address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked( bytes1(0xff), address(this), salt, keccak256(abi.encodePacked( type(D).creationCode, abi.encode(arg) )) ))))); D d = new D{salt: salt}(arg); require(address(d) == predictedAddress); } } .. warning:: There are some peculiarities in relation to salted creation. A contract can be re-created at the same address after having been destroyed. Yet, it is possible for that newly created contract to have a different deployed bytecode even though the creation bytecode has been the same (which is a requirement because otherwise the address would change). This is due to the fact that the constructor can query external state that might have changed between the two creations and incorporate that into the deployed bytecode before it is stored. Order of Evaluation of Expressions ================================== The evaluation order of expressions is not specified (more formally, the order in which the children of one node in the expression tree are evaluated is not specified, but they are of course evaluated before the node itself). It is only guaranteed that statements are executed in order and short-circuiting for boolean expressions is done. .. index:: ! assignment Assignment ========== .. index:: ! assignment;destructuring Destructuring Assignments and Returning Multiple Values ------------------------------------------------------- Solidity internally allows tuple types, i.e. a list of objects of potentially different types whose number is a constant at compile-time. Those tuples can be used to return multiple values at the same time. These can then either be assigned to newly declared variables or to pre-existing variables (or LValues in general). Tuples are not proper types in Solidity, they can only be used to form syntactic groupings of expressions. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; contract C { uint index; function f() public pure returns (uint, bool, uint) { return (7, true, 2); } function g() public { // Variables declared with type and assigned from the returned tuple, // not all elements have to be specified (but the number must match). (uint x, , uint y) = f(); // Common trick to swap values -- does not work for non-value storage types. (x, y) = (y, x); // Components can be left out (also for variable declarations). (index, , ) = f(); // Sets the index to 7 } } It is not possible to mix variable declarations and non-declaration assignments, i.e. the following is not valid: ``(x, uint y) = (1, 2);`` .. note:: Prior to version 0.5.0 it was possible to assign to tuples of smaller size, either filling up on the left or on the right side (which ever was empty). This is now disallowed, so both sides have to have the same number of components. .. warning:: Be careful when assigning to multiple variables at the same time when reference types are involved, because it could lead to unexpected copying behavior. Complications for Arrays and Structs ------------------------------------ The semantics of assignments are more complicated for non-value types like arrays and structs, including ``bytes`` and ``string``, see :ref:`Data location and assignment behavior ` for details. In the example below the call to ``g(x)`` has no effect on ``x`` because it creates an independent copy of the storage value in memory. However, ``h(x)`` successfully modifies ``x`` because only a reference and not a copy is passed. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; contract C { uint[20] x; function f() public { g(x); h(x); } function g(uint[20] memory y) internal pure { y[2] = 3; } function h(uint[20] storage y) internal { y[3] = 4; } } .. index:: ! scoping, declarations, default value .. _default-value: Scoping and Declarations ======================== A variable which is declared will have an initial default value whose byte-representation is all zeros. The "default values" of variables are the typical "zero-state" of whatever the type is. For example, the default value for a ``bool`` is ``false``. The default value for the ``uint`` or ``int`` types is ``0``. For statically-sized arrays and ``bytes1`` to ``bytes32``, each individual element will be initialized to the default value corresponding to its type. For dynamically-sized arrays, ``bytes`` and ``string``, the default value is an empty array or string. For the ``enum`` type, the default value is its first member. Scoping in Solidity follows the widespread scoping rules of C99 (and many other languages): Variables are visible from the point right after their declaration until the end of the smallest ``{ }``-block that contains the declaration. As an exception to this rule, variables declared in the initialization part of a for-loop are only visible until the end of the for-loop. Variables that are parameter-like (function parameters, modifier parameters, catch parameters, ...) are visible inside the code block that follows - the body of the function/modifier for a function and modifier parameter and the catch block for a catch parameter. Variables and other items declared outside of a code block, for example functions, contracts, user-defined types, etc., are visible even before they were declared. This means you can use state variables before they are declared and call functions recursively. As a consequence, the following examples will compile without warnings, since the two variables have the same name but disjoint scopes. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; contract C { function minimalScoping() pure public { { uint same; same = 1; } { uint same; same = 3; } } } As a special example of the C99 scoping rules, note that in the following, the first assignment to ``x`` will actually assign the outer and not the inner variable. In any case, you will get a warning about the outer variable being shadowed. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; // This will report a warning contract C { function f() pure public returns (uint) { uint x = 1; { x = 2; // this will assign to the outer variable uint x; } return x; // x has value 2 } } .. warning:: Before version 0.5.0 Solidity followed the same scoping rules as JavaScript, that is, a variable declared anywhere within a function would be in scope for the entire function, regardless where it was declared. The following example shows a code snippet that used to compile but leads to an error starting from version 0.5.0. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; // This will not compile contract C { function f() pure public returns (uint) { x = 2; uint x; return x; } } .. index:: ! safe math, safemath, checked, unchecked .. _unchecked: Checked or Unchecked Arithmetic =============================== An overflow or underflow is the situation where the resulting value of an arithmetic operation, when executed on an unrestricted integer, falls outside the range of the result type. Prior to Solidity 0.8.0, arithmetic operations would always wrap in case of under- or overflow leading to widespread use of libraries that introduce additional checks. Since Solidity 0.8.0, all arithmetic operations revert on over- and underflow by default, thus making the use of these libraries unnecessary. To obtain the previous behavior, an ``unchecked`` block can be used: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; contract C { function f(uint a, uint b) pure public returns (uint) { // This subtraction will wrap on underflow. unchecked { return a - b; } } function g(uint a, uint b) pure public returns (uint) { // This subtraction will revert on underflow. return a - b; } } The call to ``f(2, 3)`` will return ``2**256-1``, while ``g(2, 3)`` will cause a failing assertion. The ``unchecked`` block can be used everywhere inside a block, but not as a replacement for a block. It also cannot be nested. The setting only affects the statements that are syntactically inside the block. Functions called from within an ``unchecked`` block do not inherit the property. .. note:: To avoid ambiguity, you cannot use ``_;`` inside an ``unchecked`` block. The following operators will cause a failing assertion on overflow or underflow and will wrap without an error if used inside an unchecked block: ``++``, ``--``, ``+``, binary ``-``, unary ``-``, ``*``, ``/``, ``%``, ``**`` ``+=``, ``-=``, ``*=``, ``/=``, ``%=`` .. warning:: It is not possible to disable the check for division by zero or modulo by zero using the ``unchecked`` block. .. note:: Bitwise operators do not perform overflow or underflow checks. This is particularly visible when using bitwise shifts (``<<``, ``>>``, ``<<=``, ``>>=``) in place of integer division and multiplication by a power of 2. For example ``type(uint256).max << 3`` does not revert even though ``type(uint256).max * 8`` would. .. note:: The second statement in ``int x = type(int).min; -x;`` will result in an overflow because the negative range can hold one more value than the positive range. Explicit type conversions will always truncate and never cause a failing assertion with the exception of a conversion from an integer to an enum type. .. index:: ! exception, ! throw, ! assert, ! require, ! revert, ! errors .. _assert-and-require: Error handling: Assert, Require, Revert and Exceptions ====================================================== Solidity uses state-reverting exceptions to handle errors. Such an exception undoes all changes made to the state in the current call (and all its sub-calls) and flags an error to the caller. When exceptions happen in a sub-call, they "bubble up" (i.e., exceptions are rethrown) automatically unless they are caught in a ``try/catch`` statement. Exceptions to this rule are ``send`` and the low-level functions ``call``, ``delegatecall`` and ``staticcall``: they return ``false`` as their first return value in case of an exception instead of "bubbling up". .. warning:: The low-level functions ``call``, ``delegatecall`` and ``staticcall`` return ``true`` as their first return value if the account called is non-existent, as part of the design of the EVM. Account existence must be checked prior to calling if needed. Exceptions can contain error data that is passed back to the caller in the form of :ref:`error instances `. The built-in errors ``Error(string)`` and ``Panic(uint256)`` are used by special functions, as explained below. ``Error`` is used for "regular" error conditions while ``Panic`` is used for errors that should not be present in bug-free code. .. _assert-and-require-statements: Panic via ``assert`` and Error via ``require`` ---------------------------------------------- The convenience functions ``assert`` and ``require`` can be used to check for conditions and throw an exception if the condition is not met. The ``assert`` function creates an error of type ``Panic(uint256)``. The same error is created by the compiler in certain situations as listed below. Assert should only be used to test for internal errors, and to check invariants. Properly functioning code should never create a Panic, not even on invalid external input. If this happens, then there is a bug in your contract which you should fix. Language analysis tools can evaluate your contract to identify the conditions and function calls which will cause a Panic. A Panic exception is generated in the following situations. The error code supplied with the error data indicates the kind of panic. #. 0x00: Used for generic compiler inserted panics. #. 0x01: If you call ``assert`` with an argument that evaluates to false. #. 0x11: If an arithmetic operation results in underflow or overflow outside of an ``unchecked { ... }`` block. #. 0x12; If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``). #. 0x21: If you convert a value that is too big or negative into an enum type. #. 0x22: If you access a storage byte array that is incorrectly encoded. #. 0x31: If you call ``.pop()`` on an empty array. #. 0x32: If you access an array, ``bytesN`` or an array slice at an out-of-bounds or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``). #. 0x41: If you allocate too much memory or create an array that is too large. #. 0x51: If you call a zero-initialized variable of internal function type. The ``require`` function provides three overloads: 1. ``require(bool)`` which will revert without any data (not even an error selector). 2. ``require(bool, string)`` which will revert with an ``Error(string)``. 3. ``require(bool, error)`` which will revert with the custom, user supplied error provided as the second argument. .. note:: ``require`` arguments are evaluated unconditionally, so take special care to make sure that they are not expressions with unexpected side-effects. For example, in ``require(condition, CustomError(f()));`` and ``require(condition, f());``, function ``f()`` will be called regardless of whether the supplied condition is ``true`` or ``false``. An ``Error(string)`` exception (or an exception without data) is generated by the compiler in the following situations: #. Calling ``require(x)`` where ``x`` evaluates to ``false``. #. If you use ``revert()`` or ``revert("description")``. #. If you perform an external function call targeting a contract that contains no code. #. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function). #. If your contract receives Ether via a public getter function. For the following cases, the error data from the external call (if provided) is forwarded. This means that it can either cause an ``Error`` or a ``Panic`` (or whatever else was given): #. If a ``.transfer()`` fails. #. If you call a function via a message call but it does not finish properly (i.e., it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall``, ``callcode`` or ``staticcall`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``. #. If you create a contract using the ``new`` keyword but the contract creation :ref:`does not finish properly`. You can optionally provide a message string or a custom error to ``require``, but not to ``assert``. .. note:: If you do not provide a string or custom error argument to ``require``, it will revert with empty error data, not even including the error selector. The following example shows how you can use ``require`` to check conditions on inputs and ``assert`` for internal error checking. .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; contract Sharer { function sendHalf(address payable addr) public payable returns (uint balance) { require(msg.value % 2 == 0, "Even value required."); uint balanceBeforeTransfer = address(this).balance; (bool success, ) = addr.call{value: msg.value / 2}(""); require(success); // Since require will stop execution and revert if success is false, // there should be no way for us to still have half of the Ether. assert(address(this).balance == balanceBeforeTransfer - msg.value / 2); return address(this).balance; } } Internally, Solidity performs a revert operation (instruction ``0xfd``). This causes the EVM to revert all changes made to the state. The reason for reverting is that there is no safe way to continue execution, because an expected effect did not occur. Because we want to keep the atomicity of transactions, the safest action is to revert all changes and make the whole transaction (or at least call) without effect. In both cases, the caller can react on such failures using ``try``/``catch``, but the changes in the callee will always be reverted. .. note:: Panic exceptions used to use the ``invalid`` opcode before Solidity 0.8.0, which consumed all gas available to the call. Exceptions that use ``require`` used to consume all gas until before the Metropolis release. .. _revert-statement: ``revert`` ---------- A direct revert can be triggered using the ``revert`` statement and the ``revert`` function. The ``revert`` statement takes a custom error as direct argument without parentheses: revert CustomError(arg1, arg2); For backward-compatibility reasons, there is also the ``revert()`` function, which uses parentheses and accepts a string: revert(); revert("description"); The error data will be passed back to the caller and can be caught there. Using ``revert()`` causes a revert without any error data while ``revert("description")`` will create an ``Error(string)`` error. Using a custom error instance will usually be much cheaper than a string description, because you can use the name of the error to describe it, which is encoded in only four bytes. A longer description can be supplied via NatSpec which does not incur any costs. The following example shows how to use an error string and a custom error instance together with ``revert`` and the equivalent ``require``: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract VendingMachine { address owner; error Unauthorized(); function buy(uint amount) public payable { if (amount > msg.value / 2 ether) revert("Not enough Ether provided."); // Alternative way to do it: require( amount <= msg.value / 2 ether, "Not enough Ether provided." ); // Perform the purchase. } function withdraw() public { if (msg.sender != owner) revert Unauthorized(); (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); require(success); } } The two ways ``if (!condition) revert(...);`` and ``require(condition, ...);`` are equivalent as long as the arguments to ``revert`` and ``require`` do not have side-effects, for example if they are just strings. .. note:: The ``require`` function is evaluated just as any other function. This means that all arguments are evaluated before the function itself is executed. In particular, in ``require(condition, f())`` the function ``f`` is executed even if ``condition`` is true. The provided string is :ref:`abi-encoded ` as if it were a call to a function ``Error(string)``. In the above example, ``revert("Not enough Ether provided.");`` returns the following hexadecimal as error return data: .. code:: 0x08c379a0 // Function selector for Error(string) 0x0000000000000000000000000000000000000000000000000000000000000020 // Data offset 0x000000000000000000000000000000000000000000000000000000000000001a // String length 0x4e6f7420656e6f7567682045746865722070726f76696465642e000000000000 // String data The provided message can be retrieved by the caller using ``try``/``catch`` as shown below. .. note:: There used to be a keyword called ``throw`` with the same semantics as ``revert()`` which was deprecated in version 0.4.13 and removed in version 0.5.0. .. _try-catch: ``try``/``catch`` ----------------- A failure in an external call can be caught using a try/catch statement, as follows: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.1; interface DataFeed { function getData(address token) external returns (uint value); } contract FeedConsumer { DataFeed feed; uint errorCount; function rate(address token) public returns (uint value, bool success) { // Permanently disable the mechanism if there are // more than 10 errors. require(errorCount < 10); try feed.getData(token) returns (uint v) { return (v, true); } catch Error(string memory /*reason*/) { // This is executed in case // revert was called inside getData // and a reason string was provided. errorCount++; return (0, false); } catch Panic(uint /*errorCode*/) { // This is executed in case of a panic, // i.e. a serious error like division by zero // or overflow. The error code can be used // to determine the kind of error. errorCount++; return (0, false); } catch (bytes memory /*lowLevelData*/) { // This is executed in case revert() was used. errorCount++; return (0, false); } } } The ``try`` keyword has to be followed by an expression representing an external function call or a contract creation (``new ContractName()``). Errors inside the expression are not caught (for example if it is a complex expression that also involves internal function calls), only a revert happening inside the external call itself. The ``returns`` part (which is optional) that follows declares return variables matching the types returned by the external call. In case there was no error, these variables are assigned and the contract's execution continues inside the first success block. If the end of the success block is reached, execution continues after the ``catch`` blocks. Solidity supports different kinds of catch blocks depending on the type of error: - ``catch Error(string memory reason) { ... }``: This catch clause is executed if the error was caused by ``revert("reasonString")`` or ``require(false, "reasonString")`` (or an internal error that causes such an exception). - ``catch Panic(uint errorCode) { ... }``: If the error was caused by a panic, i.e. by a failing ``assert``, division by zero, invalid array access, arithmetic overflow and others, this catch clause will be run. - ``catch (bytes memory lowLevelData) { ... }``: This clause is executed if the error signature does not match any other clause, if there was an error while decoding the error message, or if no error data was provided with the exception. The declared variable provides access to the low-level error data in that case. - ``catch { ... }``: If you are not interested in the error data, you can just use ``catch { ... }`` (even as the only catch clause) instead of the previous clause. It is planned to support other types of error data in the future. The strings ``Error`` and ``Panic`` are currently parsed as is and are not treated as identifiers. In order to catch all error cases, you have to have at least the clause ``catch { ...}`` or the clause ``catch (bytes memory lowLevelData) { ... }``. The variables declared in the ``returns`` and the ``catch`` clause are only in scope in the block that follows. .. note:: If an error happens during the decoding of the return data inside a try/catch-statement, this causes an exception in the currently executing contract and because of that, it is not caught in the catch clause. If there is an error during decoding of ``catch Error(string memory reason)`` and there is a low-level catch clause, this error is caught there. .. note:: If execution reaches a catch-block, then the state-changing effects of the external call have been reverted. If execution reaches the success block, the effects were not reverted. If the effects have been reverted, then execution either continues in a catch block or the execution of the try/catch statement itself reverts (for example due to decoding failures as noted above or due to not providing a low-level catch clause). .. note:: The reason behind a failed call can be manifold. Do not assume that the error message is coming directly from the called contract: The error might have happened deeper down in the call chain and the called contract just forwarded it. Also, it could be due to an out-of-gas situation and not a deliberate error condition: The caller always retains at least 1/64th of the gas in a call and thus even if the called contract goes out of gas, the caller still has some gas left. ================================================ FILE: docs/credits-and-attribution.rst ================================================ .. This page is meant to be linked to from the footer. :orphan: ####################### Credits and Attribution ####################### Website icons ============= .. |icon-share-solid| image:: _static/img/solid-share-arrow.svg .. _share icon: https://fontawesome.com/v5.15/icons/share?style=solid .. _Font Awesome Free License: https://fontawesome.com/license/free +-------------------------+-----------------------------------------------------------------------+ | Icon | Attribution | +=========================+=======================================================================+ | |icon-share-solid| | - Source: `share icon`_ from Font Awesome 5.15.0. | | | - License: `Font Awesome Free License`_ (CC BY 4.0). | +-------------------------+-----------------------------------------------------------------------+ ================================================ FILE: docs/docs.sh ================================================ #!/usr/bin/env bash #------------------------------------------------------------------------------ # Bash script to build the Solidity Sphinx documentation locally. # # The documentation for solidity is hosted at: # # https://docs.soliditylang.org # # ------------------------------------------------------------------------------ # This file is part of solidity. # # solidity is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # solidity is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with solidity. If not, see # # (c) 2016 solidity contributors. #------------------------------------------------------------------------------ set -euo pipefail script_dir="$(dirname "$0")" cd "${script_dir}" # TODO `--ignore-installed` now fixes an issue where pip tries to uninstall a Debian installed package, but is unable to # TODO since Debian has decided to not use the RECORD file, which then breaks pip. # TODO https://github.com/pypa/pip/issues/11631 and https://bugs.launchpad.net/ubuntu/+source/wheel/+bug/2063151 pip3 install -r requirements.txt --ignore-installed --upgrade --upgrade-strategy eager sphinx-build -nW -b html -d _build/doctrees . _build/html ================================================ FILE: docs/examples/blind-auction.rst ================================================ .. index:: auction;blind, auction;open, blind auction, open auction ************* Blind Auction ************* In this section, we will show how easy it is to create a completely blind auction contract on Ethereum. We will start with an open auction where everyone can see the bids that are made and then extend this contract into a blind auction where it is not possible to see the actual bid until the bidding period ends. .. _simple_auction: Simple Open Auction =================== The general idea of the following simple auction contract is that everyone can send their bids during a bidding period. The bids already include sending some compensation, e.g. Ether, in order to bind the bidders to their bid. If the highest bid is raised, the previous highest bidder gets their Ether back. After the end of the bidding period, the contract has to be called manually for the beneficiary to receive their Ether - contracts cannot activate themselves. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract SimpleAuction { // Parameters of the auction. Times are either // absolute unix timestamps (seconds since 1970-01-01) // or time periods in seconds. address payable public beneficiary; uint public auctionEndTime; // Current state of the auction. address public highestBidder; uint public highestBid; // Allowed withdrawals of previous bids mapping(address => uint) pendingReturns; // Set to true at the end, disallows any change. // By default initialized to `false`. bool ended; // Events that will be emitted on changes. event HighestBidIncreased(address bidder, uint amount); event AuctionEnded(address winner, uint amount); // Errors that describe failures. // The triple-slash comments are so-called natspec // comments. They will be shown when the user // is asked to confirm a transaction or // when an error is displayed. /// The auction has already ended. error AuctionAlreadyEnded(); /// There is already a higher or equal bid. error BidNotHighEnough(uint highestBid); /// The auction has not ended yet. error AuctionNotYetEnded(); /// The function auctionEnd has already been called. error AuctionEndAlreadyCalled(); /// Create a simple auction with `biddingTime` /// seconds bidding time on behalf of the /// beneficiary address `beneficiaryAddress`. constructor( uint biddingTime, address payable beneficiaryAddress ) { beneficiary = beneficiaryAddress; auctionEndTime = block.timestamp + biddingTime; } /// Bid on the auction with the value sent /// together with this transaction. /// The value will only be refunded if the /// auction is not won. function bid() external payable { // No arguments are necessary, all // information is already part of // the transaction. The keyword payable // is required for the function to // be able to receive Ether. // Revert the call if the bidding // period is over. if (block.timestamp > auctionEndTime) revert AuctionAlreadyEnded(); // If the bid is not higher, send the // Ether back (the revert statement // will revert all changes in this // function execution including // it having received the Ether). if (msg.value <= highestBid) revert BidNotHighEnough(highestBid); if (highestBid != 0) { // Sending back the Ether by simply using // highestBidder.send(highestBid) is a security risk // because it could execute an untrusted contract. // It is always safer to let the recipients // withdraw their Ether themselves. pendingReturns[highestBidder] += highestBid; } highestBidder = msg.sender; highestBid = msg.value; emit HighestBidIncreased(msg.sender, msg.value); } /// Withdraw a bid that was overbid. function withdraw() external returns (bool) { uint amount = pendingReturns[msg.sender]; if (amount > 0) { // It is important to set this to zero because the recipient // can call this function again as part of the receiving call // before `call` returns. pendingReturns[msg.sender] = 0; // msg.sender is not of type `address payable` and must be // explicitly converted using `payable(msg.sender)` in order // use the member function `call()`. (bool success, ) = payable(msg.sender).call{value: amount}(""); if (!success) { // No need to call throw here, just reset the amount owing pendingReturns[msg.sender] = amount; return false; } } return true; } /// End the auction and send the highest bid /// to the beneficiary. function auctionEnd() external { // It is a good guideline to structure functions that interact // with other contracts (i.e. they call functions or send Ether) // into three phases: // 1. checking conditions // 2. performing actions (potentially changing conditions) // 3. interacting with other contracts // If these phases are mixed up, the other contract could call // back into the current contract and modify the state or cause // effects (ether payout) to be performed multiple times. // If functions called internally include interaction with external // contracts, they also have to be considered interaction with // external contracts. // 1. Conditions if (block.timestamp < auctionEndTime) revert AuctionNotYetEnded(); if (ended) revert AuctionEndAlreadyCalled(); // 2. Effects ended = true; emit AuctionEnded(highestBidder, highestBid); // 3. Interaction (bool success, ) = beneficiary.call{value: highestBid}(""); require(success); } } Blind Auction ============= The previous open auction is extended to a blind auction in the following. The advantage of a blind auction is that there is no time pressure towards the end of the bidding period. Creating a blind auction on a transparent computing platform might sound like a contradiction, but cryptography comes to the rescue. During the **bidding period**, a bidder does not actually send their bid, but only a hashed version of it. Since it is currently considered practically impossible to find two (sufficiently long) values whose hash values are equal, the bidder commits to the bid by that. After the end of the bidding period, the bidders have to reveal their bids: They send their values unencrypted, and the contract checks that the hash value is the same as the one provided during the bidding period. Another challenge is how to make the auction **binding and blind** at the same time: The only way to prevent the bidder from just not sending the Ether after they won the auction is to make them send it together with the bid. Since value transfers cannot be blinded in Ethereum, anyone can see the value. The following contract solves this problem by accepting any value that is larger than the highest bid. Since this can of course only be checked during the reveal phase, some bids might be **invalid**, and this is on purpose (it even provides an explicit flag to place invalid bids with high-value transfers): Bidders can confuse competition by placing several high or low invalid bids. .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract BlindAuction { struct Bid { bytes32 blindedBid; uint deposit; } address payable public beneficiary; uint public biddingEnd; uint public revealEnd; bool public ended; mapping(address => Bid[]) public bids; address public highestBidder; uint public highestBid; // Allowed withdrawals of previous bids mapping(address => uint) pendingReturns; event AuctionEnded(address winner, uint highestBid); // Errors that describe failures. /// The function has been called too early. /// Try again at `time`. error TooEarly(uint time); /// The function has been called too late. /// It cannot be called after `time`. error TooLate(uint time); /// The function auctionEnd has already been called. error AuctionEndAlreadyCalled(); // Modifiers are a convenient way to validate inputs to // functions. `onlyBefore` is applied to `bid` below: // The new function body is the modifier's body where // `_` is replaced by the old function body. modifier onlyBefore(uint time) { if (block.timestamp >= time) revert TooLate(time); _; } modifier onlyAfter(uint time) { if (block.timestamp <= time) revert TooEarly(time); _; } constructor( uint biddingTime, uint revealTime, address payable beneficiaryAddress ) { beneficiary = beneficiaryAddress; biddingEnd = block.timestamp + biddingTime; revealEnd = biddingEnd + revealTime; } /// Place a blinded bid with `blindedBid` = /// keccak256(abi.encodePacked(value, fake, secret)). /// The sent ether is only refunded if the bid is correctly /// revealed in the revealing phase. The bid is valid if the /// ether sent together with the bid is at least "value" and /// "fake" is not true. Setting "fake" to true and sending /// not the exact amount are ways to hide the real bid but /// still make the required deposit. The same address can /// place multiple bids. function bid(bytes32 blindedBid) external payable onlyBefore(biddingEnd) { bids[msg.sender].push(Bid({ blindedBid: blindedBid, deposit: msg.value })); } /// Reveal your blinded bids. You will get a refund for all /// correctly blinded invalid bids and for all bids except for /// the totally highest. function reveal( uint[] calldata values, bool[] calldata fakes, bytes32[] calldata secrets ) external onlyAfter(biddingEnd) onlyBefore(revealEnd) { uint length = bids[msg.sender].length; require(values.length == length); require(fakes.length == length); require(secrets.length == length); uint refund; for (uint i = 0; i < length; i++) { Bid storage bidToCheck = bids[msg.sender][i]; (uint value, bool fake, bytes32 secret) = (values[i], fakes[i], secrets[i]); if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) { // Bid was not actually revealed. // Do not refund deposit. continue; } refund += bidToCheck.deposit; if (!fake && bidToCheck.deposit >= value) { if (placeBid(msg.sender, value)) refund -= value; } // Make it impossible for the sender to re-claim // the same deposit. bidToCheck.blindedBid = bytes32(0); } (bool success, ) = payable(msg.sender).call{value: refund}(""); require(success); } /// Withdraw a bid that was overbid. function withdraw() external { uint amount = pendingReturns[msg.sender]; if (amount > 0) { // It is important to set this to zero because the recipient // can call this function again as part of the receiving call // before `call` returns (see the remark above about // conditions -> effects -> interaction). pendingReturns[msg.sender] = 0; (bool success, ) = payable(msg.sender).call{value: amount}(""); require(success); } } /// End the auction and send the highest bid /// to the beneficiary. function auctionEnd() external onlyAfter(revealEnd) { if (ended) revert AuctionEndAlreadyCalled(); emit AuctionEnded(highestBidder, highestBid); ended = true; (bool success, ) = beneficiary.call{value: highestBid}(""); require(success); } // This is an "internal" function which means that it // can only be called from the contract itself (or from // derived contracts). function placeBid(address bidder, uint value) internal returns (bool success) { if (value <= highestBid) { return false; } if (highestBidder != address(0)) { // Refund the previously highest bidder. pendingReturns[highestBidder] += highestBid; } highestBid = value; highestBidder = bidder; return true; } } ================================================ FILE: docs/examples/micropayment.rst ================================================ ******************** Micropayment Channel ******************** In this section, we will learn how to build an example implementation of a payment channel. It uses cryptographic signatures to make repeated transfers of Ether between the same parties secure, instantaneous, and without transaction fees. For the example, we need to understand how to sign and verify signatures, and setup the payment channel. Creating and verifying signatures ================================= Imagine Alice wants to send some Ether to Bob, i.e. Alice is the sender and Bob is the recipient. Alice only needs to send cryptographically signed messages off-chain (e.g. via email) to Bob and it is similar to writing checks. Alice and Bob use signatures to authorize transactions, which is possible with smart contracts on Ethereum. Alice will build a simple smart contract that lets her transmit Ether, but instead of calling a function herself to initiate a payment, she will let Bob do that, and therefore pay the transaction fee. The contract will work as follows: 1. Alice deploys the ``ReceiverPays`` contract, attaching enough Ether to cover the payments that will be made. 2. Alice authorizes a payment by signing a message with her private key. 3. Alice sends the cryptographically signed message to Bob. The message does not need to be kept secret (explained later), and the mechanism for sending it does not matter. 4. Bob claims his payment by presenting the signed message to the smart contract, it verifies the authenticity of the message and then releases the funds. Creating the signature ---------------------- Alice does not need to interact with the Ethereum network to sign the transaction, the process is completely offline. In this tutorial, we will sign messages in the browser using `web3.js `_ and `MetaMask `_, using the method described in `EIP-712 `_, as it provides a number of other security benefits. .. code-block:: javascript /// Hashing first makes things easier var hash = web3.utils.sha3("message to sign"); web3.eth.personal.sign(hash, web3.eth.defaultAccount, function () { console.log("Signed"); }); .. note:: The ``web3.eth.personal.sign`` prepends the length of the message to the signed data. Since we hash first, the message will always be exactly 32 bytes long, and thus this length prefix is always the same. What to Sign ------------ For a contract that fulfills payments, the signed message must include: 1. The recipient's address. 2. The amount to be transferred. 3. Protection against replay attacks. A replay attack is when a signed message is reused to claim authorization for a second action. To avoid replay attacks we use the same technique as in Ethereum transactions themselves, a so-called nonce, which is the number of transactions sent by an account. The smart contract checks if a nonce is used multiple times. Another type of replay attack can occur when the owner deploys a ``ReceiverPays`` smart contract, makes some payments, and then destroys the contract. Later, they decide to deploy the ``RecipientPays`` smart contract again, but the new contract does not know the nonces used in the previous deployment, so the attacker can use the old messages again. Alice can protect against this attack by including the contract's address in the message, and only messages containing the contract's address itself will be accepted. You can find an example of this in the first two lines of the ``claimPayment()`` function of the full contract at the end of this section. Furthermore, instead of destroying the contract by calling ``selfdestruct``, which is currently deprecated, we will disable the contract's functionalities by freezing it, resulting in the reversion of any call after it being frozen. Packing arguments ----------------- Now that we have identified what information to include in the signed message, we are ready to put the message together, hash it, and sign it. For simplicity, we concatenate the data. The `ethereumjs-abi `_ library provides a function called ``soliditySHA3`` that mimics the behavior of Solidity's ``keccak256`` function applied to arguments encoded using ``abi.encodePacked``. Here is a JavaScript function that creates the proper signature for the ``ReceiverPays`` example: .. code-block:: javascript // recipient is the address that should be paid. // amount, in wei, specifies how much ether should be sent. // nonce can be any unique number to prevent replay attacks // contractAddress is used to prevent cross-contract replay attacks function signPayment(recipient, amount, nonce, contractAddress, callback) { var hash = "0x" + abi.soliditySHA3( ["address", "uint256", "uint256", "address"], [recipient, amount, nonce, contractAddress] ).toString("hex"); web3.eth.personal.sign(hash, web3.eth.defaultAccount, callback); } Recovering the Message Signer in Solidity ----------------------------------------- In general, ECDSA signatures consist of two parameters, ``r`` and ``s``. Signatures in Ethereum include a third parameter called ``v``, that you can use to verify which account's private key was used to sign the message, and the transaction's sender. Solidity provides a built-in function :ref:`ecrecover ` that accepts a message along with the ``r``, ``s`` and ``v`` parameters and returns the address that was used to sign the message. Extracting the Signature Parameters ----------------------------------- Signatures produced by web3.js are the concatenation of ``r``, ``s`` and ``v``, so the first step is to split these parameters apart. You can do this on the client-side, but doing it inside the smart contract means you only need to send one signature parameter rather than three. Splitting apart a byte array into its constituent parts is a mess, so we use :doc:`inline assembly ` to do the job in the ``splitSignature`` function (the third function in the full contract at the end of this section). Computing the Message Hash -------------------------- The smart contract needs to know exactly what parameters were signed, and so it must recreate the message from the parameters and use that for signature verification. The functions ``prefixed`` and ``recoverSigner`` do this in the ``claimPayment`` function. The full contract ----------------- .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Owned { address payable owner; constructor() { owner = payable(msg.sender); } } contract Freezable is Owned { bool private _frozen = false; modifier notFrozen() { require(!_frozen, "Inactive Contract."); _; } function freeze() internal { if (msg.sender == owner) _frozen = true; } } contract ReceiverPays is Freezable { mapping(uint256 => bool) usedNonces; constructor() payable {} function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) external notFrozen { require(!usedNonces[nonce]); usedNonces[nonce] = true; // this recreates the message that was signed on the client bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this))); require(recoverSigner(message, signature) == owner); (bool success, ) = payable(msg.sender).call{value: amount}(""); require(success); } /// freeze the contract and reclaim the leftover funds. function shutdown() external notFrozen { require(msg.sender == owner); freeze(); (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); require(success); } /// signature methods. function splitSignature(bytes memory sig) internal pure returns (uint8 v, bytes32 r, bytes32 s) { require(sig.length == 65); assembly { // first 32 bytes, after the length prefix. r := mload(add(sig, 32)) // second 32 bytes. s := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes). v := byte(0, mload(add(sig, 96))) } return (v, r, s); } function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); return ecrecover(message, v, r, s); } /// builds a prefixed hash to mimic the behavior of eth_sign. function prefixed(bytes32 hash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } } Writing a Simple Payment Channel ================================ Alice now builds a simple but complete implementation of a payment channel. Payment channels use cryptographic signatures to make repeated transfers of Ether securely, instantaneously, and without transaction fees. What is a Payment Channel? -------------------------- Payment channels allow participants to make repeated transfers of Ether without using transactions. This means that you can avoid the delays and fees associated with transactions. We are going to explore a simple unidirectional payment channel between two parties (Alice and Bob). It involves three steps: 1. Alice funds a smart contract with Ether. This "opens" the payment channel. 2. Alice signs messages that specify how much of that Ether is owed to the recipient. This step is repeated for each payment. 3. Bob "closes" the payment channel, withdrawing his portion of the Ether and sending the remainder back to the sender. .. note:: Only steps 1 and 3 require Ethereum transactions, step 2 means that the sender transmits a cryptographically signed message to the recipient via off chain methods (e.g. email). This means only two transactions are required to support any number of transfers. Bob is guaranteed to receive his funds because the smart contract escrows the Ether and honours a valid signed message. The smart contract also enforces a timeout, so Alice is guaranteed to eventually recover her funds even if the recipient refuses to close the channel. It is up to the participants in a payment channel to decide how long to keep it open. For a short-lived transaction, such as paying an internet café for each minute of network access, the payment channel may be kept open for a limited duration. On the other hand, for a recurring payment, such as paying an employee an hourly wage, the payment channel may be kept open for several months or years. Opening the Payment Channel --------------------------- To open the payment channel, Alice deploys the smart contract, attaching the Ether to be escrowed and specifying the intended recipient and a maximum duration for the channel to exist. This is the ``constructor`` in the ``SimplePaymentChannel`` contract, at the end of this section. Making Payments --------------- Alice makes payments by sending signed messages to Bob. This step is performed entirely outside of the Ethereum network. Messages are cryptographically signed by the sender and then transmitted directly to the recipient. Each message includes the following information: * The smart contract's address, used to prevent cross-contract replay attacks. * The total amount of Ether that is owed to the recipient so far. A payment channel is closed just once, at the end of a series of transfers. Because of this, only one of the messages sent is redeemed. This is why each message specifies a cumulative total amount of Ether owed, rather than the amount of the individual micropayment. The recipient will naturally choose to redeem the most recent message because that is the one with the highest total. The nonce per-message is not needed anymore, because the smart contract only honours a single message. The address of the smart contract is still used to prevent a message intended for one payment channel from being used for a different channel. Here is the modified JavaScript code to cryptographically sign a message from the previous section: .. code-block:: javascript function constructPaymentMessage(contractAddress, amount) { return abi.soliditySHA3( ["address", "uint256"], [contractAddress, amount] ); } function signMessage(message, callback) { web3.eth.personal.sign( "0x" + message.toString("hex"), web3.eth.defaultAccount, callback ); } // contractAddress is used to prevent cross-contract replay attacks. // amount, in wei, specifies how much Ether should be sent. function signPayment(contractAddress, amount, callback) { var message = constructPaymentMessage(contractAddress, amount); signMessage(message, callback); } Closing the Payment Channel --------------------------- When Bob is ready to receive his funds, it is time to close the payment channel by calling a ``close`` function on the smart contract. Closing the channel pays the recipient the Ether they are owed and deactivates the contract by freezing it, sending any remaining Ether back to Alice. To close the channel, Bob needs to provide a message signed by Alice. The smart contract must verify that the message contains a valid signature from the sender. The process for doing this verification is the same as the process the recipient uses. The Solidity functions ``isValidSignature`` and ``recoverSigner`` work just like their JavaScript counterparts in the previous section, with the latter function borrowed from the ``ReceiverPays`` contract. Only the payment channel recipient can call the ``close`` function, who naturally passes the most recent payment message because that message carries the highest total owed. If the sender were allowed to call this function, they could provide a message with a lower amount and cheat the recipient out of what they are owed. The function verifies the signed message matches the given parameters. If everything checks out, the recipient is sent their portion of the Ether, and the sender is sent the remaining funds via a ``transfer``. You can see the ``close`` function in the full contract. Channel Expiration ------------------- Bob can close the payment channel at any time, but if they fail to do so, Alice needs a way to recover her escrowed funds. An *expiration* time was set at the time of contract deployment. Once that time is reached, Alice can call ``claimTimeout`` to recover her funds. You can see the ``claimTimeout`` function in the full contract. After this function is called, Bob can no longer receive any Ether, so it is important that Bob closes the channel before the expiration is reached. The full contract ----------------- .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; contract Frozeable { bool private _frozen = false; modifier notFrozen() { require(!_frozen, "Inactive Contract."); _; } function freeze() internal { _frozen = true; } } contract SimplePaymentChannel is Frozeable { address payable public sender; // The account sending payments. address payable public recipient; // The account receiving the payments. uint256 public expiration; // Timeout in case the recipient never closes. constructor (address payable recipientAddress, uint256 duration) payable { sender = payable(msg.sender); recipient = recipientAddress; expiration = block.timestamp + duration; } /// the recipient can close the channel at any time by presenting a /// signed amount from the sender. the recipient will be sent that amount, /// and the remainder will go back to the sender function close(uint256 amount, bytes memory signature) external notFrozen { require(msg.sender == recipient); require(isValidSignature(amount, signature)); freeze(); (bool success, ) = recipient.call{value: amount}(""); require(success); (success, ) = sender.call{value: address(this).balance}(""); require(success); } /// the sender can extend the expiration at any time function extend(uint256 newExpiration) external notFrozen { require(msg.sender == sender); require(newExpiration > expiration); expiration = newExpiration; } /// if the timeout is reached without the recipient closing the channel, /// then the Ether is released back to the sender. function claimTimeout() external notFrozen { require(block.timestamp >= expiration); freeze(); (bool success, ) = sender.call{value: address(this).balance}(""); require(success); } function isValidSignature(uint256 amount, bytes memory signature) internal view returns (bool) { bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount))); // check that the signature is from the payment sender return recoverSigner(message, signature) == sender; } /// All functions below this are just taken from the chapter /// 'creating and verifying signatures' chapter. function splitSignature(bytes memory sig) internal pure returns (uint8 v, bytes32 r, bytes32 s) { require(sig.length == 65); assembly { // first 32 bytes, after the length prefix r := mload(add(sig, 32)) // second 32 bytes s := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } return (v, r, s); } function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); return ecrecover(message, v, r, s); } /// builds a prefixed hash to mimic the behavior of eth_sign. function prefixed(bytes32 hash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } } .. note:: The function ``splitSignature`` does not use all security checks. A real implementation should use a more rigorously tested library, such as openzeppelin's `version `_ of this code. Verifying Payments ------------------ Unlike in the previous section, messages in a payment channel aren't redeemed right away. The recipient keeps track of the latest message and redeems it when it's time to close the payment channel. This means it's critical that the recipient perform their own verification of each message. Otherwise there is no guarantee that the recipient will be able to get paid in the end. The recipient should verify each message using the following process: 1. Verify that the contract address in the message matches the payment channel. 2. Verify that the new total is the expected amount. 3. Verify that the new total does not exceed the amount of Ether escrowed. 4. Verify that the signature is valid and comes from the payment channel sender. We'll use the `ethereumjs-util `_ library to write this verification. The final step can be done a number of ways, and we use JavaScript. The following code borrows the ``constructPaymentMessage`` function from the signing **JavaScript code** above: .. code-block:: javascript // this mimics the prefixing behavior of the eth_sign JSON-RPC method. function prefixed(hash) { return ethereumjs.ABI.soliditySHA3( ["string", "bytes32"], ["\x19Ethereum Signed Message:\n32", hash] ); } function recoverSigner(message, signature) { var split = ethereumjs.Util.fromRpcSig(signature); var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s); var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex"); return signer; } function isValidSignature(contractAddress, amount, signature, expectedSigner) { var message = prefixed(constructPaymentMessage(contractAddress, amount)); var signer = recoverSigner(message, signature); return signer.toLowerCase() == ethereumjs.Util.stripHexPrefix(expectedSigner).toLowerCase(); } ================================================ FILE: docs/examples/modular.rst ================================================ .. index:: contract;modular, modular contract ***************** Modular Contracts ***************** A modular approach to building your contracts helps you reduce the complexity and improve the readability which will help to identify bugs and vulnerabilities during development and code review. If you specify and control the behavior of each module in isolation, the interactions you have to consider are only those between the module specifications and not every other moving part of the contract. In the example below, the contract uses the ``move`` method of the ``Balances`` :ref:`library ` to check that balances sent between addresses match what you expect. In this way, the ``Balances`` library provides an isolated component that properly tracks balances of accounts. It is easy to verify that the ``Balances`` library never produces negative balances or overflows and the sum of all balances is an invariant across the lifetime of the contract. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.9.0; library Balances { function move(mapping(address => uint256) storage balances, address from, address to, uint amount) internal { require(balances[from] >= amount); require(balances[to] + amount >= balances[to]); balances[from] -= amount; balances[to] += amount; } } contract Token { mapping(address => uint256) balances; using Balances for *; mapping(address => mapping(address => uint256)) allowed; event Transfer(address from, address to, uint amount); event Approval(address owner, address spender, uint amount); function transfer(address to, uint amount) external returns (bool success) { balances.move(msg.sender, to, amount); emit Transfer(msg.sender, to, amount); return true; } function transferFrom(address from, address to, uint amount) external returns (bool success) { require(allowed[from][msg.sender] >= amount); allowed[from][msg.sender] -= amount; balances.move(from, to, amount); emit Transfer(from, to, amount); return true; } function approve(address spender, uint tokens) external returns (bool success) { require(allowed[msg.sender][spender] == 0, ""); allowed[msg.sender][spender] = tokens; emit Approval(msg.sender, spender, tokens); return true; } function balanceOf(address tokenOwner) external view returns (uint balance) { return balances[tokenOwner]; } } ================================================ FILE: docs/examples/safe-remote.rst ================================================ .. index:: purchase, remote purchase, escrow ******************** Safe Remote Purchase ******************** Purchasing goods remotely currently requires multiple parties that need to trust each other. The simplest configuration involves a seller and a buyer. The buyer would like to receive an item from the seller and the seller would like to get some compensation, e.g. Ether, in return. The problematic part is the shipment here: There is no way to determine for sure that the item arrived at the buyer. There are multiple ways to solve this problem, but all fall short in one or the other way. In the following example, both parties have to put twice the value of the item into the contract as escrow. As soon as this happened, the Ether will stay locked inside the contract until the buyer confirms that they received the item. After that, the buyer is returned the value (half of their deposit) and the seller gets three times the value (their deposit plus the value). The idea behind this is that both parties have an incentive to resolve the situation or otherwise their Ether is locked forever. This contract of course does not solve the problem, but gives an overview of how you can use state machine-like constructs inside a contract. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract Purchase { uint public value; address payable public seller; address payable public buyer; enum State { Created, Locked, Release, Inactive } // The state variable has a default value of the first member, `State.created` State public state; modifier condition(bool condition_) { require(condition_); _; } /// Only the buyer can call this function. error OnlyBuyer(); /// Only the seller can call this function. error OnlySeller(); /// The function cannot be called at the current state. error InvalidState(); /// The provided value has to be even. error ValueNotEven(); modifier onlyBuyer() { if (msg.sender != buyer) revert OnlyBuyer(); _; } modifier onlySeller() { if (msg.sender != seller) revert OnlySeller(); _; } modifier inState(State state_) { if (state != state_) revert InvalidState(); _; } event Aborted(); event PurchaseConfirmed(); event ItemReceived(); event SellerRefunded(); // Ensure that `msg.value` is an even number. // Division will truncate if it is an odd number. // Check via multiplication that it wasn't an odd number. constructor() payable { seller = payable(msg.sender); value = msg.value / 2; if ((2 * value) != msg.value) revert ValueNotEven(); } /// Abort the purchase and reclaim the ether. /// Can only be called by the seller before /// the contract is locked. function abort() external onlySeller inState(State.Created) { emit Aborted(); state = State.Inactive; // We use call here directly. It is // reentrancy-safe, because it is the // last call in this function and we // already changed the state. (bool success, ) = seller.call{value: address(this).balance}(""); require(success); } /// Confirm the purchase as buyer. /// Transaction has to include `2 * value` ether. /// The ether will be locked until confirmReceived /// is called. function confirmPurchase() external inState(State.Created) condition(msg.value == (2 * value)) payable { emit PurchaseConfirmed(); buyer = payable(msg.sender); state = State.Locked; } /// Confirm that you (the buyer) received the item. /// This will release the locked ether. function confirmReceived() external onlyBuyer inState(State.Locked) { emit ItemReceived(); // It is important to change the state first because // otherwise, the contracts called using `call` below // can call in again here. state = State.Release; (bool success, ) = buyer.call{value: value}(""); require(success); } /// This function refunds the seller, i.e. /// pays back the locked funds of the seller. function refundSeller() external onlySeller inState(State.Release) { emit SellerRefunded(); // It is important to change the state first because // otherwise, the contracts called using `call` below // can call in again here. state = State.Inactive; (bool success, ) = seller.call{value: 3 * value}(""); require(success); } } ================================================ FILE: docs/examples/voting.rst ================================================ .. index:: voting, ballot .. _voting: ****** Voting ****** The following contract is quite complex, but showcases a lot of Solidity's features. It implements a voting contract. Of course, the main problems of electronic voting is how to assign voting rights to the correct persons and how to prevent manipulation. We will not solve all problems here, but at least we will show how delegated voting can be done so that vote counting is **automatic and completely transparent** at the same time. The idea is to create one contract per ballot, providing a short name for each option. Then the creator of the contract who serves as chairperson will give the right to vote to each address individually. The persons behind the addresses can then choose to either vote themselves or to delegate their vote to a person they trust. At the end of the voting time, ``winningProposal()`` will return the proposal with the largest number of votes. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; /// @title Voting with delegation. contract Ballot { // This declares a new complex type which will // be used for variables later. // It will represent a single voter. struct Voter { uint weight; // weight is accumulated by delegation bool voted; // if true, that person already voted address delegate; // person delegated to uint vote; // index of the voted proposal } // This is a type for a single proposal. struct Proposal { bytes32 name; // short name (up to 32 bytes) uint voteCount; // number of accumulated votes } address public chairperson; // This declares a state variable that // stores a `Voter` struct for each possible address. mapping(address => Voter) public voters; // A dynamically-sized array of `Proposal` structs. Proposal[] public proposals; /// Create a new ballot to choose one of `proposalNames`. constructor(bytes32[] memory proposalNames) { chairperson = msg.sender; voters[chairperson].weight = 1; // For each of the provided proposal names, // create a new proposal object and add it // to the end of the array. for (uint i = 0; i < proposalNames.length; i++) { // `Proposal({...})` creates a temporary // Proposal object and `proposals.push(...)` // appends it to the end of `proposals`. proposals.push(Proposal({ name: proposalNames[i], voteCount: 0 })); } } // Give `voter` the right to vote on this ballot. // May only be called by `chairperson`. function giveRightToVote(address voter) external { // If the first argument of `require` evaluates // to `false`, execution terminates and all // changes to the state and to Ether balances // are reverted. // This used to consume all gas in old EVM versions, but // not anymore. // It is often a good idea to use `require` to check if // functions are called correctly. // As a second argument, you can also provide an // explanation about what went wrong. require( msg.sender == chairperson, "Only chairperson can give right to vote." ); require( !voters[voter].voted, "The voter already voted." ); require(voters[voter].weight == 0); voters[voter].weight = 1; } /// Delegate your vote to the voter `to`. function delegate(address to) external { // assigns reference Voter storage sender = voters[msg.sender]; require(sender.weight != 0, "You have no right to vote"); require(!sender.voted, "You already voted."); require(to != msg.sender, "Self-delegation is disallowed."); // Forward the delegation as long as // `to` also delegated. // In general, such loops are very dangerous, // because if they run too long, they might // need more gas than is available in a block. // In this case, the delegation will not be executed, // but in other situations, such loops might // cause a contract to get "stuck" completely. while (voters[to].delegate != address(0)) { to = voters[to].delegate; // We found a loop in the delegation, not allowed. require(to != msg.sender, "Found loop in delegation."); } Voter storage delegate_ = voters[to]; // Voters cannot delegate to accounts that cannot vote. require(delegate_.weight >= 1); // Since `sender` is a reference, this // modifies `voters[msg.sender]`. sender.voted = true; sender.delegate = to; if (delegate_.voted) { // If the delegate already voted, // directly add to the number of votes proposals[delegate_.vote].voteCount += sender.weight; } else { // If the delegate did not vote yet, // add to her weight. delegate_.weight += sender.weight; } } /// Give your vote (including votes delegated to you) /// to proposal `proposals[proposal].name`. function vote(uint proposal) external { Voter storage sender = voters[msg.sender]; require(sender.weight != 0, "Has no right to vote"); require(!sender.voted, "Already voted."); sender.voted = true; sender.vote = proposal; // If `proposal` is out of the range of the array, // this will throw automatically and revert all // changes. proposals[proposal].voteCount += sender.weight; } /// @dev Computes the winning proposal taking all /// previous votes into account. function winningProposal() public view returns (uint winningProposal_) { uint winningVoteCount = 0; for (uint p = 0; p < proposals.length; p++) { if (proposals[p].voteCount > winningVoteCount) { winningVoteCount = proposals[p].voteCount; winningProposal_ = p; } } } // Calls winningProposal() function to get the index // of the winner contained in the proposals array and then // returns the name of the winner function winnerName() external view returns (bytes32 winnerName_) { winnerName_ = proposals[winningProposal()].name; } } Possible Improvements ===================== Currently, many transactions are needed to assign the rights to vote to all participants. Moreover, if two or more proposals have the same number of votes, ``winningProposal()`` is not able to register a tie. Can you think of a way to fix these issues? ================================================ FILE: docs/ext/html_extra_template_renderer.py ================================================ import os.path def render_html_extra_templates(app): if app.builder.format != 'html': # Non-HTML builders do not provide .templates.render_string(). Note that a HTML # builder is still used also when building some other formats like json or epub. return for input_path, template_config in app.config.html_extra_templates.items(): # Requiring absolute paths simplifies the implementation. if not os.path.isabs(input_path): raise RuntimeError(f"Template input path is not absolute: {input_path}") if not os.path.isabs(template_config['target']): raise RuntimeError(f"Template target path is not absolute: {template_config['target']}") with open(input_path, 'r', encoding='utf8') as input_file: # This runs Jinja2, which supports rendering {{ }} tags among other things. rendered_template = app.builder.templates.render_string( input_file.read(), template_config['context'], ) with open(template_config['target'], 'w', encoding='utf8') as target_file: target_file.write(rendered_template) app.config.html_extra_path.append(template_config['target']) def setup(app): app.add_config_value('html_extra_templates', default={}, rebuild='', types=dict) # Register a handler for the env-before-read-docs event. Any event that's fired before static # files get copied would do. app.connect( 'env-before-read-docs', lambda app, env, docnames: render_html_extra_templates(app) ) return { # NOTE: Need to access _raw_config here because setup() runs before app.config is ready. 'version': app.config._raw_config['version'], # pylint: disable=protected-access 'parallel_read_safe': True, 'parallel_write_safe': True, } ================================================ FILE: docs/ext/remix_code_links.py ================================================ import base64 import docutils # pragma pylint: disable=import-error from sphinx.util import logging # pragma pylint: disable=import-error # NOTE: 2000 should generally be safe for all browsers, while 8000 for most of them. MAX_SAFE_URL_LENGTH = 10000 logger = logging.getLogger(__name__) def insert_node_before(child, new_sibling): assert child in child.parent.children for position, node in enumerate(child.parent.children): if node == child: child.parent.insert(position, new_sibling) break def remix_code_url(source_code, language, solidity_version): # NOTE: base64 encoded data may contain +, = and / characters. Remix seems to handle them just # fine without any escaping. base64_encoded_source = base64.b64encode(source_code.encode('utf-8')).decode('ascii') return f"https://remix.ethereum.org/?#language={language}&version={solidity_version}&code={base64_encoded_source}" def build_remix_link_node(url): reference_node = docutils.nodes.reference('', 'open in Remix', internal=False, refuri=url, target='_blank') reference_node['classes'].append('remix-link') paragraph_node = docutils.nodes.paragraph() paragraph_node['classes'].append('remix-link-container') paragraph_node.append(reference_node) return paragraph_node def insert_remix_link(app, doctree, solidity_version): if app.builder.format != 'html' or app.builder.name == 'epub': return for literal_block_node in doctree.traverse(docutils.nodes.literal_block): assert 'language' in literal_block_node.attributes language = literal_block_node.attributes['language'].lower() if language not in ['solidity', 'yul']: continue text_nodes = list(literal_block_node.traverse(docutils.nodes.Text)) assert len(text_nodes) == 1 remix_url = remix_code_url(text_nodes[0], language, solidity_version) url_length = len(remix_url.encode('utf-8')) if url_length > MAX_SAFE_URL_LENGTH: logger.warning( "Remix URL generated from the code snippet exceeds the maximum safe URL length " " (%d > %d bytes).", url_length, MAX_SAFE_URL_LENGTH, location=(literal_block_node.source, literal_block_node.line), ) insert_node_before(literal_block_node, build_remix_link_node(remix_url)) def setup(app): # NOTE: Need to access _raw_config here because setup() runs before app.config is ready. solidity_version = app.config._raw_config['version'] # pylint: disable=protected-access app.connect( 'doctree-resolved', lambda app, doctree, docname: insert_remix_link(app, doctree, solidity_version) ) return { 'version': solidity_version, 'parallel_read_safe': True, 'parallel_write_safe': True, } ================================================ FILE: docs/grammar/SolidityLexer.g4 ================================================ lexer grammar SolidityLexer; /** * Keywords reserved for future use in Solidity. */ ReservedKeywords: 'after' | 'alias' | 'apply' | 'auto' | 'byte' | 'case' | 'copyof' | 'default' | 'define' | 'final' | 'implements' | 'in' | 'inline' | 'let' | 'macro' | 'match' | 'mutable' | 'null' | 'of' | 'partial' | 'promise' | 'reference' | 'relocatable' | 'sealed' | 'sizeof' | 'static' | 'supports' | 'switch' | 'typedef' | 'typeof' | 'var'; Abstract: 'abstract'; Address: 'address'; Anonymous: 'anonymous'; As: 'as'; Assembly: 'assembly' -> pushMode(AssemblyBlockMode); At: 'at'; // not a real keyword Bool: 'bool'; Break: 'break'; Bytes: 'bytes'; Calldata: 'calldata'; Catch: 'catch'; Constant: 'constant'; Constructor: 'constructor'; Continue: 'continue'; Contract: 'contract'; Delete: 'delete'; Do: 'do'; Else: 'else'; Emit: 'emit'; Enum: 'enum'; Error: 'error'; // not a real keyword Event: 'event'; External: 'external'; Fallback: 'fallback'; False: 'false'; Fixed: 'fixed' | ('fixed' [1-9][0-9]* 'x' [1-9][0-9]*); /** * Bytes types of fixed length. */ FixedBytes: 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | 'bytes6' | 'bytes7' | 'bytes8' | 'bytes9' | 'bytes10' | 'bytes11' | 'bytes12' | 'bytes13' | 'bytes14' | 'bytes15' | 'bytes16' | 'bytes17' | 'bytes18' | 'bytes19' | 'bytes20' | 'bytes21' | 'bytes22' | 'bytes23' | 'bytes24' | 'bytes25' | 'bytes26' | 'bytes27' | 'bytes28' | 'bytes29' | 'bytes30' | 'bytes31' | 'bytes32'; For: 'for'; From: 'from'; // not a real keyword Function: 'function'; Global: 'global'; // not a real keyword Hex: 'hex'; If: 'if'; Immutable: 'immutable'; Import: 'import'; Indexed: 'indexed'; Interface: 'interface'; Internal: 'internal'; Is: 'is'; Layout: 'layout'; // not a real keyword Library: 'library'; Mapping: 'mapping'; Memory: 'memory'; Modifier: 'modifier'; New: 'new'; /** * Unit denomination for numbers. */ SubDenomination: 'wei' | 'gwei' | 'ether' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years'; Override: 'override'; Payable: 'payable'; Pragma: 'pragma' -> pushMode(PragmaMode); Private: 'private'; Public: 'public'; Pure: 'pure'; Receive: 'receive'; Return: 'return'; Returns: 'returns'; Revert: 'revert'; // not a real keyword /** * Sized signed integer types. * int is an alias of int256. */ SignedIntegerType: 'int' | 'int8' | 'int16' | 'int24' | 'int32' | 'int40' | 'int48' | 'int56' | 'int64' | 'int72' | 'int80' | 'int88' | 'int96' | 'int104' | 'int112' | 'int120' | 'int128' | 'int136' | 'int144' | 'int152' | 'int160' | 'int168' | 'int176' | 'int184' | 'int192' | 'int200' | 'int208' | 'int216' | 'int224' | 'int232' | 'int240' | 'int248' | 'int256'; Storage: 'storage'; String: 'string'; Struct: 'struct'; Transient: 'transient'; // not a real keyword True: 'true'; Try: 'try'; Type: 'type'; Ufixed: 'ufixed' | ('ufixed' [1-9][0-9]+ 'x' [1-9][0-9]+); Unchecked: 'unchecked'; Unicode: 'unicode'; /** * Sized unsigned integer types. * uint is an alias of uint256. */ UnsignedIntegerType: 'uint' | 'uint8' | 'uint16' | 'uint24' | 'uint32' | 'uint40' | 'uint48' | 'uint56' | 'uint64' | 'uint72' | 'uint80' | 'uint88' | 'uint96' | 'uint104' | 'uint112' | 'uint120' | 'uint128' | 'uint136' | 'uint144' | 'uint152' | 'uint160' | 'uint168' | 'uint176' | 'uint184' | 'uint192' | 'uint200' | 'uint208' | 'uint216' | 'uint224' | 'uint232' | 'uint240' | 'uint248' | 'uint256'; Using: 'using'; View: 'view'; Virtual: 'virtual'; While: 'while'; LParen: '('; RParen: ')'; LBrack: '['; RBrack: ']'; LBrace: '{'; RBrace: '}'; Colon: ':'; Semicolon: ';'; Period: '.'; Conditional: '?'; DoubleArrow: '=>'; RightArrow: '->'; Assign: '='; AssignBitOr: '|='; AssignBitXor: '^='; AssignBitAnd: '&='; AssignShl: '<<='; AssignSar: '>>='; AssignShr: '>>>='; AssignAdd: '+='; AssignSub: '-='; AssignMul: '*='; AssignDiv: '/='; AssignMod: '%='; Comma: ','; Or: '||'; And: '&&'; BitOr: '|'; BitXor: '^'; BitAnd: '&'; Shl: '<<'; Sar: '>>'; Shr: '>>>'; Add: '+'; Sub: '-'; Mul: '*'; Div: '/'; Mod: '%'; Exp: '**'; Equal: '=='; NotEqual: '!='; LessThan: '<'; GreaterThan: '>'; LessThanOrEqual: '<='; GreaterThanOrEqual: '>='; Not: '!'; BitNot: '~'; Inc: '++'; Dec: '--'; //@doc:inline DoubleQuote: '"'; //@doc:inline SingleQuote: '\''; /** * A non-empty quoted string literal restricted to printable characters. */ NonEmptyStringLiteral: '"' DoubleQuotedStringCharacter+ '"' | '\'' SingleQuotedStringCharacter+ '\''; /** * An empty string literal */ EmptyStringLiteral: '"' '"' | '\'' '\''; // Note that this will also be used for Yul string literals. //@doc:inline fragment DoubleQuotedStringCharacter: DoubleQuotedPrintable | EscapeSequence; // Note that this will also be used for Yul string literals. //@doc:inline fragment SingleQuotedStringCharacter: SingleQuotedPrintable | EscapeSequence; /** * Any printable character except single quote or back slash. */ fragment SingleQuotedPrintable: [\u0020-\u0026\u0028-\u005B\u005D-\u007E]; /** * Any printable character except double quote or back slash. */ fragment DoubleQuotedPrintable: [\u0020-\u0021\u0023-\u005B\u005D-\u007E]; /** * Escape sequence. * Apart from common single character escape sequences, line breaks can be escaped * as well as four hex digit unicode escapes \\uXXXX and two digit hex escape sequences \\xXX are allowed. */ fragment EscapeSequence: '\\' ( ['"\\nrt\n\r] | 'u' HexCharacter HexCharacter HexCharacter HexCharacter | 'x' HexCharacter HexCharacter ); /** * A single quoted string literal allowing arbitrary unicode characters. */ UnicodeStringLiteral: 'unicode' (('"' DoubleQuotedUnicodeStringCharacter* '"') | ('\'' SingleQuotedUnicodeStringCharacter* '\'')); //@doc:inline fragment DoubleQuotedUnicodeStringCharacter: ~["\r\n\\] | EscapeSequence; //@doc:inline fragment SingleQuotedUnicodeStringCharacter: ~['\r\n\\] | EscapeSequence; // Note that this will also be used for Yul hex string literals. /** * Hex strings need to consist of an even number of hex digits that may be grouped using underscores. */ HexString: 'hex' (('"' EvenHexDigits? '"') | ('\'' EvenHexDigits? '\'')); /** * Hex numbers consist of a prefix and an arbitrary number of hex digits that may be delimited by underscores. */ HexNumber: '0' 'x' HexDigits; //@doc:inline fragment HexDigits: HexCharacter ('_'? HexCharacter)*; //@doc:inline fragment EvenHexDigits: HexCharacter HexCharacter ('_'? HexCharacter HexCharacter)*; //@doc:inline fragment HexCharacter: [0-9A-Fa-f]; /** * Scanned but not used by any rule, i.e, disallowed. * solc parser considers number starting with '0', not immediately followed by '.' or 'x' as * octal, even if non octal digits '8' and '9' are present. */ OctalNumber: '0' DecimalDigits ('.' DecimalDigits)?; /** * A decimal number literal consists of decimal digits that may be delimited by underscores and * an optional positive or negative exponent. * If the digits contain a decimal point, the literal has fixed point type. */ DecimalNumber: (DecimalDigits | (DecimalDigits? '.' DecimalDigits)) ([eE] '-'? DecimalDigits)?; //@doc:inline fragment DecimalDigits: [0-9] ('_'? [0-9])* ; /** * This is needed to avoid successfully parsing a number followed by a string with no whitespace between. */ DecimalNumberFollowedByIdentifier: DecimalNumber Identifier; /** * An identifier in solidity has to start with a letter, a dollar-sign or an underscore and * may additionally contain numbers after the first symbol. */ Identifier: IdentifierStart IdentifierPart*; //@doc:inline fragment IdentifierStart: [a-zA-Z$_]; //@doc:inline fragment IdentifierPart: [a-zA-Z0-9$_]; WS: [ \t\r\n\u000C]+ -> skip ; COMMENT: '/*' .*? '*/' -> channel(HIDDEN) ; LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN); mode AssemblyBlockMode; //@doc:inline AssemblyDialect: '"evmasm"'; AssemblyLBrace: '{' -> popMode, pushMode(YulMode); AssemblyFlagString: '"' DoubleQuotedStringCharacter+ '"'; AssemblyBlockLParen: '('; AssemblyBlockRParen: ')'; AssemblyBlockComma: ','; AssemblyBlockWS: [ \t\r\n\u000C]+ -> skip ; AssemblyBlockCOMMENT: '/*' .*? '*/' -> channel(HIDDEN) ; AssemblyBlockLINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN) ; mode YulMode; YulBreak: 'break'; YulCase: 'case'; YulContinue: 'continue'; YulDefault: 'default'; YulFalse: 'false'; YulFor: 'for'; YulFunction: 'function'; YulIf: 'if'; YulLeave: 'leave'; YulLet: 'let'; YulSwitch: 'switch'; YulTrue: 'true'; YulHex: 'hex'; /** * Builtin functions in the EVM Yul dialect. */ YulEVMBuiltin: 'stop' | 'add' | 'sub' | 'mul' | 'div' | 'sdiv' | 'mod' | 'smod' | 'exp' | 'not' | 'lt' | 'gt' | 'slt' | 'sgt' | 'eq' | 'iszero' | 'and' | 'or' | 'xor' | 'byte' | 'shl' | 'shr' | 'sar' | 'clz' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256' | 'pop' | 'mload' | 'mstore' | 'mstore8' | 'sload' | 'sstore' | 'tload' | 'tstore'| 'msize' | 'gas' | 'address' | 'balance' | 'selfbalance' | 'caller' | 'callvalue' | 'calldataload' | 'calldatasize' | 'calldatacopy' | 'extcodesize' | 'extcodecopy' | 'returndatasize' | 'returndatacopy' | 'mcopy' | 'extcodehash' | 'create' | 'create2' | 'call' | 'callcode' | 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid' | 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice' | 'blockhash' | 'blobhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'prevrandao' | 'gaslimit' | 'basefee' | 'blobbasefee'; YulLBrace: '{' -> pushMode(YulMode); YulRBrace: '}' -> popMode; YulLParen: '('; YulRParen: ')'; YulAssign: ':='; YulPeriod: '.'; YulComma: ','; YulArrow: '->'; /** * Yul identifiers consist of letters, dollar signs, underscores and numbers, but may not start with a number. * In inline assembly there cannot be dots in user-defined identifiers. Instead see yulPath for expressions * consisting of identifiers with dots. */ YulIdentifier: YulIdentifierStart YulIdentifierPart*; //@doc:inline fragment YulIdentifierStart: [a-zA-Z$_]; //@doc:inline fragment YulIdentifierPart: [a-zA-Z0-9$_]; /** * Hex literals in Yul consist of a prefix and one or more hexadecimal digits. */ YulHexNumber: '0' 'x' [0-9a-fA-F]+; /** * Decimal literals in Yul may be zero or any sequence of decimal digits without leading zeroes. */ YulDecimalNumber: '0' | ([1-9] [0-9]*); /** * String literals in Yul consist of one or more double-quoted or single-quoted strings * that may contain escape sequences and printable characters except unescaped line breaks or * unescaped double-quotes or single-quotes, respectively. */ YulStringLiteral: '"' DoubleQuotedStringCharacter* '"' | '\'' SingleQuotedStringCharacter* '\''; //@doc:inline YulHexStringLiteral: HexString; YulWS: [ \t\r\n\u000C]+ -> skip ; YulCOMMENT: '/*' .*? '*/' -> channel(HIDDEN) ; YulLINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN) ; mode PragmaMode; /** * Pragma token. Can contain any kind of symbol except a semicolon. * Note that currently the solidity parser only allows a subset of this. */ //@doc:name pragma-token //@doc:no-diagram PragmaToken: ~[;]+; PragmaSemicolon: ';' -> popMode; PragmaWS: [ \t\r\n\u000C]+ -> skip ; PragmaCOMMENT: '/*' .*? '*/' -> channel(HIDDEN) ; PragmaLINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN) ; ================================================ FILE: docs/grammar/SolidityParser.g4 ================================================ /** * Solidity is a statically typed, contract-oriented, high-level language for implementing smart contracts on the Ethereum platform. */ parser grammar SolidityParser; options { tokenVocab=SolidityLexer; } /** * On top level, Solidity allows pragmas, import directives, and * definitions of contracts, interfaces, libraries, structs, enums and constants. */ sourceUnit: ( pragmaDirective | importDirective | usingDirective | contractDefinition | interfaceDefinition | libraryDefinition | functionDefinition | constantVariableDeclaration | structDefinition | enumDefinition | userDefinedValueTypeDefinition | errorDefinition | eventDefinition )* EOF; //@doc: inline pragmaDirective: Pragma PragmaToken+ PragmaSemicolon; /** * Import directives import identifiers from different files. */ importDirective: Import ( (path (As unitAlias=identifier)?) | (symbolAliases From path) | (Mul As unitAlias=identifier From path) ) Semicolon; //@doc: inline //@doc:name aliases importAliases: symbol=identifier (As alias=identifier)?; /** * Path of a file to be imported. */ path: NonEmptyStringLiteral; /** * List of aliases for symbols to be imported. */ symbolAliases: LBrace aliases+=importAliases (Comma aliases+=importAliases)* RBrace; /** * Top-level definition of a contract. */ contractDefinition locals [boolean layoutSet=false, boolean inheritanceSet=false] : Abstract? Contract name=identifier ( {!$layoutSet}? Layout At expression {$layoutSet = true;} | {!$inheritanceSet}? inheritanceSpecifierList {$inheritanceSet = true;} )* LBrace contractBodyElement* RBrace; /** * Top-level definition of an interface. */ interfaceDefinition: Interface name=identifier inheritanceSpecifierList? LBrace contractBodyElement* RBrace; /** * Top-level definition of a library. */ libraryDefinition: Library name=identifier LBrace contractBodyElement* RBrace; //@doc:inline inheritanceSpecifierList: Is inheritanceSpecifiers+=inheritanceSpecifier (Comma inheritanceSpecifiers+=inheritanceSpecifier)*?; /** * Inheritance specifier for contracts and interfaces. * Can optionally supply base constructor arguments. */ inheritanceSpecifier: name=identifierPath arguments=callArgumentList?; /** * Declarations that can be used in contracts, interfaces and libraries. * * Note that interfaces and libraries may not contain constructors, interfaces may not contain state variables * and libraries may not contain fallback, receive functions nor non-constant state variables. */ contractBodyElement: constructorDefinition | functionDefinition | modifierDefinition | fallbackFunctionDefinition | receiveFunctionDefinition | structDefinition | enumDefinition | userDefinedValueTypeDefinition | stateVariableDeclaration | eventDefinition | errorDefinition | usingDirective; //@doc:inline namedArgument: name=identifier Colon value=expression; /** * Arguments when calling a function or a similar callable object. * The arguments are either given as comma separated list or as map of named arguments. */ callArgumentList: LParen ((expression (Comma expression)*)? | LBrace (namedArgument (Comma namedArgument)*)? RBrace) RParen; /** * Qualified name. */ identifierPath: identifier (Period identifier)*; /** * Call to a modifier. If the modifier takes no arguments, the argument list can be skipped entirely * (including opening and closing parentheses). */ modifierInvocation: identifierPath callArgumentList?; /** * Visibility for functions and function types. */ visibility: Internal | External | Private | Public; /** * A list of parameters, such as function arguments or return values. */ parameterList: parameters+=parameterDeclaration (Comma parameters+=parameterDeclaration)*; //@doc:inline parameterDeclaration: type=typeName location=dataLocation? name=identifier?; /** * Definition of a constructor. * Must always supply an implementation. * Note that specifying internal or public visibility is deprecated. */ constructorDefinition locals[boolean payableSet = false, boolean visibilitySet = false] : Constructor LParen (arguments=parameterList)? RParen ( modifierInvocation | {!$payableSet}? Payable {$payableSet = true;} | {!$visibilitySet}? Internal {$visibilitySet = true;} | {!$visibilitySet}? Public {$visibilitySet = true;} )* body=block; /** * State mutability for function types. * The default mutability 'non-payable' is assumed if no mutability is specified. */ stateMutability: Pure | View | Payable; /** * An override specifier used for functions, modifiers or state variables. * In cases where there are ambiguous declarations in several base contracts being overridden, * a complete list of base contracts has to be given. */ overrideSpecifier: Override (LParen overrides+=identifierPath (Comma overrides+=identifierPath)* RParen)?; /** * The definition of contract, library, interface or free functions. * Depending on the context in which the function is defined, further restrictions may apply, * e.g. functions in interfaces have to be unimplemented, i.e. may not contain a body block. */ functionDefinition locals[ boolean visibilitySet = false, boolean mutabilitySet = false, boolean virtualSet = false, boolean overrideSpecifierSet = false, ] : Function (identifier | Fallback | Receive) LParen (arguments=parameterList)? RParen ( {!$visibilitySet}? visibility {$visibilitySet = true;} | {!$mutabilitySet}? stateMutability {$mutabilitySet = true;} | modifierInvocation | {!$virtualSet}? Virtual {$virtualSet = true;} | {!$overrideSpecifierSet}? overrideSpecifier {$overrideSpecifierSet = true;} )* (Returns LParen returnParameters=parameterList RParen)? (Semicolon | body=block); /** * The definition of a modifier. * Note that within the body block of a modifier, the underscore cannot be used as identifier, * but is used as placeholder statement for the body of a function to which the modifier is applied. */ modifierDefinition locals[ boolean virtualSet = false, boolean overrideSpecifierSet = false ] : Modifier name=identifier (LParen (arguments=parameterList)? RParen)? ( {!$virtualSet}? Virtual {$virtualSet = true;} | {!$overrideSpecifierSet}? overrideSpecifier {$overrideSpecifierSet = true;} )* (Semicolon | body=block); /** * Definition of the special fallback function. */ fallbackFunctionDefinition locals[ boolean visibilitySet = false, boolean mutabilitySet = false, boolean virtualSet = false, boolean overrideSpecifierSet = false, boolean hasParameters = false ] : kind=Fallback LParen (parameterList { $hasParameters = true; } )? RParen ( {!$visibilitySet}? External {$visibilitySet = true;} | {!$mutabilitySet}? stateMutability {$mutabilitySet = true;} | modifierInvocation | {!$virtualSet}? Virtual {$virtualSet = true;} | {!$overrideSpecifierSet}? overrideSpecifier {$overrideSpecifierSet = true;} )* ( {$hasParameters}? Returns LParen returnParameters=parameterList RParen | {!$hasParameters}? ) (Semicolon | body=block); /** * Definition of the special receive function. */ receiveFunctionDefinition locals[ boolean visibilitySet = false, boolean mutabilitySet = false, boolean virtualSet = false, boolean overrideSpecifierSet = false ] : kind=Receive LParen RParen ( {!$visibilitySet}? External {$visibilitySet = true;} | {!$mutabilitySet}? Payable {$mutabilitySet = true;} | modifierInvocation | {!$virtualSet}? Virtual {$virtualSet = true;} | {!$overrideSpecifierSet}? overrideSpecifier {$overrideSpecifierSet = true;} )* (Semicolon | body=block); /** * Definition of a struct. Can occur at top-level within a source unit or within a contract, library or interface. */ structDefinition: Struct name=identifier LBrace members=structMember+ RBrace; /** * The declaration of a named struct member. */ structMember: type=typeName name=identifier Semicolon; /** * Definition of an enum. Can occur at top-level within a source unit or within a contract, library or interface. */ enumDefinition: Enum name=identifier LBrace enumValues+=identifier (Comma enumValues+=identifier)* RBrace; /** * Definition of a user defined value type. Can occur at top-level within a source unit or within a contract, library or interface. */ userDefinedValueTypeDefinition: Type name=identifier Is elementaryTypeName[true] Semicolon; /** * The declaration of a state variable. */ stateVariableDeclaration locals [boolean constantnessSet = false, boolean visibilitySet = false, boolean overrideSpecifierSet = false, boolean locationSet = false] : type=typeName ( {!$visibilitySet}? Public {$visibilitySet = true;} | {!$visibilitySet}? Private {$visibilitySet = true;} | {!$visibilitySet}? Internal {$visibilitySet = true;} | {!$constantnessSet}? Constant {$constantnessSet = true;} | {!$overrideSpecifierSet}? overrideSpecifier {$overrideSpecifierSet = true;} | {!$constantnessSet}? Immutable {$constantnessSet = true;} | {!$locationSet}? Transient {$locationSet = true;} )* name=identifier (Assign initialValue=expression)? Semicolon; /** * The declaration of a constant variable. */ constantVariableDeclaration : type=typeName Constant name=identifier Assign initialValue=expression Semicolon; /** * Parameter of an event. */ eventParameter: type=typeName Indexed? name=identifier?; /** * Definition of an event. Can occur in contracts, libraries or interfaces. */ eventDefinition: Event name=identifier LParen (parameters+=eventParameter (Comma parameters+=eventParameter)*)? RParen Anonymous? Semicolon; /** * Parameter of an error. */ errorParameter: type=typeName name=identifier?; /** * Definition of an error. */ errorDefinition: Error name=identifier LParen (parameters+=errorParameter (Comma parameters+=errorParameter)*)? RParen Semicolon; /** * Operators that users are allowed to implement for some types with `using for`. */ userDefinableOperator: BitAnd | BitNot | BitOr | BitXor | Add | Div | Mod | Mul | Sub | Equal | GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual | NotEqual; /** * Using directive to attach library functions and free functions to types. * Can occur within contracts and libraries and at the file level. */ usingDirective: Using ( identifierPath | (LBrace usingAliases (Comma usingAliases)* RBrace) ) For (Mul | typeName) Global? Semicolon; usingAliases: identifierPath (As userDefinableOperator)?; /** * A type name can be an elementary type, a function type, a mapping type, a user-defined type * (e.g. a contract or struct) or an array type. */ typeName: elementaryTypeName[true] | functionTypeName | mappingType | identifierPath | typeName LBrack expression? RBrack; elementaryTypeName[boolean allowAddressPayable]: Address | {$allowAddressPayable}? Address Payable | Bool | String | Bytes | SignedIntegerType | UnsignedIntegerType | FixedBytes | Fixed | Ufixed; functionTypeName locals [boolean visibilitySet = false, boolean mutabilitySet = false] : Function LParen (arguments=parameterList)? RParen ( {!$visibilitySet}? visibility {$visibilitySet = true;} | {!$mutabilitySet}? stateMutability {$mutabilitySet = true;} )* (Returns LParen returnParameters=parameterList RParen)?; /** * The declaration of a single variable. */ variableDeclaration: type=typeName location=dataLocation? name=identifier; dataLocation: Memory | Storage | Calldata; /** * Complex expression. * Can be an index access, an index range access, a member access, a function call (with optional function call options), * a type conversion, an unary or binary expression, a comparison or assignment, a ternary expression, * a new-expression (i.e. a contract creation or the allocation of a dynamic memory array), * a tuple, an inline array or a primary expression (i.e. an identifier, literal or type name). */ expression: expression LBrack index=expression? RBrack # IndexAccess | expression LBrack startIndex=expression? Colon endIndex=expression? RBrack # IndexRangeAccess | expression Period (identifier | Address) # MemberAccess | expression LBrace (namedArgument (Comma namedArgument)*) RBrace # FunctionCallOptions | expression callArgumentList # FunctionCall | Payable callArgumentList # PayableConversion | Type LParen typeName RParen # MetaType | (Inc | Dec | Not | BitNot | Delete | Sub) expression # UnaryPrefixOperation | expression (Inc | Dec) # UnarySuffixOperation | expression Exp expression # ExpOperation | expression (Mul | Div | Mod) expression # MulDivModOperation | expression (Add | Sub) expression # AddSubOperation | expression (Shl | Sar | Shr) expression # ShiftOperation | expression BitAnd expression # BitAndOperation | expression BitXor expression # BitXorOperation | expression BitOr expression # BitOrOperation | expression (LessThan | GreaterThan | LessThanOrEqual | GreaterThanOrEqual) expression # OrderComparison | expression (Equal | NotEqual) expression # EqualityComparison | expression And expression # AndOperation | expression Or expression # OrOperation | expression Conditional expression Colon expression # Conditional | expression assignOp expression # Assignment | New typeName # NewExpr | tupleExpression # Tuple | inlineArrayExpression # InlineArray | ( identifier | literal | literalWithSubDenomination | elementaryTypeName[false] ) # PrimaryExpression ; //@doc:inline assignOp: Assign | AssignBitOr | AssignBitXor | AssignBitAnd | AssignShl | AssignSar | AssignShr | AssignAdd | AssignSub | AssignMul | AssignDiv | AssignMod; tupleExpression: LParen (expression? ( Comma expression?)* ) RParen; /** * An inline array expression denotes a statically sized array of the common type of the contained expressions. */ inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack; /** * Besides regular non-keyword Identifiers, some keywords like 'from' and 'error' can also be used as identifiers. */ identifier: Identifier | From | Error | Revert | Global | Transient | Layout | At; literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral; literalWithSubDenomination: numberLiteral SubDenomination; booleanLiteral: True | False; /** * A full string literal consists of either one or several consecutive quoted strings. */ stringLiteral: (NonEmptyStringLiteral | EmptyStringLiteral)+; /** * A full hex string literal that consists of either one or several consecutive hex strings. */ hexStringLiteral: HexString+; /** * A full unicode string literal that consists of either one or several consecutive unicode strings. */ unicodeStringLiteral: UnicodeStringLiteral+; /** * Number literals can be decimal or hexadecimal numbers with an optional unit. */ numberLiteral: DecimalNumber | HexNumber; /** * A curly-braced block of statements. Opens its own scope. */ block: LBrace ( statement | uncheckedBlock )* RBrace; uncheckedBlock: Unchecked block; statement: block | simpleStatement | ifStatement | forStatement | whileStatement | doWhileStatement | continueStatement | breakStatement | tryStatement | returnStatement | emitStatement | revertStatement | assemblyStatement ; //@doc:inline simpleStatement: variableDeclarationStatement | expressionStatement; /** * If statement with optional else part. */ ifStatement: If LParen expression RParen statement (Else statement)?; /** * For statement with optional init, condition and post-loop part. */ forStatement: For LParen (simpleStatement | Semicolon) (expressionStatement | Semicolon) expression? RParen statement; whileStatement: While LParen expression RParen statement; doWhileStatement: Do statement While LParen expression RParen Semicolon; /** * A continue statement. Only allowed inside for, while or do-while loops. */ continueStatement: Continue Semicolon; /** * A break statement. Only allowed inside for, while or do-while loops. */ breakStatement: Break Semicolon; /** * A try statement. The contained expression needs to be an external function call or a contract creation. */ tryStatement: Try expression (Returns LParen returnParameters=parameterList RParen)? block catchClause+; /** * The catch clause of a try statement. */ catchClause: Catch (identifier? LParen (arguments=parameterList) RParen)? block; returnStatement: Return expression? Semicolon; /** * An emit statement. The contained expression needs to refer to an event. */ emitStatement: Emit expression callArgumentList Semicolon; /** * A revert statement. The contained expression needs to refer to an error. */ revertStatement: Revert expression callArgumentList Semicolon; /** * An inline assembly block. * The contents of an inline assembly block use a separate scanner/lexer, i.e. the set of keywords and * allowed identifiers is different inside an inline assembly block. */ assemblyStatement: Assembly AssemblyDialect? assemblyFlags? AssemblyLBrace yulStatement* YulRBrace; /** * Assembly flags. * Comma-separated list of double-quoted strings as flags. */ assemblyFlags: AssemblyBlockLParen AssemblyFlagString (AssemblyBlockComma AssemblyFlagString)* AssemblyBlockRParen; //@doc:inline variableDeclarationList: variableDeclarations+=variableDeclaration (Comma variableDeclarations+=variableDeclaration)*; /** * A tuple of variable names to be used in variable declarations. * May contain empty fields. */ variableDeclarationTuple: LParen (Comma* variableDeclarations+=variableDeclaration) (Comma (variableDeclarations+=variableDeclaration)?)* RParen; /** * A variable declaration statement. * A single variable may be declared without initial value, whereas a tuple of variables can only be * declared with initial value. */ variableDeclarationStatement: ((variableDeclaration (Assign expression)?) | (variableDeclarationTuple Assign expression)) Semicolon; expressionStatement: expression Semicolon; mappingType: Mapping LParen key=mappingKeyType name=identifier? DoubleArrow value=typeName name=identifier? RParen; /** * Only elementary types or user defined types are viable as mapping keys. */ mappingKeyType: elementaryTypeName[false] | identifierPath; /** * A Yul statement within an inline assembly block. * continue and break statements are only valid within for loops. * leave statements are only valid within function bodies. */ yulStatement: yulBlock | yulVariableDeclaration | yulAssignment | yulFunctionCall | yulIfStatement | yulForStatement | yulSwitchStatement | YulLeave | YulBreak | YulContinue | yulFunctionDefinition; yulBlock: YulLBrace yulStatement* YulRBrace; /** * The declaration of one or more Yul variables with optional initial value. * If multiple variables are declared, only a function call is a valid initial value. */ yulVariableDeclaration: (YulLet variables+=YulIdentifier (YulAssign yulExpression)?) | (YulLet variables+=YulIdentifier (YulComma variables+=YulIdentifier)* (YulAssign yulFunctionCall)?); /** * Any expression can be assigned to a single Yul variable, whereas * multi-assignments require a function call on the right-hand side. */ yulAssignment: yulPath YulAssign yulExpression | (yulPath (YulComma yulPath)+) YulAssign yulFunctionCall; yulIfStatement: YulIf cond=yulExpression body=yulBlock; yulForStatement: YulFor init=yulBlock cond=yulExpression post=yulBlock body=yulBlock; //@doc:inline yulSwitchCase: YulCase yulLiteral yulBlock; /** * A Yul switch statement can consist of only a default-case (deprecated) or * one or more non-default cases optionally followed by a default-case. */ yulSwitchStatement: YulSwitch yulExpression ( (yulSwitchCase+ (YulDefault yulBlock)?) | (YulDefault yulBlock) ); yulFunctionDefinition: YulFunction YulIdentifier YulLParen (arguments+=YulIdentifier (YulComma arguments+=YulIdentifier)*)? YulRParen (YulArrow returnParameters+=YulIdentifier (YulComma returnParameters+=YulIdentifier)*)? body=yulBlock; /** * While only identifiers without dots can be declared within inline assembly, * paths containing dots can refer to declarations outside the inline assembly block. */ yulPath: YulIdentifier (YulPeriod (YulIdentifier | YulEVMBuiltin))*; /** * A call to a function with return values can only occur as right-hand side of an assignment or * a variable declaration. */ yulFunctionCall: (YulIdentifier | YulEVMBuiltin) YulLParen (yulExpression (YulComma yulExpression)*)? YulRParen; yulBoolean: YulTrue | YulFalse; yulLiteral: YulDecimalNumber | YulStringLiteral | YulHexNumber | yulBoolean | YulHexStringLiteral; yulExpression: yulPath | yulFunctionCall | yulLiteral; ================================================ FILE: docs/grammar.rst ================================================ **************** Language Grammar **************** .. syntax:autogrammar:: SolidityParser.g4 :root-rule: SolidityParser.sourceUnit :undocumented: :cc-to-dash: .. syntax:autogrammar:: SolidityLexer.g4 :root-rule: SolidityParser.sourceUnit :fragments: :cc-to-dash: ================================================ FILE: docs/index.rst ================================================ Solidity ======== Solidity is an object-oriented, high-level language for implementing smart contracts. Smart contracts are programs that govern the behavior of accounts within the Ethereum state. Solidity is a `curly-bracket language `_ designed to target the Ethereum Virtual Machine (EVM). It is influenced by C++, Python, and JavaScript. You can find more details about which languages Solidity has been inspired by in the :doc:`language influences ` section. Solidity is statically typed, supports inheritance, libraries, and complex user-defined types, among other features. With Solidity, you can create contracts for uses such as voting, crowdfunding, blind auctions, and multi-signature wallets. When deploying contracts, you should use the latest released version of Solidity. Apart from exceptional cases, only the latest version receives `security fixes `_. Furthermore, breaking changes, as well as new features, are introduced regularly. We currently use a 0.y.z version number `to indicate this fast pace of change `_. .. warning:: Solidity recently released the 0.8.x version that introduced a lot of breaking changes. Make sure you read :doc:`the full list <080-breaking-changes>`. Ideas for improving Solidity or this documentation are always welcome, read our :doc:`contributors guide ` for more details. .. Hint:: You can download this documentation as PDF, HTML or Epub by clicking on the versions flyout menu in the bottom-right corner and selecting the preferred download format. Getting Started --------------- **1. Understand the Smart Contract Basics** If you are new to the concept of smart contracts, we recommend you to get started by digging into the "Introduction to Smart Contracts" section, which covers the following: * :ref:`A simple example smart contract ` written in Solidity. * :ref:`Blockchain Basics `. * :ref:`The Ethereum Virtual Machine `. **2. Get to Know Solidity** Once you are accustomed to the basics, we recommend you read the :doc:`"Solidity by Example" ` and “Language Description” sections to understand the core concepts of the language. **3. Install the Solidity Compiler** There are various ways to install the Solidity compiler, simply choose your preferred option and follow the steps outlined on the :ref:`installation page `. .. hint:: You can try out code examples directly in your browser with the `Remix IDE `_. Remix is a web browser-based IDE that allows you to write, deploy and administer Solidity smart contracts, without the need to install Solidity locally. .. warning:: As humans write software, it can have bugs. Therefore, you should follow established software development best practices when writing your smart contracts. This includes code review, testing, audits, and correctness proofs. Smart contract users are sometimes more confident with code than their authors, and blockchains and smart contracts have their own unique issues to watch out for, so before working on production code, make sure you read the :ref:`security_considerations` section. **4. Learn More** If you want to learn more about building decentralized applications on Ethereum, the `Ethereum Developer Resources `_ can help you with further general documentation around Ethereum, and a wide selection of tutorials, tools, and development frameworks. If you have any questions, you can try searching for answers or asking on the `Ethereum StackExchange `_, or our `Gitter channel `_. .. _translations: Translations ------------ Community contributors help translate this documentation into several languages. Note that they have varying degrees of completeness and up-to-dateness. The English version stands as a reference. You can switch between languages by clicking on the flyout menu in the bottom-right corner and selecting the preferred language. * `Chinese `_ * `French `_ * `Indonesian `_ * `Japanese `_ * `Korean `_ * `Persian `_ * `Russian `_ * `Spanish `_ * `Turkish `_ .. note:: We set up a GitHub organization and translation workflow to help streamline the community efforts. Please refer to the translation guide in the `solidity-docs org `_ for information on how to start a new language or contribute to the community translations. Contents ======== :ref:`Keyword Index `, :ref:`Search Page ` .. toctree:: :maxdepth: 2 :caption: Basics introduction-to-smart-contracts.rst solidity-by-example.rst installing-solidity.rst .. toctree:: :maxdepth: 2 :caption: Language Description layout-of-source-files.rst structure-of-a-contract.rst types.rst units-and-global-variables.rst control-structures.rst contracts.rst assembly.rst cheatsheet.rst grammar.rst .. toctree:: :maxdepth: 2 :caption: Compiler using-the-compiler.rst analysing-compilation-output.rst ir-breaking-changes.rst .. toctree:: :maxdepth: 2 :caption: Internals internals/layout_in_storage.rst internals/layout_in_memory.rst internals/layout_in_calldata.rst internals/variable_cleanup.rst internals/source_mappings.rst internals/optimizer.rst metadata.rst abi-spec.rst .. toctree:: :maxdepth: 2 :caption: Advisory content security-considerations.rst bugs.rst 050-breaking-changes.rst 060-breaking-changes.rst 070-breaking-changes.rst 080-breaking-changes.rst .. toctree:: :maxdepth: 2 :caption: Additional Material natspec-format.rst smtchecker.rst yul.rst path-resolution.rst .. toctree:: :maxdepth: 2 :caption: Resources style-guide.rst common-patterns.rst resources.rst contributing.rst language-influences.rst brand-guide.rst ================================================ FILE: docs/installing-solidity.rst ================================================ .. index:: ! installing .. _installing-solidity: ################################ Installing the Solidity Compiler ################################ Versioning ========== Solidity versions follow `Semantic Versioning `_. In addition, patch-level releases with major release 0 (i.e. 0.x.y) will not contain breaking changes. That means code that compiles with version 0.x.y can be expected to compile with 0.x.z where z > y. In addition to releases, we provide **prereleases** and **nightly development builds** to make it easy for developers to try out upcoming features and provide early feedback. Note that such builds contain bleeding-edge code from the development branch and are not guaranteed to be of the same quality as full releases. Despite our best efforts, they might contain undocumented and/or broken changes that will not become a part of an actual release. They are not meant for production use. When deploying contracts, you should use the latest released version of Solidity. This is because breaking changes, as well as new features and bug fixes are introduced regularly. We currently use a 0.x version number `to indicate this fast pace of change `_. Remix ===== *We recommend Remix for small contracts and for quickly learning Solidity.* `Access Remix online `_, you do not need to install anything. If you want to use it without connection to the Internet, download Remix Desktop from `the releases page `_. Remix is also a convenient option for testing nightly builds without installing multiple Solidity versions. Further options on this page detail installing command-line Solidity compiler software on your computer. Choose a command-line compiler if you are working on a larger contract or if you require more compilation options. .. _solcjs: npm / Node.js ============= Use ``npm`` for a convenient and portable way to install ``solcjs``, a Solidity compiler. The ``solcjs`` program has fewer features than the ways to access the compiler described further down this page. The :ref:`commandline-compiler` documentation assumes you are using the full-featured compiler, ``solc``. The usage of ``solcjs`` is documented inside its own `repository `_. Note: The solc-js project is derived from the C++ ``solc`` by using Emscripten, which means that both use the same compiler source code. ``solc-js`` can be used in JavaScript projects directly (such as Remix). Please refer to the solc-js repository for instructions. .. code-block:: bash npm install --global solc .. note:: The command-line executable is named ``solcjs``. The command-line options of ``solcjs`` are not compatible with ``solc`` and tools (such as ``geth``) expecting the behavior of ``solc`` will not work with ``solcjs``. Docker ====== Docker images of Solidity builds are available using the `solc `_ image from the argotorg organization on ghcr.io. Use the ``stable`` tag for the latest released version, and ``nightly`` for potentially unstable changes in the ``develop`` branch. The Docker image runs the compiler executable so that you can pass all compiler arguments to it. For example, the command below pulls the stable version of the ``solc`` image (if you do not have it already), and runs it in a new container, passing the ``--help`` argument. .. code-block:: bash docker run ghcr.io/argotorg/solc:stable --help .. note:: Specific compiler versions are supported as the Docker image tag such as ``ghcr.io/argotorg/solc:0.8.23``. We will be passing the ``stable`` tag here instead of specific version tag to ensure that users get the latest version by default and avoid the issue of an out-of-date version. To use the Docker image to compile Solidity files on the host machine, mount a local folder for input and output, and specify the contract to compile. For example: .. code-block:: bash docker run \ --volume "/tmp/some/local/path/:/sources/" \ ghcr.io/argotorg/solc:stable \ /sources/Contract.sol \ --abi \ --bin \ --output-dir /sources/output/ You can also use the standard JSON interface (which is recommended when using the compiler with tooling). When using this interface, it is not necessary to mount any directories as long as the JSON input is self-contained (i.e. it does not refer to any external files that would have to be :ref:`loaded by the import callback `). .. code-block:: bash docker run ghcr.io/argotorg/solc:stable --standard-json < input.json > output.json Linux Packages ============== We provide :ref:`standalone binaries ` of the compiler that should run on most distributions without any additional installation steps. Ubuntu packages for versions up to 0.8.30 are available in the `ethereum/ethereum PPA `_. However, we have discontinued this distribution method and future versions will not be added there. Some Linux distributions provide their own packages. These packages are not directly maintained by us but usually kept up-to-date by the respective package maintainers. Unofficial, community-maintained scripts for building and installing the compiler are also available for some distributions: - Arch Linux / (AUR): - `solidity `_ (builds from source), - `solidity-bin `_ (uses our standalone binaries). - Nix: - `solc.nix `_ (builds from source). .. note:: Please be aware that these scripts are produced and maintained by users and not vetted in any way by the distro maintainers. Exercise caution when using them. There is also a `snap package `_, however, it is **currently unmaintained**. It is installable in all the `supported Linux distros `_. To install the latest stable version of solc: .. code-block:: bash sudo snap install solc If you want to help testing the latest development version of Solidity with the most recent changes, please use the following: .. code-block:: bash sudo snap install solc --edge .. note:: The ``solc`` snap uses strict confinement. This is the most secure mode for snap packages but it comes with limitations, like accessing only the files in your ``/home`` and ``/media`` directories. For more information, go to `Demystifying Snap Confinement `_. macOS Packages ============== We distribute the Solidity compiler through Homebrew as a build-from-source version. Pre-built bottles are currently not supported. .. code-block:: bash brew update brew upgrade brew tap ethereum/ethereum brew install solidity To install the most recent 0.4.x / 0.5.x version of Solidity you can also use ``brew install solidity@4`` and ``brew install solidity@5``, respectively. If you need a specific version of Solidity you can install a Homebrew formula directly from Github. View `solidity.rb commits on GitHub `_. Copy the commit hash of the version you want and check it out on your machine. .. code-block:: bash git clone https://github.com/ethereum/homebrew-ethereum.git cd homebrew-ethereum git checkout Install it using ``brew``: .. code-block:: bash brew unlink solidity # eg. Install 0.4.8 brew install solidity.rb .. _static-binaries: Static Binaries =============== We maintain a repository containing static builds of past and current compiler versions for all supported platforms at `solc-bin`_. This is also the location where you can find the nightly builds. The repository is not only a quick and easy way for end users to get binaries ready to be used out-of-the-box but it is also meant to be friendly to third-party tools: - The content is mirrored to https://binaries.soliditylang.org where it can be easily downloaded over HTTPS without any authentication, rate limiting or the need to use git. - Content is served with correct ``Content-Type`` headers and lenient CORS configuration so that it can be directly loaded by tools running in the browser. - Binaries do not require installation or unpacking (exception for older Windows builds bundled with necessary DLLs). - We strive for a high level of backward-compatibility. Files, once added, are not removed or moved without providing a symlink/redirect at the old location. They are also never modified in place and should always match the original checksum. The only exception would be broken or unusable files with the potential to cause more harm than good if left as is. - Files are served over both HTTP and HTTPS. As long as you obtain the file list in a secure way (via git, HTTPS, IPFS or just have it cached locally) and verify hashes of the binaries after downloading them, you do not have to use HTTPS for the binaries themselves. The same binaries are in most cases available on the `Solidity release page on GitHub`_. The difference is that we do not generally update old releases on the GitHub release page. This means that we do not rename them if the naming convention changes and we do not add builds for platforms that were not supported at the time of release. This only happens in ``solc-bin``. The ``solc-bin`` repository contains several top-level directories, each representing a single platform. Each one includes a ``list.json`` file listing the available binaries. For example in ``emscripten-wasm32/list.json`` you will find the following information about version 0.7.4: .. code-block:: json { "path": "solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js", "version": "0.7.4", "build": "commit.3f05b770", "longVersion": "0.7.4+commit.3f05b770", "keccak256": "0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3", "sha256": "0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2", "urls": [ "dweb:/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS" ] } This means that: - You can find the binary in the same directory under the name `solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js `_. Note that the file might be a symlink, and you will need to resolve it yourself if you are not using git to download it or your file system does not support symlinks. - The binary is also mirrored at https://binaries.soliditylang.org/emscripten-wasm32/solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js. In this case git is not necessary and symlinks are resolved transparently, either by serving a copy of the file or returning a HTTP redirect. - The file is also available on IPFS at `QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS`_. Please, be aware that the order of items in the ``urls`` array is not predetermined or guaranteed and users should not rely on it. - You can verify the integrity of the binary by comparing its keccak256 hash to ``0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3``. The hash can be computed on the command-line using ``keccak256sum`` utility provided by `sha3sum`_ or `keccak256() function from ethereumjs-util`_ in JavaScript. - You can also verify the integrity of the binary by comparing its sha256 hash to ``0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2``. .. warning:: Due to the strong backwards compatibility requirement the repository contains some legacy elements but you should avoid using them when writing new tools: - Use ``emscripten-wasm32/`` (with a fallback to ``emscripten-asmjs/``) instead of ``bin/`` if you want the best performance. Until version 0.6.1 we only provided asm.js binaries. Starting with 0.6.2 we switched to `WebAssembly builds`_ with much better performance. We have rebuilt the older versions for wasm but the original asm.js files remain in ``bin/``. The new ones had to be placed in a separate directory to avoid name clashes. - Use ``emscripten-asmjs/`` and ``emscripten-wasm32/`` instead of ``bin/`` and ``wasm/`` directories if you want to be sure whether you are downloading a wasm or an asm.js binary. - Use ``list.json`` instead of ``list.js`` and ``list.txt``. The JSON list format contains all the information from the old ones and more. .. warning:: - The solc-bin.ethereum.org domain is no longer supported. Going forward, we recommend any tools which are still using it as the source of Solidity binaries to switch to binaries.soliditylang.org. .. warning:: The binaries are also available at https://argotorg.github.io/solc-bin/ but this page stopped being updated just after the release of version 0.7.2, will not receive any new releases or nightly builds for any platform and does not serve the new directory structure, including non-emscripten builds. If you are using it, please switch to https://binaries.soliditylang.org, which is a drop-in replacement. This allows us to make changes to the underlying hosting in a transparent way and minimize disruption. Unlike the ``argotorg.github.io`` domain, which we do not have any control over, ``binaries.soliditylang.org`` is guaranteed to work and maintain the same URL structure in the long-term. .. _IPFS: https://ipfs.io .. _solc-bin: https://github.com/argotorg/solc-bin/ .. _Solidity release page on GitHub: https://github.com/argotorg/solidity/releases .. _sha3sum: https://github.com/maandree/sha3sum .. _keccak256() function from ethereumjs-util: https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_hash_.md#const-keccak256 .. _WebAssembly builds: https://emscripten.org/docs/compiling/WebAssembly.html .. _QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS: https://gateway.ipfs.io/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS .. _building-from-source: Building from Source ==================== Prerequisites - All Operating Systems ------------------------------------- The following are dependencies for all builds of Solidity: .. Note: This has to be kept in sync with `scripts/ci/install_and_check_minimum_requirements.sh`. +-----------------------------------+-------------------------------------------------------+ | Software | Notes | +===================================+=======================================================+ | `CMake`_ (version 3.21.3+ on | Cross-platform build file generator. | | Windows, 3.13+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Boost`_ (version 1.77+ on | C++ libraries. | | Windows, 1.83+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Git`_ | Command-line tool for retrieving source code. | +-----------------------------------+-------------------------------------------------------+ | `z3`_ (version 4.8.16+, Optional) | For use with SMT checker. | +-----------------------------------+-------------------------------------------------------+ .. _Git: https://git-scm.com/download .. _Boost: https://www.boost.org .. _CMake: https://cmake.org/download/ .. _z3: https://github.com/Z3Prover/z3 .. note:: Solidity versions prior to 0.5.10 can fail to correctly link against Boost versions 1.70+. A possible workaround is to temporarily rename ``/lib/cmake/Boost-1.70.0`` prior to running the cmake command to configure Solidity. Starting from 0.5.10 linking against Boost 1.70+ should work without manual intervention. .. note:: The default build configuration requires a specific Z3 version (the latest one at the time the code was last updated). Changes introduced between Z3 releases often result in slightly different (but still valid) results being returned. Our SMT tests do not account for these differences and will likely fail with a different version than the one they were written for. This does not mean that a build using a different version is faulty. If you pass ``-DSTRICT_Z3_VERSION=OFF`` option to CMake, you can build with any version that satisfies the requirement given in the table above. If you do this, however, please remember to pass the ``--no-smt`` option to ``scripts/tests.sh`` to skip the SMT tests. .. note:: By default the build is performed in *pedantic mode*, which enables extra warnings and tells the compiler to treat all warnings as errors. This forces developers to fix warnings as they arise, so they do not accumulate "to be fixed later". If you are only interested in creating a release build and do not intend to modify the source code to deal with such warnings, you can pass ``-DPEDANTIC=OFF`` option to CMake to disable this mode. Doing this is not recommended for general use but may be necessary when using a toolchain we are not testing with or trying to build an older version with newer tools. If you encounter such warnings, please consider `reporting them `_. Minimum Compiler Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ The following C++ compilers and their minimum versions can build the Solidity codebase: .. Note: Minimum versions for GCC and Clang are based on availability in Ubuntu 24.04. - `GCC `_, version 13.3+ - `Clang `_, version 18.1.3+ - `MSVC `_, version 2019+ Prerequisites - macOS --------------------- For macOS builds, ensure that you have the latest version of `Xcode installed `_. This contains the `Clang C++ compiler `_, the `Xcode IDE `_ and other Apple development tools that are required for building C++ applications on OS X. If you are installing Xcode for the first time, or have just installed a new version then you will need to agree to the license before you can do command-line builds: .. code-block:: bash sudo xcodebuild -license accept Our OS X build script uses `the Homebrew `_ package manager for installing external dependencies. Here's how to `uninstall Homebrew `_, if you ever want to start again from scratch. Prerequisites - Windows ----------------------- You need to install the following dependencies for Windows builds of Solidity: +-----------------------------------+-------------------------------------------------------+ | Software | Notes | +===================================+=======================================================+ | `Visual Studio 2019 Build Tools`_ | C++ compiler | +-----------------------------------+-------------------------------------------------------+ | `Visual Studio 2019`_ (Optional) | C++ compiler and dev environment. | +-----------------------------------+-------------------------------------------------------+ | `Boost`_ (version 1.77+) | C++ libraries. | +-----------------------------------+-------------------------------------------------------+ If you already have one IDE and only need the compiler and libraries, you could install Visual Studio 2019 Build Tools. Visual Studio 2019 provides both IDE and necessary compiler and libraries. So if you have not got an IDE and prefer to develop Solidity, Visual Studio 2019 may be a choice for you to get everything setup easily. Here is the list of components that should be installed in Visual Studio 2019 Build Tools or Visual Studio 2019: * Visual Studio C++ core features * VC++ 2019 v141 toolset (x86,x64) * Windows Universal CRT SDK * Windows 8.1 SDK * C++/CLI support .. _Visual Studio 2019: https://www.visualstudio.com/vs/ .. _Visual Studio 2019 Build Tools: https://visualstudio.microsoft.com/vs/older-downloads/#visual-studio-2019-and-other-products We have a helper script which you can use to install all required external dependencies: .. code-block:: bat scripts\install_deps.ps1 This will install ``boost`` and ``cmake`` to the ``deps`` subdirectory. Clone the Repository -------------------- To clone the source code, execute the following command: .. code-block:: bash git clone --recursive https://github.com/argotorg/solidity.git cd solidity If you want to help develop Solidity, you should fork Solidity and add your personal fork as a second remote: .. code-block:: bash git remote add personal git@github.com:[username]/solidity.git .. note:: This method will result in a pre-release build leading to e.g. a flag being set in each bytecode produced by such a compiler. If you want to re-build a released Solidity compiler, then please use the source tarball on the GitHub release page: https://github.com/argotorg/solidity/releases/download/v0.X.Y/solidity_0.X.Y.tar.gz (not the "Source code" provided by GitHub). Command-Line Build ------------------ **Be sure to install External Dependencies (see above) before build.** Solidity project uses CMake to configure the build. You might want to install `ccache`_ to speed up repeated builds. CMake will pick it up automatically. Building Solidity is quite similar on Linux, macOS and other Unices: .. _ccache: https://ccache.dev/ .. code-block:: bash mkdir build cd build cmake .. && make or even easier on Linux and macOS, you can run: .. code-block:: bash #note: this will install binaries solc and soltest at usr/local/bin ./scripts/build.sh .. warning:: BSD builds should work, but are untested by the Solidity team. And for Windows: .. code-block:: bash mkdir build cd build cmake -G "Visual Studio 16 2019" .. In case you want to use the version of boost installed by ``scripts\install_deps.ps1``, you will additionally need to pass ``-DBoost_ROOT="deps/boost" -DBoost_INCLUDE_DIR="deps/boost/include"`` and ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`` as arguments to the call to ``cmake``. This should result in the creation of **solidity.sln** in that build directory. Double-clicking on that file should result in Visual Studio firing up. We suggest building **Release** configuration, but all others work. Alternatively, you can build for Windows on the command-line, like so: .. code-block:: bash cmake --build . --config Release CMake Options ============= If you are interested what CMake options are available run ``cmake .. -LH``. .. _smt_solvers_build: SMT Solvers ----------- Solidity can optionally use SMT solvers, namely ``z3``, ``cvc5`` and ``Eldarica``, but their presence is checked only at runtime, they are not needed for the build to succeed. .. note:: The emscripten builds require Z3 and will statically link against it instead. The Version String in Detail ============================ The Solidity version string contains four parts: - the version number - pre-release tag, usually set to ``develop.YYYY.MM.DD``, ``pre.N`` or ``nightly.YYYY.MM.DD`` - commit in the format of ``commit.GITHASH`` - platform, which has an arbitrary number of items, containing details about the platform and compiler If there are local modifications, the commit will be postfixed with ``.mod``. These parts are combined as required by SemVer, where the Solidity pre-release tag equals to the SemVer pre-release and the Solidity commit and platform combined make up the SemVer build metadata. Examples: - release: ``0.4.8+commit.60cc1668.Emscripten.clang`` - pre-release: ``0.4.9-pre.3+commit.fb60450bc.Emscripten.clang`` - nightly build: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang`` Important Information About Versioning ====================================== After a release is made, the patch version level is bumped, because we assume that only patch level changes follow. When changes are merged, the version should be bumped according to SemVer and the severity of the change. Finally, a release is always made with the version of the current build, but without the ``prerelease`` specifier. Example: 1. The 0.4.0 release is made. 2. Nightly builds and preerelases have a version of 0.4.1 from now on. 3. Non-breaking changes are introduced --> no change in version. 4. A breaking change is introduced --> version is bumped to 0.5.0. 5. The 0.5.0 release is made. This behavior works well with the :ref:`version pragma `. ================================================ FILE: docs/internals/layout_in_calldata.rst ================================================ .. index: calldata layout ******************* Layout of Call Data ******************* The input data for a function call is assumed to be in the format defined by the :ref:`ABI specification `. Among others, the ABI specification requires arguments to be padded to multiples of 32 bytes. The internal function calls use a different convention. Arguments for the constructor of a contract are directly appended at the end of the contract's code, also in ABI encoding. The constructor will access them through a hard-coded offset, and not by using the ``codesize`` opcode, since this of course changes when appending data to the code. ================================================ FILE: docs/internals/layout_in_memory.rst ================================================ .. index: memory layout **************** Layout in Memory **************** Solidity reserves four 32-byte slots, with specific byte ranges (inclusive of endpoints) being used as follows: - ``0x00`` - ``0x3f`` (64 bytes): scratch space for hashing methods - ``0x40`` - ``0x5f`` (32 bytes): currently allocated memory size (aka. free memory pointer) - ``0x60`` - ``0x7f`` (32 bytes): zero slot Scratch space can be used between statements (i.e. within inline assembly). The zero slot is used as initial value for dynamic memory arrays and should never be written to (the free memory pointer points to ``0x80`` initially). Solidity always places new objects at the free memory pointer and memory is never freed (this might change in the future). Elements in memory arrays in Solidity always occupy multiples of 32 bytes (this is even true for ``bytes1[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory arrays are pointers to memory arrays. The length of a dynamic array is stored at the first slot of the array and followed by the array elements. .. warning:: There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifetime, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one should not expect the free memory to point to zeroed out memory. While it may seem like a good idea to use ``msize`` to arrive at a definitely zeroed out memory area, using such a pointer non-temporarily without updating the free memory pointer can have unexpected results. Differences to Layout in Storage ================================ As described above the layout in memory is different from the layout in :ref:`storage`. Below there are some examples. Example for Difference in Arrays -------------------------------- The following array occupies 32 bytes (1 slot) in storage, but 128 bytes (4 items with 32 bytes each) in memory. .. code-block:: solidity uint8[4] a; Example for Difference in Struct Layout --------------------------------------- The following struct occupies 96 bytes (3 slots of 32 bytes) in storage, but 128 bytes (4 items with 32 bytes each) in memory. .. code-block:: solidity struct S { uint a; uint b; uint8 c; uint8 d; } ================================================ FILE: docs/internals/layout_in_storage.rst ================================================ .. index:: storage, state variable, mapping, transient storage ********************************************************** Layout of State Variables in Storage and Transient Storage ********************************************************** .. _storage-inplace-encoding: .. note:: The rules described in this section apply for both storage and transient storage data locations. The layouts are completely independent and don't interfere with each other's variable locations. Thus storage and transient storage state variables can be safely interleaved without any side effects. Only value types are supported for transient storage. State variables of contracts are stored in storage in a compact way such that multiple values sometimes use the same storage slot. Except for dynamically-sized arrays and mappings (see below), data is stored contiguously item after item starting with the first state variable, which is stored in slot ``0``. For each variable, a size in bytes is determined according to its type. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible, according to the following rules: - The first item in a storage slot is stored lower-order aligned. - Value types use only as many bytes as are necessary to store them. - If a value type does not fit the remaining part of a storage slot, it is stored in the next storage slot. - Structs and array data always start a new slot and their items are packed tightly according to these rules. - Items following struct or array data always start a new storage slot. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract. If allowed by the above rules, state variables from different contracts do share the same storage slot. The elements of structs and arrays are stored after each other, just as if they were given as individual values. If a contract specifies a :ref:`custom storage layout`, the slots assigned to static storage variables are shifted according the value defined as the layout base. Locations of dynamic arrays and mappings are also indirectly affected by this due to shifting of the static slots they are based on. The custom layout is specified in the most derived contract and, following the order explained above, starting from the most base-ward contract's variables, all storage slots are adjusted. In the following example, contract ``C`` inherits from contracts ``A`` and ``B`` and also specifies a custom storage base slot. The result is that all storage variable slots of the inheritance tree are adjusted according to the value specified by ``C``. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.29; struct S { int32 x; bool y; } contract A { uint a; uint128 transient b; uint constant c = 10; uint immutable d = 12; } contract B { uint8[] e; mapping(uint => S) f; uint16 g; uint16 h; bytes16 transient i; S s; int8 k; } contract C is A, B layout at 42 { bytes21 l; uint8[10] m; bytes5[8] n; bytes5 o; } In the example, the storage layout starts with the inherited state variable ``a`` stored directly inside the base slot (slot ``42``). Transient, constant and immutable variables are stored in separate locations, and thus, ``b``, ``i``, ``c`` and ``d`` have no effect on the storage layout. Then we get to the dynamic array ``e`` and mapping ``f``. They both reserve a whole slot whose address will be used to :ref:`calculate` the location where their data is actually stored. The slot cannot be shared with any other variable, because the resulting addresses must be unique. The next two variables, ``g`` and ``h``, need 2 bytes each and can be packed together into slot ``45``, at offsets ``0`` and ``2`` respectively. Since ``s`` is a struct, its two members are packed contiguously, each taking up 5 bytes. Even though they both would still fit in slot ``45``, structs and arrays always start a new slot. Therefore, ``s`` is placed in slot ``46`` and the next variable, ``k``, in slot ``47``. Base contracts, on the other hand, can share slots with derived ones, so ``l`` does not require an new one. Then variable ``m``, which is an array of 10 items, gets into slot ``48`` and takes up 10 bytes. ``n`` is an array as well, but due to the size of its items, cannot fill its first slot perfectly and spills over to the next one. Finally, variable ``o`` ends up in slot ``51``, even though it is of the same type as items of ``n``. As explained before, variables after structs and arrays always start a new slot. Putting it all together, the storage and transient storage layouts of contract ``C`` can be illustrated as follows: - Storage: :: 42 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] 43 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] 44 [ffffffffffffffffffffffffffffffff] 45 [ hhgg] 46 [ yxxxx] 47 [ lllllllllllllllllllllk] 48 [ mmmmmmmmmm] 49 [ nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn] 50 [ nnnnnnnnnn] 51 [ ooooo] - Transient storage: :: 00 [iiiiiiiiiiiiiiiibbbbbbbbbbbbbbbb] Note that the storage specifier affects ``A`` and ``B`` only as a part of ``C``'s inheritance hierarchy. When deployed independently, their storage starts at ``0``: - Storage layout of ``A``: :: 00 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] - Storage layout of ``B``: :: 00 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] 01 [ffffffffffffffffffffffffffffffff] 02 [ hhgg] 03 [ yxxxx] 04 [ k] .. warning:: When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size. It might be beneficial to use reduced-size types if you are dealing with storage values because the compiler will pack multiple elements into one storage slot, and thus, combine multiple reads or writes into a single operation. If you are not reading or writing all the values in a slot at the same time, this can have the opposite effect, though: When one value is written to a multi-value storage slot, the storage slot has to be read first and then combined with the new value such that other data in the same slot is not destroyed. When dealing with function arguments or memory values, there is no inherent benefit because the compiler does not pack these values. Finally, in order to allow the EVM to optimize for this, ensure that you try to order your storage variables and ``struct`` members such that they can be packed tightly. For example, declaring your storage variables in the order of ``uint128, uint128, uint256`` instead of ``uint128, uint256, uint128``, as the former will only take up two slots of storage whereas the latter will take up three. .. note:: The layout of state variables in storage is considered to be part of the external interface of Solidity due to the fact that storage pointers can be passed to libraries. This means that any change to the rules outlined in this section is considered a breaking change of the language and due to its critical nature should be considered very carefully before being executed. In the event of such a breaking change, we would want to release a compatibility mode in which the compiler would generate bytecode supporting the old layout. Mappings and Dynamic Arrays =========================== .. _storage-hashed-encoding: Due to their unpredictable size, mappings and dynamically-sized array types cannot be stored "in between" the state variables preceding and following them. Instead, they are considered to occupy only 32 bytes with regards to the :ref:`rules above ` and the elements they contain are stored starting at a different storage slot that is computed using a Keccak-256 hash. Assume the storage location of the mapping or array ends up being a slot ``p`` after applying :ref:`the storage layout rules `. For dynamic arrays, this slot stores the number of elements in the array (byte arrays and strings are an exception, see :ref:`below `). For mappings, the slot stays empty, but it is still needed to ensure that even if there are two mappings next to each other, their content ends up at different storage locations. Array data is located starting at ``keccak256(p)`` and it is laid out in the same way as statically-sized array data would: One element after the other, potentially sharing storage slots if the elements are not longer than 16 bytes. Dynamic arrays of dynamic arrays apply this rule recursively. The location of element ``x[i][j]``, where the type of ``x`` is ``uint24[][]``, is computed as follows (again, assuming ``x`` itself is stored at slot ``p``): The slot is ``keccak256(keccak256(p) + i) + floor(j / floor(256 / 24))`` and the element can be obtained from the slot data ``v`` using ``(v >> ((j % floor(256 / 24)) * 24)) & type(uint24).max``. The value corresponding to a mapping key ``k`` is located at ``keccak256(h(k) . p)`` where ``.`` is concatenation and ``h`` is a function that is applied to the key depending on its type: - for value types, ``h`` pads the value to 32 bytes in the same way as when storing the value in memory. - for strings and byte arrays, ``h(k)`` is just the unpadded data. If the mapping value is a non-value type, the computed slot marks the start of the data. If the value is of struct type, for example, you have to add an offset corresponding to the struct member to reach the member. As an example, consider the following contract: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; contract C { struct S { uint16 a; uint16 b; uint256 c; } uint x; mapping(uint => mapping(uint => S)) data; } Let us compute the storage location of ``data[4][9].c``. The position of the mapping itself is ``1`` (the variable ``x`` with 32 bytes precedes it). This means ``data[4]`` is stored at ``keccak256(uint256(4) . uint256(1))``. The type of ``data[4]`` is again a mapping and the data for ``data[4][9]`` starts at slot ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1)))``. The slot offset of the member ``c`` inside the struct ``S`` is ``1`` because ``a`` and ``b`` are packed in a single slot. This means the slot for ``data[4][9].c`` is ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``. The type of the value is ``uint256``, so it uses a single slot. .. _bytes-and-string: ``bytes`` and ``string`` ------------------------ ``bytes`` and ``string`` are encoded identically. In general, the encoding is similar to ``bytes1[]``, in the sense that there is a slot for the array itself and a data area that is computed using a ``keccak256`` hash of that slot's position. However, for short values (shorter than 32 bytes) the array elements are stored together with the length in the same slot. In particular: if the data is at most ``31`` bytes long, the elements are stored in the higher-order bytes (left aligned) and the lowest-order byte stores the value ``length * 2``. For byte arrays that store data which is ``32`` or more bytes long, the main slot ``p`` stores ``length * 2 + 1`` and the data is stored as usual in ``keccak256(p)``. This means that you can distinguish a short array from a long array by checking if the lowest bit is set: short (not set) and long (set). .. note:: Handling invalidly encoded slots is currently not supported but may be added in the future. If you are compiling via IR, reading an invalidly encoded slot results in a ``Panic(0x22)`` error. JSON Output =========== .. _storage-layout-top-level: The storage (or transient storage) layout of a contract can be requested via the :ref:`standard JSON interface `. The output is a JSON object containing two keys, ``storage`` and ``types``. The ``storage`` object is an array where each element has the following form: .. code-block:: json { "astId": 2, "contract": "fileA:A", "label": "x", "offset": 0, "slot": "0", "type": "t_uint256" } The example above is the storage layout of ``contract A { uint x; }`` from source unit ``fileA`` and - ``astId`` is the id of the AST node of the state variable's declaration - ``contract`` is the name of the contract including its path as prefix - ``label`` is the name of the state variable - ``offset`` is the offset in bytes within the storage slot according to the encoding - ``slot`` is the storage slot where the state variable resides or starts. This number may be very large and therefore its JSON value is represented as a string. - ``type`` is an identifier used as key to the variable's type information (described in the following) The given ``type``, in this case ``t_uint256`` represents an element in ``types``, which has the form: .. code-block:: json { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32", } where - ``encoding`` how the data is encoded in storage, where the possible values are: - ``inplace``: data is laid out contiguously in storage (see :ref:`above `). - ``mapping``: Keccak-256 hash-based method (see :ref:`above `). - ``dynamic_array``: Keccak-256 hash-based method (see :ref:`above `). - ``bytes``: single slot or Keccak-256 hash-based depending on the data size (see :ref:`above `). - ``label`` is the canonical type name. - ``numberOfBytes`` is the number of used bytes (as a decimal string). Note that if ``numberOfBytes > 32`` this means that more than one slot is used. Some types have extra information besides the four above. Mappings contain its ``key`` and ``value`` types (again referencing an entry in this mapping of types), arrays have its ``base`` type, and structs list their ``members`` in the same format as the top-level ``storage`` (see :ref:`above `). .. note:: The JSON output format of a contract's storage layout is still considered experimental and is subject to change in non-breaking releases of Solidity. The following example shows a contract and both its storage and transient storage layout, containing value and reference types, types that are encoded packed, and nested types. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.28; contract A { struct S { uint128 a; uint128 b; uint[2] staticArray; uint[] dynArray; } uint x; uint transient y; uint w; uint transient z; S s; address addr; address transient taddr; mapping(uint => mapping(address => bool)) map; uint[] array; string s1; bytes b1; } Storage Layout -------------- .. code-block:: json { "storage": [ { "astId": 15, "contract": "fileA:A", "label": "x", "offset": 0, "slot": "0", "type": "t_uint256" }, { "astId": 19, "contract": "fileA:A", "label": "w", "offset": 0, "slot": "1", "type": "t_uint256" }, { "astId": 24, "contract": "fileA:A", "label": "s", "offset": 0, "slot": "2", "type": "t_struct(S)13_storage" }, { "astId": 26, "contract": "fileA:A", "label": "addr", "offset": 0, "slot": "6", "type": "t_address" }, { "astId": 34, "contract": "fileA:A", "label": "map", "offset": 0, "slot": "7", "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))" }, { "astId": 37, "contract": "fileA:A", "label": "array", "offset": 0, "slot": "8", "type": "t_array(t_uint256)dyn_storage" }, { "astId": 39, "contract": "fileA:A", "label": "s1", "offset": 0, "slot": "9", "type": "t_string_storage" }, { "astId": 41, "contract": "fileA:A", "label": "b1", "offset": 0, "slot": "10", "type": "t_bytes_storage" } ], "types": { "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, "t_array(t_uint256)2_storage": { "base": "t_uint256", "encoding": "inplace", "label": "uint256[2]", "numberOfBytes": "64" }, "t_array(t_uint256)dyn_storage": { "base": "t_uint256", "encoding": "dynamic_array", "label": "uint256[]", "numberOfBytes": "32" }, "t_bool": { "encoding": "inplace", "label": "bool", "numberOfBytes": "1" }, "t_bytes_storage": { "encoding": "bytes", "label": "bytes", "numberOfBytes": "32" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => bool)", "numberOfBytes": "32", "value": "t_bool" }, "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => mapping(address => bool))", "numberOfBytes": "32", "value": "t_mapping(t_address,t_bool)" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, "t_struct(S)13_storage": { "encoding": "inplace", "label": "struct A.S", "members": [ { "astId": 3, "contract": "fileA:A", "label": "a", "offset": 0, "slot": "0", "type": "t_uint128" }, { "astId": 5, "contract": "fileA:A", "label": "b", "offset": 16, "slot": "0", "type": "t_uint128" }, { "astId": 9, "contract": "fileA:A", "label": "staticArray", "offset": 0, "slot": "1", "type": "t_array(t_uint256)2_storage" }, { "astId": 12, "contract": "fileA:A", "label": "dynArray", "offset": 0, "slot": "3", "type": "t_array(t_uint256)dyn_storage" } ], "numberOfBytes": "128" }, "t_uint128": { "encoding": "inplace", "label": "uint128", "numberOfBytes": "16" }, "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" } } } Transient Storage Layout ------------------------ .. code-block:: json { "storage": [ { "astId": 17, "contract": "fileA:A", "label": "y", "offset": 0, "slot": "0", "type": "t_uint256" }, { "astId": 21, "contract": "fileA:A", "label": "z", "offset": 0, "slot": "1", "type": "t_uint256" }, { "astId": 28, "contract": "fileA:A", "label": "taddr", "offset": 0, "slot": "2", "type": "t_address" } ], "types": { "t_address": { "encoding": "inplace", "label": "address", "numberOfBytes": "20" }, "t_uint256": { "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" } } } ================================================ FILE: docs/internals/optimizer.rst ================================================ .. index:: optimizer, optimiser, common subexpression elimination, constant propagation .. _optimizer: ************* The Optimizer ************* The Solidity compiler involves optimizations at three different levels (in order of execution): - Optimizations during code generation based on a direct analysis of Solidity code. - Optimizing transformations on the Yul IR code. - Optimizations at the opcode level. The opcode-based optimizer applies a set of `simplification rules `_ to opcodes. It also combines equal code sets and removes unused code. The Yul-based optimizer is much more powerful, because it can work across function calls. For example, arbitrary jumps are not possible in Yul, so it is possible to compute the side-effects of each function. Consider two function calls, where the first does not modify storage and the second does modify storage. If their arguments and return values do not depend on each other, we can reorder the function calls. Similarly, if a function is side-effect free and its result is multiplied by zero, you can remove the function call completely. The codegen-based optimizer affects the initial low-level code produced from the Solidity input. In the legacy pipeline, the bytecode is generated immediately and most of the optimizations of this kind are implicit and not configurable, the only exception being an optimization which changes the order of literals in binary operations. The IR-based pipeline takes a different approach and produces Yul IR closely matching the structure of the Solidity code, with nearly all optimizations deferred to the Yul optimizer module. In that case codegen-level optimization is done only in very limited cases which are difficult to handle in Yul IR, but are straightforward with the high-level information from analysis phase at hand. An example of such an optimization is the bypass of checked arithmetic when incrementing the counter in certain idiomatic ``for`` loops. Currently, the parameter ``--optimize`` activates the opcode-based optimizer for the generated bytecode and the Yul optimizer for the Yul code generated internally, for example for ABI coder v2. One can use ``solc --ir-optimized --optimize`` to produce an optimized Yul IR for a Solidity source. Similarly, one can use ``solc --strict-assembly --optimize`` for a stand-alone Yul mode. .. note:: Some optimizer steps, such as, for example, the `peephole optimizer `_ and the :ref:`unchecked loop increment optimizer ` are always enabled by default and can only be turned off via the :ref:`Standard JSON `. .. note:: An empty optimizer sequence, i.e ``:``, is accepted even without ``--optimize`` in order to fully disable the user-supplied portion of the Yul :ref:`optimizer sequence `, as by default, even when the optimizer is not turned on, the :ref:`unused pruner ` step will be run. You can find more details on both optimizer modules and their optimization steps below. Benefits of Optimizing Solidity Code ==================================== Overall, the optimizer tries to simplify complicated expressions, which reduces both code size and execution cost, i.e., it can reduce gas needed for contract deployment as well as for external calls made to the contract. It also specializes or inlines functions. Especially function inlining is an operation that can cause much bigger code, but it is often done because it results in opportunities for more simplifications. Differences between Optimized and Non-Optimized Code ==================================================== Generally, the most visible difference is that constant expressions are evaluated at compile time. When it comes to the ASM output, one can also notice a reduction of equivalent or duplicate code blocks (compare the output of the flags ``--asm`` and ``--asm --optimize``). However, when it comes to the Yul/intermediate-representation, there can be significant differences, for example, functions may be inlined, combined, or rewritten to eliminate redundancies, etc. (compare the output between the flags ``--ir`` and ``--optimize --ir-optimized``). .. _optimizer-parameter-runs: Optimizer Parameter Runs ======================== The number of runs (``--optimize-runs``) specifies roughly how often each opcode of the deployed code will be executed across the life-time of the contract. This means it is a trade-off parameter between code size (deploy cost) and code execution cost (cost after deployment). A "runs" parameter of "1" will produce short but expensive code. In contrast, a larger "runs" parameter will produce longer but more gas efficient code. The maximum value of the parameter is ``2**32-1``. .. note:: A common misconception is that this parameter specifies the number of iterations of the optimizer. This is not true: The optimizer will always run as many times as it can still improve the code. Opcode-Based Optimizer Module ============================= The opcode-based optimizer module operates on assembly code. It splits the sequence of instructions into basic blocks at ``JUMPs`` and ``JUMPDESTs``. Inside these blocks, the optimizer analyzes the instructions and records every modification to the stack, memory, or storage as an expression which consists of an instruction and a list of arguments which are pointers to other expressions. Additionally, the opcode-based optimizer uses a component called "CommonSubexpressionEliminator" that, amongst other tasks, finds expressions that are always equal (on every input) and combines them into an expression class. It first tries to find each new expression in a list of already known expressions. If no such matches are found, it simplifies the expression according to rules like ``constant + constant = sum_of_constants`` or ``X * 1 = X``. Since this is a recursive process, we can also apply the latter rule if the second factor is a more complex expression which we know always evaluates to one. Certain optimizer steps symbolically track the storage and memory locations. For example, this information is used to compute Keccak-256 hashes that can be evaluated during compile time. Consider the sequence: .. code-block:: none PUSH 32 PUSH 0 CALLDATALOAD PUSH 100 DUP2 MSTORE KECCAK256 or the equivalent Yul .. code-block:: yul let x := calldataload(0) mstore(x, 100) let value := keccak256(x, 32) In this case, the optimizer tracks the value at a memory location ``calldataload(0)`` and then realizes that the Keccak-256 hash can be evaluated at compile time. This only works if there is no other instruction that modifies memory between the ``mstore`` and ``keccak256``. So if there is an instruction that writes to memory (or storage), then we need to erase the knowledge of the current memory (or storage). There is, however, an exception to this erasing, when we can easily see that the instruction doesn't write to a certain location. For example, .. code-block:: yul let x := calldataload(0) mstore(x, 100) // Current knowledge memory location x -> 100 let y := add(x, 32) // Does not clear the knowledge that x -> 100, since y does not write to [x, x + 32) mstore(y, 200) // This Keccak-256 can now be evaluated let value := keccak256(x, 32) Therefore, modifications to storage and memory locations, of say location ``l``, must erase knowledge about storage or memory locations which may be equal to ``l``. More specifically, for storage, the optimizer has to erase all knowledge of symbolic locations, that may be equal to ``l`` and for memory, the optimizer has to erase all knowledge of symbolic locations that may not be at least 32 bytes away. If ``m`` denotes an arbitrary location, then this decision on erasure is done by computing the value ``sub(l, m)``. For storage, if this value evaluates to a literal that is non-zero, then the knowledge about ``m`` will be kept. For memory, if the value evaluates to a literal that is between ``32`` and ``2**256 - 32``, then the knowledge about ``m`` will be kept. In all other cases, the knowledge about ``m`` will be erased. After this process, we know which expressions have to be on the stack at the end, and have a list of modifications to memory and storage. This information is stored together with the basic blocks and is used to link them. Furthermore, knowledge about the stack, storage and memory configuration is forwarded to the next block(s). If we know the targets of all ``JUMP`` and ``JUMPI`` instructions, we can build a complete control flow graph of the program. If there is only one target we do not know (this can happen as in principle, jump targets can be computed from inputs), we have to erase all knowledge about the input state of a block as it can be the target of the unknown ``JUMP``. If the opcode-based optimizer module finds a ``JUMPI`` whose condition evaluates to a constant, it transforms it to an unconditional jump. As the last step, the code in each block is re-generated. The optimizer creates a dependency graph from the expressions on the stack at the end of the block, and it drops every operation that is not part of this graph. It generates code that applies the modifications to memory and storage in the order they were made in the original code (dropping modifications which were found not to be needed). Finally, it generates all values that are required to be on the stack in the correct place. These steps are applied to each basic block and the newly generated code is used as replacement if it is smaller. If a basic block is split at a ``JUMPI`` and during the analysis, the condition evaluates to a constant, the ``JUMPI`` is replaced based on the value of the constant. Thus code like .. code-block:: solidity uint x = 7; data[7] = 9; if (data[x] != x + 2) // this condition is never true return 2; else return 1; simplifies to this: .. code-block:: solidity data[7] = 9; return 1; Simple Inlining --------------- Since Solidity version 0.8.2, there is another optimizer step that replaces certain jumps to blocks containing "simple" instructions ending with a "jump" by a copy of these instructions. This corresponds to inlining of simple, small Solidity or Yul functions. In particular, the sequence ``PUSHTAG(tag) JUMP`` may be replaced, whenever the ``JUMP`` is marked as jump "into" a function and behind ``tag`` there is a basic block (as described above for the "CommonSubexpressionEliminator") that ends in another ``JUMP`` which is marked as a jump "out of" a function. In particular, consider the following prototypical example of assembly generated for a call to an internal Solidity function: .. code-block:: text tag_return tag_f jump // in tag_return: ...opcodes after call to f... tag_f: ...body of function f... jump // out As long as the body of the function is a continuous basic block, the "Inliner" can replace ``tag_f jump`` by the block at ``tag_f`` resulting in: .. code-block:: text tag_return ...body of function f... jump tag_return: ...opcodes after call to f... tag_f: ...body of function f... jump // out Now ideally, the other optimizer steps described above will result in the return tag push being moved towards the remaining jump resulting in: .. code-block:: text ...body of function f... tag_return jump tag_return: ...opcodes after call to f... tag_f: ...body of function f... jump // out In this situation the "PeepholeOptimizer" will remove the return jump. Ideally, all of this can be done for all references to ``tag_f`` leaving it unused, s.t. it can be removed, yielding: .. code-block:: text ...body of function f... ...opcodes after call to f... So the call to function ``f`` is inlined and the original definition of ``f`` can be removed. Inlining like this is attempted, whenever a heuristics suggests that inlining is cheaper over the lifetime of a contract than not inlining. This heuristics depends on the size of the function body, the number of other references to its tag (approximating the number of calls to the function) and the expected number of executions of the contract (the global optimizer parameter "runs"). Yul-Based Optimizer Module ========================== The Yul-based optimizer consists of several stages and components that all transform the AST in a semantically equivalent way. The goal is to end up either with code that is shorter or at least only marginally longer but will allow further optimization steps. .. warning:: Since the optimizer is under heavy development, the information here might be outdated. If you rely on a certain functionality, please reach out to the team directly. The optimizer currently follows a purely greedy strategy and does not do any backtracking. All components of the Yul-based optimizer module are explained below. The following transformation steps are the main components: - SSATransform - CommonSubexpressionEliminator - ExpressionSimplifier - UnusedAssignEliminator - FullInliner .. _optimizer-steps: Optimizer Steps --------------- This is a list of all steps the Yul-based optimizer sorted alphabetically. You can find more information on the individual steps and their sequence below. ============ =============================== Abbreviation Full name ============ =============================== ``f`` :ref:`block-flattener` ``l`` :ref:`circular-references-pruner` ``c`` :ref:`common-subexpression-eliminator` ``C`` :ref:`conditional-simplifier` ``U`` :ref:`conditional-unsimplifier` ``n`` :ref:`control-flow-simplifier` ``D`` :ref:`dead-code-eliminator` ``E`` :ref:`equal-store-eliminator` ``v`` :ref:`equivalent-function-combiner` ``e`` :ref:`expression-inliner` ``j`` :ref:`expression-joiner` ``s`` :ref:`expression-simplifier` ``x`` :ref:`expression-splitter` ``I`` :ref:`for-loop-condition-into-body` ``O`` :ref:`for-loop-condition-out-of-body` ``o`` :ref:`for-loop-init-rewriter` ``i`` :ref:`full-inliner` ``g`` :ref:`function-grouper` ``h`` :ref:`function-hoister` ``F`` :ref:`function-specializer` ``T`` :ref:`literal-rematerialiser` ``L`` :ref:`load-resolver` ``M`` :ref:`loop-invariant-code-motion` ``m`` :ref:`rematerialiser` ``V`` :ref:`ssa-reverser` ``a`` :ref:`ssa-transform` ``t`` :ref:`structural-simplifier` ``r`` :ref:`unused-assign-eliminator` ``p`` :ref:`unused-function-parameter-pruner` ``S`` :ref:`unused-store-eliminator` ``u`` :ref:`unused-pruner` ``d`` :ref:`var-decl-initializer` ============ =============================== Some steps depend on properties ensured by ``BlockFlattener``, ``FunctionGrouper``, ``ForLoopInitRewriter``. For this reason the Yul optimizer always applies them before applying any steps supplied by the user. .. _selecting-optimizations: Selecting Optimizations ----------------------- By default the optimizer applies its predefined sequence of optimization steps to the generated assembly. You can override this sequence and supply your own using the ``--yul-optimizations`` option: .. code-block:: bash solc --optimize --ir-optimized --yul-optimizations 'dhfoD[xarrscLMcCTU]uljmul:fDnTOcmu' The order of steps is significant and affects the quality of the output. Moreover, applying a step may uncover new optimization opportunities for others that were already applied, so repeating steps is often beneficial. The sequence inside ``[...]`` will be applied multiple times in a loop until the Yul code remains unchanged or until the maximum number of rounds (currently 12) has been reached. Brackets (``[]``) may be used multiple times in a sequence, but can not be nested. An important thing to note, is that there are some hardcoded steps that are always run before and after the user-supplied sequence, or the default sequence if one was not supplied by the user. The cleanup sequence delimiter ``:`` is optional, and is used to supply a custom cleanup sequence in order to replace the default one. If omitted, the optimizer will simply apply the default cleanup sequence. In addition, the delimiter may be placed at the beginning of the user-supplied sequence, which will result in the optimization sequence being empty, whereas conversely, if placed at the end of the sequence, will be treated as an empty cleanup sequence. Preprocessing ------------- The preprocessing components perform transformations to get the program into a certain normal form that is easier to work with. This normal form is kept during the rest of the optimization process. .. _disambiguator: Disambiguator ^^^^^^^^^^^^^ The disambiguator takes an AST and returns a fresh copy where all identifiers have unique names in the input AST. This is a prerequisite for all other optimizer stages. One of the benefits is that identifier lookup does not need to take scopes into account which simplifies the analysis needed for other steps. All subsequent stages have the property that all names stay unique. This means if a new identifier needs to be introduced, a new unique name is generated. .. _function-hoister: FunctionHoister ^^^^^^^^^^^^^^^ The function hoister moves all function definitions to the end of the topmost block. This is a semantically equivalent transformation as long as it is performed after the disambiguation stage. The reason is that moving a definition to a higher-level block cannot decrease its visibility and it is impossible to reference variables defined in a different function. The benefit of this stage is that function definitions can be looked up more easily and functions can be optimized in isolation without having to traverse the AST completely. .. _function-grouper: FunctionGrouper ^^^^^^^^^^^^^^^ The function grouper has to be applied after the Disambiguator and the FunctionHoister. Its effect is that all topmost elements that are not function definitions are moved into a single block which is the first statement of the root block. After this step, a program has the following normal form: .. code-block:: text { I F... } Where ``I`` is a (potentially empty) block that does not contain any function definitions (not even recursively) and ``F`` is a list of function definitions such that no function contains a function definition. The benefit of this stage is that we always know where the list of functions begins. .. _for-loop-condition-into-body: ForLoopConditionIntoBody ^^^^^^^^^^^^^^^^^^^^^^^^ This transformation moves the loop-iteration condition of a ``for`` loop into loop body. We need this transformation because :ref:`expression-splitter` will not apply to iteration condition expressions (the ``C`` in the following example). .. code-block:: text for { Init... } C { Post... } { Body... } is transformed to .. code-block:: text for { Init... } 1 { Post... } { if iszero(C) { break } Body... } This transformation can also be useful when paired with LoopInvariantCodeMotion, since invariants in the loop-invariant conditions can then be taken outside the loop. .. _for-loop-init-rewriter: ForLoopInitRewriter ^^^^^^^^^^^^^^^^^^^ This transformation moves the initialization part of a ``for`` loop to before the loop: .. code-block:: text for { Init... } C { Post... } { Body... } is transformed to .. code-block:: text Init... for {} C { Post... } { Body... } This eases the rest of the optimization process because we can ignore the complicated scoping rules of the ``for`` loop initialization block. .. _var-decl-initializer: VarDeclInitializer ^^^^^^^^^^^^^^^^^^ This step rewrites variable declarations so that all of them are initialized. Declarations like ``let x, y`` are split into multiple declaration statements. Only supports initializing with the zero literal for now. Pseudo-SSA Transformation ------------------------- The purpose of this components is to get the program into a longer form, so that other components can more easily work with it. The final representation will be similar to a static-single-assignment (SSA) form, with the difference that it does not make use of explicit "phi" functions which combines the values from different branches of control flow because such a feature does not exist in the Yul language. Instead, when control flow merges, if a variable is re-assigned in one of the branches, a new SSA variable is declared to hold its current value, so that the following expressions still only need to reference SSA variables. An example transformation is the following: .. code-block:: yul { let a := calldataload(0) let b := calldataload(0x20) if gt(a, 0) { b := mul(b, 0x20) } a := add(a, 1) sstore(a, add(b, 0x20)) } When all the following transformation steps are applied, the program will look as follows: .. code-block:: yul { let _1 := 0 let a_9 := calldataload(_1) let a := a_9 let _2 := 0x20 let b_10 := calldataload(_2) let b := b_10 let _3 := 0 let _4 := gt(a_9, _3) if _4 { let _5 := 0x20 let b_11 := mul(b_10, _5) b := b_11 } let b_12 := b let _6 := 1 let a_13 := add(a_9, _6) let _7 := 0x20 let _8 := add(b_12, _7) sstore(a_13, _8) } Note that the only variable that is re-assigned in this snippet is ``b``. This re-assignment cannot be avoided because ``b`` has different values depending on the control flow. All other variables never change their value once they are defined. The advantage of this property is that variables can be freely moved around and references to them can be exchanged by their initial value (and vice-versa), as long as these values are still valid in the new context. Of course, the code here is far from being optimized. To the contrary, it is much longer. The hope is that this code will be easier to work with and furthermore, there are optimizer steps that undo these changes and make the code more compact again at the end. .. _expression-splitter: ExpressionSplitter ^^^^^^^^^^^^^^^^^^ The expression splitter turns expressions like ``add(mload(0x123), mul(mload(0x456), 0x20))`` into a sequence of declarations of unique variables that are assigned sub-expressions of that expression so that each function call has only variables as arguments. The above would be transformed into .. code-block:: yul { let _1 := 0x20 let _2 := 0x456 let _3 := mload(_2) let _4 := mul(_3, _1) let _5 := 0x123 let _6 := mload(_5) let z := add(_6, _4) } Note that this transformation does not change the order of opcodes or function calls. It is not applied to loop iteration-condition, because the loop control flow does not allow this "outlining" of the inner expressions in all cases. We can sidestep this limitation by applying :ref:`for-loop-condition-into-body` to move the iteration condition into loop body. The final program should be in an *expression-split form*, where (with the exception of loop conditions) function calls cannot appear nested inside expressions and all function call arguments have to be variables. The benefits of this form are that it is much easier to re-order the sequence of opcodes and it is also easier to perform function call inlining. Furthermore, it is simpler to replace individual parts of expressions or re-organize the "expression tree". The drawback is that such code is much harder to read for humans. .. _ssa-transform: SSATransform ^^^^^^^^^^^^ This stage tries to replace repeated assignments to existing variables by declarations of new variables as much as possible. The reassignments are still there, but all references to the reassigned variables are replaced by the newly declared variables. Example: .. code-block:: yul { let a := 1 mstore(a, 2) a := 3 } is transformed to .. code-block:: yul { let a_1 := 1 let a := a_1 mstore(a_1, 2) let a_3 := 3 a := a_3 } Exact semantics: For any variable ``a`` that is assigned to somewhere in the code (variables that are declared with value and never re-assigned are not modified) perform the following transforms: - replace ``let a := v`` by ``let a_i := v let a := a_i`` - replace ``a := v`` by ``let a_i := v a := a_i`` where ``i`` is a number such that ``a_i`` is yet unused. Furthermore, always record the current value of ``i`` used for ``a`` and replace each reference to ``a`` by ``a_i``. The current value mapping is cleared for a variable ``a`` at the end of each block in which it was assigned to and at the end of the ``for`` loop init block if it is assigned inside the ``for`` loop body or post block. If a variable's value is cleared according to the rule above and the variable is declared outside the block, a new SSA variable will be created at the location where control flow joins, this includes the beginning of loop post/body block and the location right after ``if``/``switch``/``for``/block statement. After this stage, the UnusedAssignEliminator is recommended to remove the unnecessary intermediate assignments. This stage provides best results if the ExpressionSplitter and the CommonSubexpressionEliminator are run right before it, because then it does not generate excessive amounts of variables. On the other hand, the CommonSubexpressionEliminator could be more efficient if run after the SSA transform. .. _unused-assign-eliminator: UnusedAssignEliminator ^^^^^^^^^^^^^^^^^^^^^^ The SSA transform always generates an assignment of the form ``a := a_i``, even though these might be unnecessary in many cases, like the following example: .. code-block:: yul { let a := 1 a := mload(a) a := sload(a) sstore(a, 1) } The SSA transform converts this snippet to the following: .. code-block:: yul { let a_1 := 1 let a := a_1 let a_2 := mload(a_1) a := a_2 let a_3 := sload(a_2) a := a_3 sstore(a_3, 1) } The UnusedAssignEliminator removes all the three assignments to ``a``, because the value of ``a`` is not used and thus turn this snippet into strict SSA form: .. code-block:: yul { let a_1 := 1 let a_2 := mload(a_1) let a_3 := sload(a_2) sstore(a_3, 1) } Of course the intricate parts of determining whether an assignment is unused or not are connected to joining control flow. The component works as follows in detail: The AST is traversed twice: in an information gathering step and in the actual removal step. During information gathering, we maintain a mapping from assignment statements to the three states "unused", "undecided" and "used" which signifies whether the assigned value will be used later by a reference to the variable. When an assignment is visited, it is added to the mapping in the "undecided" state (see remark about ``for`` loops below) and every other assignment to the same variable that is still in the "undecided" state is changed to "unused". When a variable is referenced, the state of any assignment to that variable still in the "undecided" state is changed to "used". At points where control flow splits, a copy of the mapping is handed over to each branch. At points where control flow joins, the two mappings coming from the two branches are combined in the following way: Statements that are only in one mapping or have the same state are used unchanged. Conflicting values are resolved in the following way: - "unused", "undecided" -> "undecided" - "unused", "used" -> "used" - "undecided", "used" -> "used" For ``for`` loops, the condition, body and post-part are visited twice, taking the joining control-flow at the condition into account. In other words, we create three control flow paths: Zero runs of the loop, one run and two runs and then combine them at the end. Simulating a third run or even more is unnecessary, which can be seen as follows: A state of an assignment at the beginning of the iteration will deterministically result in a state of that assignment at the end of the iteration. Let this state mapping function be called ``f``. The combination of the three different states ``unused``, ``undecided`` and ``used`` as explained above is the ``max`` operation where ``unused = 0``, ``undecided = 1`` and ``used = 2``. The proper way would be to compute .. code-block:: none max(s, f(s), f(f(s)), f(f(f(s))), ...) as state after the loop. Since ``f`` just has a range of three different values, iterating it has to reach a cycle after at most three iterations, and thus ``f(f(f(s)))`` has to equal one of ``s``, ``f(s)``, or ``f(f(s))`` and thus .. code-block:: none max(s, f(s), f(f(s))) = max(s, f(s), f(f(s)), f(f(f(s))), ...) In summary, running the loop at most twice is enough because there are only three different states. For ``switch`` statements that have a default case, there is no control-flow part that skips the ``switch``. When a variable goes out of scope, all statements still in the "undecided" state are changed to "unused", unless the variable is the return parameter of a function - there, the state changes to "used". In the second traversal, all assignments that are in the "unused" state are removed. This step is usually run right after the SSA transform to complete the generation of the pseudo-SSA. Tools ----- Movability ^^^^^^^^^^ Movability is a property of an expression. It roughly means that the expression is side-effect free and its evaluation only depends on the values of variables and the call-constant state of the environment. Most expressions are movable. The following parts make an expression non-movable: - function calls (might be relaxed in the future if all statements in the function are movable) - opcodes that (can) have side-effects (like ``call`` or ``selfdestruct``) - opcodes that read or write memory, storage or external state information - opcodes that depend on the current PC, memory size or returndata size DataflowAnalyzer ^^^^^^^^^^^^^^^^ The DataflowAnalyzer is not an optimizer step itself but is used as a tool by other components. While traversing the AST, it tracks the current value of each variable, as long as that value is a movable expression. It records the variables that are part of the expression that is currently assigned to each other variable. Upon each assignment to a variable ``a``, the current stored value of ``a`` is updated and all stored values of all variables ``b`` are cleared whenever ``a`` is part of the currently stored expression for ``b``. At control-flow joins, knowledge about variables is cleared if they have or would be assigned in any of the control-flow paths. For instance, upon entering a ``for`` loop, all variables are cleared that will be assigned during the body or the post block. Expression-Scale Simplifications -------------------------------- These simplification passes change expressions and replace them by equivalent and hopefully simpler expressions. .. _common-subexpression-eliminator: CommonSubexpressionEliminator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This step uses the DataflowAnalyzer and replaces subexpressions that syntactically match the current value of a variable by a reference to that variable. This is an equivalence transform because such subexpressions have to be movable. All subexpressions that are identifiers themselves are replaced by their current value if the value is an identifier. The combination of the two rules above allow to compute a local value numbering, which means that if two variables have the same value, one of them will always be unused. The UnusedPruner or the UnusedAssignEliminator will then be able to fully eliminate such variables. This step is especially efficient if the ExpressionSplitter is run before. If the code is in pseudo-SSA form, the values of variables are available for a longer time and thus we have a higher chance of expressions to be replaceable. The ExpressionSimplifier will be able to perform better replacements if the CommonSubexpressionEliminator was run right before it. .. _expression-simplifier: ExpressionSimplifier ^^^^^^^^^^^^^^^^^^^^ The ExpressionSimplifier uses the DataflowAnalyzer and makes use of a list of equivalence transforms on expressions like ``X + 0 -> X`` to simplify the code. It tries to match patterns like ``X + 0`` on each subexpression. During the matching procedure, it resolves variables to their currently assigned expressions to be able to match more deeply nested patterns even when the code is in pseudo-SSA form. Some of the patterns like ``X - X -> 0`` can only be applied as long as the expression ``X`` is movable, because otherwise it would remove its potential side-effects. Since variable references are always movable, even if their current value might not be, the ExpressionSimplifier is again more powerful in split or pseudo-SSA form. .. _literal-rematerialiser: LiteralRematerialiser ^^^^^^^^^^^^^^^^^^^^^ To be documented. .. _load-resolver: LoadResolver ^^^^^^^^^^^^ Optimisation stage that replaces expressions of type ``sload(x)`` and ``mload(x)`` by the value currently stored in storage resp. memory, if known. Works best if the code is in SSA form. Prerequisites: Disambiguator, ForLoopInitRewriter. Statement-Scale Simplifications ------------------------------- .. _circular-references-pruner: CircularReferencesPruner ^^^^^^^^^^^^^^^^^^^^^^^^ This stage removes functions that call each other but are neither externally referenced nor referenced from the outermost context. .. _conditional-simplifier: ConditionalSimplifier ^^^^^^^^^^^^^^^^^^^^^ The ConditionalSimplifier inserts assignments to condition variables if the value can be determined from the control-flow. Destroys SSA form. Currently, this tool is very limited, mostly because we do not yet have support for boolean types. Since conditions only check for expressions being nonzero, we cannot assign a specific value. Current features: - ``switch`` cases: insert `` := `` - after ``if`` statement with terminating control-flow, insert `` := 0`` Future features: - allow replacements by ``1`` - take termination of user-defined functions into account Works best with SSA form and if dead code removal has run before. Prerequisite: Disambiguator. .. _conditional-unsimplifier: ConditionalUnsimplifier ^^^^^^^^^^^^^^^^^^^^^^^ Reverse of ConditionalSimplifier. .. _control-flow-simplifier: ControlFlowSimplifier ^^^^^^^^^^^^^^^^^^^^^ Simplifies several control-flow structures: - replace ``if`` with empty body with ``pop(condition)`` - remove empty default ``switch`` case - remove empty ``switch`` case if no default case exists - replace ``switch`` with no cases with ``pop(expression)`` - turn ``switch`` with single case into ``if`` - replace ``switch`` with only default case with ``pop(expression)`` and body - replace ``switch`` with const expr with matching case body - replace ``for`` with terminating control flow and without other ``break``/``continue`` by ``if`` - remove ``leave`` at the end of a function. None of these operations depend on the data flow. The StructuralSimplifier performs similar tasks that do depend on data flow. The ControlFlowSimplifier does record the presence or absence of ``break`` and ``continue`` statements during its traversal. Prerequisite: Disambiguator, FunctionHoister, ForLoopInitRewriter. Important: Introduces EVM opcodes and thus can only be used on EVM code for now. .. _dead-code-eliminator: DeadCodeEliminator ^^^^^^^^^^^^^^^^^^ This optimization stage removes unreachable code. Unreachable code is any code within a block which is preceded by a ``leave``, ``return``, ``invalid``, ``break``, ``continue``, ``selfdestruct``, ``revert`` or by a call to a user-defined function that recurses infinitely. Function definitions are retained as they might be called by earlier code and thus are considered reachable. Because variables declared in a ``for`` loop's init block have their scope extended to the loop body, we require ForLoopInitRewriter to run before this step. Prerequisites: ForLoopInitRewriter, FunctionHoister, FunctionGrouper. .. _equal-store-eliminator: EqualStoreEliminator ^^^^^^^^^^^^^^^^^^^^ This steps removes ``mstore(k, v)`` and ``sstore(k, v)`` calls if there was a previous call to ``mstore(k, v)`` / ``sstore(k, v)``, no other store in between and the values of ``k`` and ``v`` did not change. This simple step is effective if run after the SSATransform and the CommonSubexpressionEliminator, because SSA will make sure that the variables will not change and the CommonSubexpressionEliminator reuses exactly the same variable if the value is known to be the same. Prerequisites: Disambiguator, ForLoopInitRewriter. .. _unused-pruner: UnusedPruner ^^^^^^^^^^^^ This step removes the definitions of all functions that are never referenced. It also removes declarations of variables that are never referenced. If a declaration assigns a value that is not movable, the expression is retained, but its value is discarded. All movable expression statements (expressions that are not assigned) are removed. .. _structural-simplifier: StructuralSimplifier ^^^^^^^^^^^^^^^^^^^^ This is a general step that performs various kinds of simplifications on a structural level: - replace ``if`` statement with empty body by ``pop(condition)`` - replace ``if`` statement with true condition by its body - remove ``if`` statement with false condition - turn ``switch`` with single case into ``if`` - replace ``switch`` with only default case by ``pop(expression)`` and body - replace ``switch`` with literal expression by matching case body - replace ``for`` loop with false condition by its initialization part This component uses the DataflowAnalyzer. .. _block-flattener: BlockFlattener ^^^^^^^^^^^^^^ This stage eliminates nested blocks by inserting the statements in the inner block at the appropriate place in the outer block. It depends on the FunctionGrouper and does not flatten the outermost block to keep the form produced by the FunctionGrouper. .. code-block:: yul { { let x := 2 { let y := 3 mstore(x, y) } } } is transformed to .. code-block:: yul { { let x := 2 let y := 3 mstore(x, y) } } As long as the code is disambiguated, this does not cause a problem because the scopes of variables can only grow. .. _loop-invariant-code-motion: LoopInvariantCodeMotion ^^^^^^^^^^^^^^^^^^^^^^^ This optimization moves movable SSA variable declarations outside the loop. Only statements at the top level in a loop's body or post block are considered, i.e variable declarations inside conditional branches will not be moved out of the loop. ExpressionSplitter and SSATransform should be run upfront to obtain better results. Prerequisites: Disambiguator, ForLoopInitRewriter, FunctionHoister. Function-Level Optimizations ---------------------------- .. _function-specializer: FunctionSpecializer ^^^^^^^^^^^^^^^^^^^ This step specializes the function with its literal arguments. If a function, say, ``function f(a, b) { sstore (a, b) }``, is called with literal arguments, for example, ``f(x, 5)``, where ``x`` is an identifier, it could be specialized by creating a new function ``f_1`` that takes only one argument, i.e., .. code-block:: yul function f_1(a_1) { let b_1 := 5 sstore(a_1, b_1) } Other optimization steps will be able to make more simplifications to the function. The optimization step is mainly useful for functions that would not be inlined. Prerequisites: Disambiguator, FunctionHoister. LiteralRematerialiser is recommended as a prerequisite, even though it's not required for correctness. .. _unused-function-parameter-pruner: UnusedFunctionParameterPruner ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This step removes unused parameters in a function. If a parameter is unused, like ``c`` and ``y`` in, ``function f(a,b,c) -> x, y { x := div(a,b) }``, we remove the parameter and create a new "linking" function as follows: .. code-block:: yul function f(a,b) -> x { x := div(a,b) } function f2(a,b,c) -> x, y { x := f(a,b) } and replace all references to ``f`` by ``f2``. The inliner should be run afterwards to make sure that all references to ``f2`` are replaced by ``f``. Prerequisites: Disambiguator, FunctionHoister, LiteralRematerialiser. The step LiteralRematerialiser is not required for correctness. It helps deal with cases such as: ``function f(x) -> y { revert(y, y} }`` where the literal ``y`` will be replaced by its value ``0``, allowing us to rewrite the function. .. index:: ! UnusedStoreEliminator .. _unused-store-eliminator: UnusedStoreEliminator ^^^^^^^^^^^^^^^^^^^^^ Optimizer component that removes redundant ``sstore`` and memory store statements. In case of an ``sstore``, if all outgoing code paths revert (due to an explicit ``revert()``, ``invalid()``, or infinite recursion) or lead to another ``sstore`` for which the optimizer can tell that it will overwrite the first store, the statement will be removed. However, if there is a read operation between the initial ``sstore`` and the revert, or the overwriting ``sstore``, the statement will not be removed. Such read operations include: external calls, user-defined functions with any storage access, and ``sload`` of a slot that cannot be proven to differ from the slot written by the initial ``sstore``. For example, the following code .. code-block:: yul { let c := calldataload(0) sstore(c, 1) if c { sstore(c, 2) } sstore(c, 3) } will be transformed into the code below after the UnusedStoreEliminator step is run .. code-block:: yul { let c := calldataload(0) if c { } sstore(c, 3) } For memory store operations, things are generally simpler, at least in the outermost Yul block as all such statements will be removed if they are never read from in any code path. At function analysis level, however, the approach is similar to ``sstore``, as we do not know whether the memory location will be read once we leave the function's scope, so the statement will be removed only if all code paths lead to a memory overwrite. Best run in SSA form. Prerequisites: Disambiguator, ForLoopInitRewriter. .. _equivalent-function-combiner: EquivalentFunctionCombiner ^^^^^^^^^^^^^^^^^^^^^^^^^^ If two functions are syntactically equivalent, while allowing variable renaming but not any re-ordering, then any reference to one of the functions is replaced by the other. The actual removal of the function is performed by the UnusedPruner. Function Inlining ----------------- .. _expression-inliner: ExpressionInliner ^^^^^^^^^^^^^^^^^ This component of the optimizer performs restricted function inlining by inlining functions that can be inlined inside functional expressions, i.e. functions that: - return a single value. - have a body like ``r := ``. - neither reference themselves nor ``r`` in the right hand side. Furthermore, for all parameters, all of the following need to be true: - The argument is movable. - The parameter is either referenced less than twice in the function body, or the argument is rather cheap ("cost" of at most 1, like a constant up to ``0xff``). Example: The function to be inlined has the form of ``function f(...) -> r { r := E }`` where ``E`` is an expression that does not reference ``r`` and all arguments in the function call are movable expressions. The result of this inlining is always a single expression. This component can only be used on sources with unique names. .. _full-inliner: FullInliner ^^^^^^^^^^^ The FullInliner replaces certain calls of certain functions by the function's body. This is not very helpful in most cases, because it just increases the code size but does not have a benefit. Furthermore, code is usually very expensive and we would often rather have shorter code than more efficient code. In some cases, though, inlining a function can have positive effects on subsequent optimizer steps. This is the case if one of the function arguments is a constant, for example. During inlining, a heuristic is used to tell if the function call should be inlined or not. The current heuristic does not inline into "large" functions unless the called function is tiny. Functions that are only used once are inlined, as well as medium-sized functions, while function calls with constant arguments allow slightly larger functions. In the future, we may include a backtracking component that, instead of inlining a function right away, only specializes it, which means that a copy of the function is generated where a certain parameter is always replaced by a constant. After that, we can run the optimizer on this specialized function. If it results in heavy gains, the specialized function is kept, otherwise the original function is used instead. FunctionHoister and ExpressionSplitter are recommended as prerequisites since they make the step more efficient, but are not required for correctness. In particular, function calls with other function calls as arguments are not inlined, but running ExpressionSplitter beforehand ensures that there are no such calls in the input. Cleanup ------- The cleanup is performed at the end of the optimizer run. It tries to combine split expressions into deeply nested ones again and also improves the "compilability" for stack machines by eliminating variables as much as possible. .. _expression-joiner: ExpressionJoiner ^^^^^^^^^^^^^^^^ This is the opposite operation of the ExpressionSplitter. It turns a sequence of variable declarations that have exactly one reference into a complex expression. This stage fully preserves the order of function calls and opcode executions. It does not make use of any information concerning the commutativity of the opcodes; if moving the value of a variable to its place of use would change the order of any function call or opcode execution, the transformation is not performed. Note that the component will not move the assigned value of a variable assignment or a variable that is referenced more than once. The snippet ``let x := add(0, 2) let y := mul(x, mload(2))`` is not transformed, because it would cause the order of the call to the opcodes ``add`` and ``mload`` to be swapped - even though this would not make a difference because ``add`` is movable. When reordering opcodes like that, variable references and literals are ignored. Because of that, the snippet ``let x := add(0, 2) let y := mul(x, 3)`` is transformed to ``let y := mul(add(0, 2), 3)``, even though the ``add`` opcode would be executed after the evaluation of the literal ``3``. .. _ssa-reverser: SSAReverser ^^^^^^^^^^^ This is a tiny step that helps in reversing the effects of the SSATransform if it is combined with the CommonSubexpressionEliminator and the UnusedPruner. The SSA form we generate is detrimental to code generation because it produces many local variables. It would be better to just reuse existing variables with assignments instead of fresh variable declarations. The SSATransform rewrites .. code-block:: yul let a := calldataload(0) mstore(a, 1) to .. code-block:: yul let a_1 := calldataload(0) let a := a_1 mstore(a_1, 1) let a_2 := calldataload(0x20) a := a_2 The problem is that instead of ``a``, the variable ``a_1`` is used whenever ``a`` was referenced. The SSATransform changes statements of this form by just swapping out the declaration and the assignment. The above snippet is turned into .. code-block:: yul let a := calldataload(0) let a_1 := a mstore(a_1, 1) a := calldataload(0x20) let a_2 := a This is a very simple equivalence transform, but when we now run the CommonSubexpressionEliminator, it will replace all occurrences of ``a_1`` by ``a`` (until ``a`` is re-assigned). The UnusedPruner will then eliminate the variable ``a_1`` altogether and thus fully reverse the SSATransform. .. _stack-compressor: StackCompressor ^^^^^^^^^^^^^^^ One problem that makes code generation for the Ethereum Virtual Machine hard is the fact that there is a hard limit of 16 slots for reaching down the expression stack. This more or less translates to a limit of 16 local variables. The stack compressor takes Yul code and compiles it to EVM bytecode. Whenever the stack difference is too large, it records the function this happened in. For each function that caused such a problem, the Rematerialiser is called with a special request to aggressively eliminate specific variables sorted by the cost of their values. On failure, this procedure is repeated multiple times. .. _rematerialiser: Rematerialiser ^^^^^^^^^^^^^^ The rematerialisation stage tries to replace variable references by the expression that was last assigned to the variable. This is of course only beneficial if this expression is comparatively cheap to evaluate. Furthermore, it is only semantically equivalent if the value of the expression did not change between the point of assignment and the point of use. The main benefit of this stage is that it can save stack slots if it leads to a variable being eliminated completely (see below), but it can also save a ``DUP`` opcode on the EVM if the expression is very cheap. The Rematerialiser uses the DataflowAnalyzer to track the current values of variables, which are always movable. If the value is very cheap or the variable was explicitly requested to be eliminated, the variable reference is replaced by its current value. .. _for-loop-condition-out-of-body: ForLoopConditionOutOfBody ^^^^^^^^^^^^^^^^^^^^^^^^^ Reverses the transformation of ForLoopConditionIntoBody. For any movable ``c``, it turns .. code-block:: none for { ... } 1 { ... } { if iszero(c) { break } ... } into .. code-block:: none for { ... } c { ... } { ... } and it turns .. code-block:: none for { ... } 1 { ... } { if c { break } ... } into .. code-block:: none for { ... } iszero(c) { ... } { ... } The LiteralRematerialiser should be run before this step. Codegen-Based Optimizer Module ============================== Currently, the codegen-based optimizer module provides two optimizations. The first one, available in the legacy code generator, moves literals to the right side of commutative binary operators, which helps exploit their associativity. The other one, available in the IR-based code generator, enables the use of unchecked arithmetic when generating code for incrementing the counter variable of certain idiomatic ``for`` loops. This avoids wasting gas by identifying some conditions that guarantee that the counter variable cannot overflow. This eliminates the need to use a verbose unchecked arithmetic block inside the loop body to increment the counter variable. .. _unchecked-loop-optimizer: Unchecked Loop Increment ------------------------ Introduced in Solidity ``0.8.22``, the overflow check optimization step is concerned with identifying the conditions under which the ``for`` loop counter can be safely incremented without overflow checks. This optimization is **only** applied to ``for`` loops of the general form: .. code-block:: solidity for (uint i = X; i < Y; ++i) { // variable i is not modified in the loop body } The condition and the fact that the counter variable is only ever incremented guarantee that it never overflows. The precise requirements for the loop to be eligible for the optimization are as follows: - The loop condition is a comparison of the form ``i < Y``, for a local counter variable ``i`` (called the "loop counter" hereon) and an expression ``Y``. - The built-in operator ``<`` is necessarily used in the loop condition and is the only operator that triggers the optimization. ``<=`` and the like are intentionally excluded. Additionally, user-defined operators are **not** eligible. - The loop expression is a prefix or postfix increment of the counter variable, i.e, ``i++`` or ``++i``. - The loop counter is a local variable of a built-in integer type. - The loop counter is **not** modified by the loop body or by the expression used as the loop condition. - The comparison is performed on the same type as the loop counter, meaning that the type of the right-hand-side expression is implicitly convertible to the type of the counter, such that the latter is not implicitly widened before the comparison. To clarify the last condition, consider the following example: .. code-block:: solidity for (uint8 i = 0; i < uint16(1000); i++) { // ... } In this case, the counter ``i`` has its type implicitly converted from ``uint8`` to ``uint16`` before the comparison and the condition is in fact never false, so the overflow check for the increment cannot be removed. ================================================ FILE: docs/internals/source_mappings.rst ================================================ .. index:: source mappings *************** Source Mappings *************** As part of the AST output, the compiler provides the range of the source code that is represented by the respective node in the AST. This can be used for various purposes ranging from static analysis tools that report errors based on the AST and debugging tools that highlight local variables and their uses. Furthermore, the compiler can also generate a mapping from the bytecode to the range in the source code that generated the instruction. This is again important for static analysis tools that operate on bytecode level and for displaying the current position in the source code inside a debugger or for breakpoint handling. This mapping also contains other information, like the jump type and the modifier depth (see below). Both kinds of source mappings use integer identifiers to refer to source files. The identifier of a source file is stored in ``output['sources'][sourceName]['id']`` where ``output`` is the output of the standard-json compiler interface parsed as JSON. For some utility routines, the compiler generates "internal" source files that are not part of the original input but are referenced from the source mappings. These source files together with their identifiers can be obtained via ``output['contracts'][sourceName][contractName]['evm']['bytecode']['generatedSources']``. .. note:: In the case of instructions that are not associated with any particular source file, the source mapping assigns an integer identifier of ``-1``. This may happen for bytecode sections stemming from compiler-generated inline assembly statements. The source mappings inside the AST use the following notation: ``s:l:f`` Where ``s`` is the byte-offset to the start of the range in the source file, ``l`` is the length of the source range in bytes and ``f`` is the source index mentioned above. The encoding in the source mapping for the bytecode is more complicated: It is a list of ``s:l:f:j:m`` separated by ``;``. Each of these elements corresponds to an instruction, i.e. you cannot use the byte offset but have to use the instruction offset (push instructions are longer than a single byte). The fields ``s``, ``l`` and ``f`` are as above. ``j`` can be either ``i``, ``o`` or ``-`` signifying whether a jump instruction goes into a function, returns from a function or is a regular jump as part of e.g. a loop. The last field, ``m``, is an integer that denotes the "modifier depth". This depth is increased whenever the placeholder statement (``_``) is entered in a modifier and decreased when it is left again. This allows debuggers to track tricky cases like the same modifier being used twice or multiple placeholder statements being used in a single modifier. In order to compress these source mappings especially for bytecode, the following rules are used: - If a field is empty, the value of the preceding element is used. - If a ``:`` is missing, all following fields are considered empty. This means the following source mappings represent the same information: ``1:2:1;1:9:1;2:1:2;2:1:2;2:1:2`` ``1:2:1;:9;2:1:2;;`` Important to note is that when the :ref:`verbatim ` builtin is used, the source mappings will be invalid: The builtin is considered a single instruction instead of potentially multiple. ================================================ FILE: docs/internals/variable_cleanup.rst ================================================ .. index: variable cleanup ********************* Cleaning Up Variables ********************* Ultimately, all values in the EVM are stored in 256 bit words. Thus, in some cases, when the type of a value has less than 256 bits, it is necessary to clean the remaining bits. The Solidity compiler is designed to do such cleaning before any operations that might be adversely affected by the potential garbage in the remaining bits. For example, before writing a value to memory, the remaining bits need to be cleared because the memory contents can be used for computing hashes or sent as the data of a message call. Similarly, before storing a value in the storage, the remaining bits need to be cleaned because otherwise the garbled value can be observed. Note that access via inline assembly is not considered such an operation: If you use inline assembly to access Solidity variables shorter than 256 bits, the compiler does not guarantee that the value is properly cleaned up. Moreover, we do not clean the bits if the immediately following operation is not affected. For instance, since any non-zero value is considered ``true`` by ``JUMPI`` instruction, we do not clean the boolean values before they are used as the condition for ``JUMPI``. In addition to the design principle above, the Solidity compiler cleans input data when it is loaded onto the stack. The following table describes the cleaning rules applied to different types, where ``higher bits`` refers to the remaining bits in case the type has less than 256 bits. +---------------+---------------+-------------------------+ |Type |Valid Values |Cleanup of Invalid Values| +===============+===============+=========================+ |enum of n |0 until n - 1 |throws exception | |members | | | +---------------+---------------+-------------------------+ |bool |0 or 1 |results in 1 | +---------------+---------------+-------------------------+ |signed integers|higher bits |currently silently | | |set to the |signextends to a valid | | |sign bit |value, i.e. all higher | | | |bits are set to the sign | | | |bit; may throw an | | | |exception in the future | +---------------+---------------+-------------------------+ |unsigned |higher bits |currently silently masks | |integers |zeroed |to a valid value, i.e. | | | |all higher bits are set | | | |to zero; may throw an | | | |exception in the future | +---------------+---------------+-------------------------+ Note that valid and invalid values are dependent on their type size. Consider ``uint8``, the unsigned 8-bit type, which has the following valid values: .. code-block:: none 0000...0000 0000 0000 0000...0000 0000 0001 0000...0000 0000 0010 .... 0000...0000 1111 1111 Any invalid value will have the higher bits set to zero: .. code-block:: none 0101...1101 0010 1010 invalid value 0000...0000 0010 1010 cleaned value For ``int8``, the signed 8-bit type, the valid values are: Negative .. code-block:: none 1111...1111 1111 1111 1111...1111 1111 1110 .... 1111...1111 1000 0000 Positive .. code-block:: none 0000...0000 0000 0000 0000...0000 0000 0001 0000...0000 0000 0010 .... 0000...0000 0111 1111 The compiler will ``signextend`` the sign bit, which is 1 for negative and 0 for positive values, overwriting the higher bits: Negative .. code-block:: none 0010...1010 1111 1111 invalid value 1111...1111 1111 1111 cleaned value Positive .. code-block:: none 1101...0101 0000 0100 invalid value 0000...0000 0000 0100 cleaned value ================================================ FILE: docs/introduction-to-smart-contracts.rst ================================================ ############################### Introduction to Smart Contracts ############################### .. _simple-smart-contract: *********************** A Simple Smart Contract *********************** Let us begin with a basic example that sets the value of a variable and exposes it for other contracts to access. It is fine if you do not understand everything right now, we will go into more details later. Storage Example =============== .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; contract SimpleStorage { uint storedData; function set(uint x) public { storedData = x; } function get() public view returns (uint) { return storedData; } } The first line tells you that the source code is licensed under the GPL version 3.0. Machine-readable license specifiers are important in a setting where publishing the source code is the default. The next line specifies that the source code is written for Solidity version 0.4.16, or a newer version of the language up to, but not including version 0.9.0. This is to ensure that the contract is not compilable with a new (breaking) compiler version, where it could behave differently. :ref:`Pragmas` are common instructions for compilers about how to treat the source code (e.g. `pragma once `_). A contract in the sense of Solidity is a collection of code (its *functions*) and data (its *state*) that resides at a specific address on the Ethereum blockchain. The line ``uint storedData;`` declares a state variable called ``storedData`` of type ``uint`` (*u*\nsigned *int*\eger of *256* bits). You can think of it as a single slot in a database that you can query and alter by calling functions of the code that manages the database. In this example, the contract defines the functions ``set`` and ``get`` that can be used to modify or retrieve the value of the variable. To access a member (like a state variable) of the current contract, you do not typically add the ``this.`` prefix, you just access it directly via its name. Unlike in some other languages, omitting it is not just a matter of style, it results in a completely different way to access the member, but more on this later. This contract does not do much yet apart from (due to the infrastructure built by Ethereum) allowing anyone to store a single number that is accessible by anyone in the world without a (feasible) way to prevent you from publishing this number. Anyone could call ``set`` again with a different value and overwrite your number, but the number is still stored in the history of the blockchain. Later, you will see how you can impose access restrictions so that only you can alter the number. .. warning:: Be careful with using Unicode text, as similar looking (or even identical) characters can have different code points and as such are encoded as a different byte array. .. note:: All identifiers (contract names, function names and variable names) are restricted to the ASCII character set. It is possible to store UTF-8 encoded data in string variables. .. index:: ! subcurrency Subcurrency Example =================== The following contract implements the simplest form of a cryptocurrency. The contract allows only its creator to create new coins (different issuance schemes are possible). Anyone can send coins to each other without a need for registering with a username and password, all you need is an Ethereum keypair. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.26; // This will only compile via IR contract Coin { // The keyword "public" makes variables // accessible from other contracts address public minter; mapping(address => uint) public balances; // Events allow clients to react to specific // contract changes you declare event Sent(address from, address to, uint amount); // Constructor code is only run when the contract // is created constructor() { minter = msg.sender; } // Sends an amount of newly created coins to an address // Can only be called by the contract creator function mint(address receiver, uint amount) public { require(msg.sender == minter); balances[receiver] += amount; } // Errors allow you to provide information about // why an operation failed. They are returned // to the caller of the function. error InsufficientBalance(uint requested, uint available); // Sends an amount of existing coins // from any caller to an address function send(address receiver, uint amount) public { require(amount <= balances[msg.sender], InsufficientBalance(amount, balances[msg.sender])); balances[msg.sender] -= amount; balances[receiver] += amount; emit Sent(msg.sender, receiver, amount); } } This contract introduces some new concepts, let us go through them one by one. The line ``address public minter;`` declares a state variable of type :ref:`address
`. The ``address`` type is a 160-bit value that does not allow any arithmetic operations. It is suitable for storing addresses of contracts, or a hash of the public half of a keypair belonging to :ref:`externally-owned accounts`. The keyword ``public`` automatically generates a function that allows you to access the current value of the state variable from outside of the contract. Without this keyword, other contracts have no way to access the variable. The code of the function generated by the compiler is equivalent to the following (ignore ``external`` and ``view`` for now): .. code-block:: solidity function minter() external view returns (address) { return minter; } You could add a function like the above yourself, but you would have a function and state variable with the same name. You do not need to do this, the compiler figures it out for you. .. index:: mapping The next line, ``mapping(address => uint) public balances;`` also creates a public state variable, but it is a more complex datatype. The :ref:`mapping ` type maps addresses to :ref:`unsigned integers `. Mappings can be seen as `hash tables `_ which are virtually initialized such that every possible key exists from the start and is mapped to a value whose byte-representation is all zeros. However, it is neither possible to obtain a list of all keys of a mapping, nor a list of all values. Record what you added to the mapping, or use it in a context where this is not needed. Or even better, keep a list, or use a more suitable data type. The :ref:`getter function` created by the ``public`` keyword is more complex in the case of a mapping. It looks like the following: .. code-block:: solidity function balances(address account) external view returns (uint) { return balances[account]; } You can use this function to query the balance of a single account. .. index:: event The line ``event Sent(address from, address to, uint amount);`` declares an :ref:`"event" `, which is emitted in the last line of the function ``send``. Ethereum clients such as web applications can listen for these events emitted on the blockchain without much cost. As soon as it is emitted, the listener receives the arguments ``from``, ``to`` and ``amount``, which makes it possible to track transactions. To listen for this event, you could use the following JavaScript code, which uses `web3.js `_ to create the ``Coin`` contract object, and any user interface calls the automatically generated ``balances`` function from above: .. code-block:: javascript Coin.Sent().watch({}, '', function(error, result) { if (!error) { console.log("Coin transfer: " + result.args.amount + " coins were sent from " + result.args.from + " to " + result.args.to + "."); console.log("Balances now:\n" + "Sender: " + Coin.balances.call(result.args.from) + "Receiver: " + Coin.balances.call(result.args.to)); } }) .. index:: coin The :ref:`constructor` is a special function that is executed during the creation of the contract and cannot be called afterwards. In this case, it permanently stores the address of the person creating the contract. The ``msg`` variable (together with ``tx`` and ``block``) is a :ref:`special global variable ` that contains properties which allow access to the blockchain. ``msg.sender`` is always the address where the current (external) function call came from. The functions that make up the contract, and that users and contracts can call are ``mint`` and ``send``. The ``mint`` function sends an amount of newly created coins to another address. The :ref:`require ` function call defines conditions that reverts all changes if not met. In this example, ``require(msg.sender == minter);`` ensures that only the creator of the contract can call ``mint``. In general, the creator can mint as many tokens as they like, but at some point, this will lead to a phenomenon called "overflow". Note that because of the default :ref:`Checked arithmetic `, the transaction would revert if the expression ``balances[receiver] += amount;`` overflows, i.e., when ``balances[receiver] + amount`` in arbitrary precision arithmetic is larger than the maximum value of ``uint`` (``2**256 - 1``). This is also true for the statement ``balances[receiver] += amount;`` in the function ``send``. :ref:`Errors ` allow you to provide more information to the caller about why a condition or operation failed. Errors are used together with the :ref:`revert statement `. The ``revert`` statement unconditionally aborts and reverts all changes, much like the :ref:`require function `. Both approaches allow you to provide the name of an error and additional data which will be supplied to the caller (and eventually to the front-end application or block explorer) so that a failure can more easily be debugged or reacted upon. The ``send`` function can be used by anyone (who already has some of these coins) to send coins to anyone else. If the sender does not have enough coins to send, the ``if`` condition evaluates to true. As a result, the ``revert`` will cause the operation to fail while providing the sender with error details using the ``InsufficientBalance`` error. .. note:: If you use this contract to send coins to an address, you will not see anything when you look at that address on a blockchain explorer, because the record that you sent coins and the changed balances are only stored in the data storage of this particular coin contract. By using events, you can create a "blockchain explorer" that tracks transactions and balances of your new coin, but you have to inspect the coin contract address and not the addresses of the coin owners. .. _blockchain-basics: ***************** Blockchain Basics ***************** Blockchains as a concept are not too hard to understand for programmers. The reason is that most of the complications (mining, `hashing `_, `elliptic-curve cryptography `_, `peer-to-peer networks `_, etc.) are just there to provide a certain set of features and promises for the platform. Once you accept these features as given, you do not have to worry about the underlying technology - or do you have to know how Amazon's AWS works internally in order to use it? .. index:: transaction Transactions ============ A blockchain is a globally shared, transactional database. This means that everyone can read entries in the database just by participating in the network. If you want to change something in the database, you have to create a so-called transaction which has to be accepted by all others. The word transaction implies that the change you want to make (assume you want to change two values at the same time) is either not done at all or completely applied. Furthermore, while your transaction is being applied to the database, no other transaction can alter it. As an example, imagine a table that lists the balances of all accounts in an electronic currency. If a transfer from one account to another is requested, the transactional nature of the database ensures that if the amount is subtracted from one account, it is always added to the other account. If due to whatever reason, adding the amount to the target account is not possible, the source account is also not modified. Furthermore, a transaction is always cryptographically signed by the sender (creator). This makes it straightforward to guard access to specific modifications of the database. In the example of the electronic currency, a simple check ensures that only the person holding the keys to the account can transfer some compensation, e.g. Ether, from it. .. index:: ! block Blocks ====== One major obstacle to overcome is what (in Bitcoin terms) is called a "double-spend attack": What happens if two transactions exist in the network that both want to empty an account? Only one of the transactions can be valid, typically the one that is accepted first. The problem is that "first" is not an objective term in a peer-to-peer network. The abstract answer to this is that you do not have to care. A globally accepted order of the transactions will be selected for you, solving the conflict. The transactions will be bundled into what is called a "block" and then they will be executed and distributed among all participating nodes. If two transactions contradict each other, the one that ends up being second will be rejected and not become part of the block. These blocks form a linear sequence in time, and that is where the word "blockchain" derives from. Blocks are added to the chain at regular intervals, although these intervals may be subject to change in the future. For the most up-to-date information, it is recommended to monitor the network, for example, on `Etherscan `_. As part of the "order selection mechanism", which is called `attestation `_, it may happen that blocks are reverted from time to time, but only at the "tip" of the chain. The more blocks are added on top of a particular block, the less likely this block will be reverted. So it might be that your transactions are reverted and even removed from the blockchain, but the longer you wait, the less likely it will be. .. note:: Transactions are not guaranteed to be included in the next block or any specific future block, since it is not up to the submitter of a transaction, but up to the miners to determine in which block the transaction is included. If you want to schedule future calls of your contract, you can use a smart contract automation tool or an oracle service. .. _the-ethereum-virtual-machine: .. index:: !evm, ! ethereum virtual machine **************************** The Ethereum Virtual Machine **************************** Overview ======== The Ethereum Virtual Machine or EVM is the runtime environment for smart contracts in Ethereum. It is not only sandboxed but actually completely isolated, which means that code running inside the EVM has no access to network, filesystem or other processes. Smart contracts even have limited access to other smart contracts. .. index:: ! account, address, storage, balance .. _accounts: Accounts ======== There are two kinds of accounts in Ethereum which share the same address space: **Externally-owned accounts** that are controlled by public-private key pairs (i.e. humans) and **contract accounts** which are controlled by the code stored together with the account. The address of an externally-owned account is determined from the public key while the address of a contract is determined at the time the contract is created (it is derived from the creator address and the number of transactions sent from that address, the so-called "nonce"). Regardless of whether or not the account stores code, the two types are treated equally by the EVM. Every account has a persistent key-value store mapping 256-bit words to 256-bit words called **storage**. Furthermore, every account has a **balance** in Ether (in "Wei" to be exact, ``1 ether`` is ``10**18 wei``) which can be modified by sending transactions that include Ether. .. index:: ! transaction Transactions ============ A transaction is a message that is sent from one account to another account (which might be the same or empty, see below). It can include binary data (which is called "payload") and Ether. If the target account contains code, that code is executed and the payload is provided as input data. If the target account is not set (the transaction does not have a recipient or the recipient is set to ``null``), the transaction creates a **new contract**. As already mentioned, the address of that contract is not the zero address but an address derived from the sender and its number of transactions sent (the "nonce"). The payload of such a contract creation transaction is taken to be EVM bytecode and executed. The output data of this execution is permanently stored as the code of the contract. This means that in order to create a contract, you do not send the actual code of the contract, but in fact code that returns that code when executed. .. note:: While a contract is being created, its code is still empty. Because of that, you should not call back into the contract under construction until its constructor has finished executing. .. index:: ! gas, ! gas price Gas === Upon creation, each transaction is charged with a certain amount of **gas** that has to be paid for by the originator of the transaction (``tx.origin``). While the EVM executes the transaction, the gas is gradually depleted according to specific rules. If the gas is used up at any point (i.e. it would be negative), an out-of-gas exception is triggered, which ends execution and reverts all modifications made to the state in the current call frame. This mechanism incentivizes economical use of EVM execution time and also compensates EVM executors (i.e. miners / stakers) for their work. Since each block has a maximum amount of gas, it also limits the amount of work needed to validate a block. The **gas price** is a value set by the originator of the transaction, who has to pay ``gas_price * gas`` up front to the EVM executor. If some gas is left after execution, it is refunded to the transaction originator. In case of an exception that reverts changes, already used up gas is not refunded. Since EVM executors can choose to include a transaction or not, transaction senders cannot abuse the system by setting a low gas price. .. index:: ! storage, ! memory, ! stack, ! transient storage .. _locations: Storage, Transient Storage, Memory and the Stack ================================================ The Ethereum Virtual Machine has different areas where it can store data with the most prominent being storage, transient storage, memory and the stack. Each account has a data area called **storage**, which is persistent between function calls and transactions. Storage is a key-value store that maps 256-bit words to 256-bit words. It is not possible to enumerate storage from within a contract, it is comparatively costly to read, and even more to initialise and modify storage. Because of this cost, you should minimize what you store in persistent storage to what the contract needs to run. Store data like derived calculations, caching, and aggregates outside of the contract. A contract can neither read nor write to any storage apart from its own. Similar to storage, there is another data area called **transient storage**, where the main difference is that it is reset at the end of each transaction. The values stored in this data location persist only across function calls originating from the first call of the transaction. When the transaction ends, the transient storage is reset and the values stored there become unavailable to calls in subsequent transactions. Despite this, the cost of reading and writing to transient storage is significantly lower than for storage. The third data area is called **memory**, of which a contract obtains a freshly cleared instance for each message call. Memory is linear and can be addressed at byte level, but reads are limited to a width of 256 bits, while writes can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when accessing (either reading or writing) a previously untouched memory word (i.e. any offset within a word). At the time of expansion, the cost in gas must be paid. Memory is more costly the larger it grows (it scales quadratically). The EVM is not a register machine but a stack machine, so all computations are performed on a data area called the **stack**. It has a maximum size of 1024 elements and contains words of 256 bits. Access to the stack is limited to the top end in the following way: It is possible to copy one of the topmost 16 elements to the top of the stack or swap the topmost element with one of the 16 elements below it. All other operations take the topmost two (or one, or more, depending on the operation) elements from the stack and push the result onto the stack. Of course it is possible to move stack elements to storage or memory in order to get deeper access to the stack, but it is not possible to just access arbitrary elements deeper in the stack without first removing the top of the stack. Calldata, Returndata and Code ============================= There are also other data areas which are not as apparent as those discussed previously. However, they are routinely used during the execution of smart contract transactions. The calldata region is the data sent to a transaction as part of a smart contract transaction. For example, when creating a contract, calldata would be the constructor code of the new contract. The parameters of external functions are always initially stored in calldata in an ABI-encoded form and only then decoded into the location specified in their declaration. If declared as ``memory``, the compiler will eagerly decode them into memory at the beginning of the function, while marking them as ``calldata`` means that this will be done lazily, only when accessed. Value types and ``storage`` pointers are decoded directly onto the stack. The returndata is the way a smart contract can return a value after a call. In general, external Solidity functions use the ``return`` keyword to ABI-encode values into the returndata area. The code is the region where the EVM instructions of a smart contract are stored. Code is the bytes read, interpreted, and executed by the EVM during smart contract execution. Instruction data stored in the code is persistent as part of a contract account state field. Immutable and constant variables are stored in the code region. All references to immutables are replaced with the values assigned to them. A similar process is performed for constants which have their expressions inlined in the places where they are referenced in the smart contract code. .. index:: ! instruction Instruction Set =============== The instruction set of the EVM is kept minimal in order to avoid incorrect or inconsistent implementations which could cause consensus problems. All instructions operate on the basic data type, 256-bit words or on slices of memory (or other byte arrays). The usual arithmetic, bit, logical and comparison operations are present. Conditional and unconditional jumps are possible. Furthermore, contracts can access relevant properties of the current block like its number and timestamp. For a complete list, please see the :ref:`list of opcodes ` as part of the inline assembly documentation. .. index:: ! message call, function;call Message Calls ============= Contracts can call other contracts or send Ether to non-contract accounts by the means of message calls. Message calls are similar to transactions, in that they have a source, a target, data payload, Ether, gas and return data. In fact, every transaction consists of a top-level message call which in turn can create further message calls. A contract can decide how much of its remaining **gas** should be sent with the inner message call and how much it wants to retain. If an out-of-gas exception happens in the inner call (or any other exception), this will be signaled by an error value put onto the stack. In this case, only the gas sent together with the call is used up. In Solidity, the calling contract causes a manual exception by default in such situations, so that exceptions "bubble up" the call stack. As already said, the called contract (which can be the same as the caller) will receive a freshly cleared instance of memory and has access to the call payload - which will be provided in a separate area called the **calldata**. After it has finished execution, it can return data which will be stored at a location in the caller's memory preallocated by the caller. All such calls are fully synchronous. Calls are **limited** to a depth of 1024, which means that for more complex operations, loops should be preferred over recursive calls. Furthermore, only 63/64th of the gas can be forwarded in a message call, which causes a depth limit of a little less than 1000 in practice. .. _delegatecall: .. index:: delegatecall, library Delegatecall and Libraries ========================== There exists a special variant of a message call, named **delegatecall** which is identical to a message call apart from the fact that the code at the target address is executed in the context (i.e. at the address) of the calling contract and ``msg.sender`` and ``msg.value`` do not change their values. This means that a contract can dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract, only the code is taken from the called address. This makes it possible to implement the "library" feature in Solidity: Reusable library code that can be applied to a contract's storage, e.g. in order to implement a complex data structure. .. index:: log Logs ==== It is possible to store data in a specially indexed data structure that maps all the way up to the block level. This feature called **logs** is used by Solidity in order to implement :ref:`events `. Contracts cannot access log data after it has been created, but they can be efficiently accessed from outside the blockchain. Since some part of the log data is stored in `bloom filters `_, it is possible to search for this data in an efficient and cryptographically secure way, so network peers that do not download the whole blockchain (so-called "light clients") can still find these logs. .. index:: contract creation Create ====== Contracts can even create other contracts using a special opcode (i.e. they do not simply call the zero address as a transaction would). The only difference between these **create calls** and normal message calls is that the payload data is executed and the result stored as code and the caller / creator receives the address of the new contract on the stack. .. index:: ! selfdestruct, deactivate Deactivate and Self-destruct ============================ The only way to remove code from the blockchain is when a contract at that address performs the ``selfdestruct`` operation. The remaining Ether stored at that address is sent to a designated target and then the storage and code is removed from the state. Removing the contract in theory sounds like a good idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost. .. warning:: From ``EVM >= Cancun`` onwards, ``selfdestruct`` will **only** send all Ether in the account to the given recipient and not destroy the contract. However, when ``selfdestruct`` is called in the same transaction that creates the contract calling it, the behaviour of ``selfdestruct`` before Cancun hardfork (i.e., ``EVM <= Shanghai``) is preserved and will destroy the current contract, deleting any data, including storage keys, code and the account itself. See `EIP-6780 `_ for more details. The new behaviour is the result of a network-wide change that affects all contracts present on the Ethereum mainnet and testnets. It is important to note that this change is dependent on the EVM version of the chain on which the contract is deployed. The ``--evm-version`` setting used when compiling the contract has no bearing on it. Also, note that the ``selfdestruct`` opcode has been deprecated in Solidity version 0.8.18, as recommended by `EIP-6049 `_. The deprecation is still in effect and the compiler will still emit warnings on its use. Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. Future changes to the EVM might further reduce the functionality of the opcode. .. warning:: Even if a contract is removed by ``selfdestruct``, it is still part of the history of the blockchain and probably retained by most Ethereum nodes. So using ``selfdestruct`` is not the same as deleting data from a hard disk. .. note:: Even if a contract's code does not contain a call to ``selfdestruct``, it can still perform that operation using ``delegatecall`` or ``callcode``. If you want to deactivate your contracts, you should instead **disable** them by changing some internal state which causes all functions to revert. This makes it impossible to use the contract, as it returns Ether immediately. .. index:: ! precompiled contracts, ! precompiles, ! contract;precompiled .. _precompiledContracts: Precompiled Contracts ===================== There is a small set of contract addresses that are special: The address range between ``1`` and (including) ``0x0a`` contains "precompiled contracts" that can be called as any other contract but their behavior (and their gas consumption) is not defined by EVM code stored at that address (they do not contain code) but instead is implemented in the EVM execution environment itself. Different EVM-compatible chains might use a different set of precompiled contracts. It might also be possible that new precompiled contracts are added to the Ethereum main chain in the future, but you can reasonably expect them to always be in the range between ``1`` and ``0xffff`` (inclusive). ================================================ FILE: docs/ir-breaking-changes.rst ================================================ .. index: ir breaking changes .. _ir-breaking-changes: ********************************* Solidity IR-based Codegen Changes ********************************* Solidity can generate EVM bytecode in two different ways: Either directly from Solidity to EVM opcodes ("old codegen") or through an intermediate representation ("IR") in Yul ("new codegen" or "IR-based codegen"). The IR-based code generator was introduced with an aim to not only allow code generation to be more transparent and auditable but also to enable more powerful optimization passes that span across functions. You can enable it on the command-line using ``--via-ir`` or with the option ``{"viaIR": true}`` in standard-json and we encourage everyone to try it out! For several reasons, there are tiny semantic differences between the old and the IR-based code generator, mostly in areas where we would not expect people to rely on this behavior anyway. This section highlights the main differences between the old and the IR-based codegen. Semantic Only Changes ===================== This section lists the changes that are semantic-only, thus potentially hiding new and different behavior in existing code. .. _state-variable-initialization-order: - The order of state variable initialization has changed in case of inheritance. The order used to be: - All state variables are zero-initialized at the beginning. - Evaluate base constructor arguments from most derived to most base contract. - Initialize all state variables in the whole inheritance hierarchy from most base to most derived. - Run the constructor, if present, for all contracts in the linearized hierarchy from most base to most derived. New order: - All state variables are zero-initialized at the beginning. - Evaluate base constructor arguments from most derived to most base contract. - For every contract in order from most base to most derived in the linearized hierarchy: 1. Initialize state variables. 2. Run the constructor (if present). This causes differences in contracts where the initial value of a state variable relies on the result of the constructor in another contract: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1; contract A { uint x; constructor() { x = 42; } function f() public view returns(uint256) { return x; } } contract B is A { uint public y = f(); } Previously, ``y`` would be set to 0. This is due to the fact that we would first initialize state variables: First, ``x`` is set to 0, and when initializing ``y``, ``f()`` would return 0 causing ``y`` to be 0 as well. With the new rules, ``y`` will be set to 42. We first initialize ``x`` to 0, then call A's constructor which sets ``x`` to 42. Finally, when initializing ``y``, ``f()`` returns 42 causing ``y`` to be 42. - When storage structs are deleted, every storage slot that contains a member of the struct is set to zero entirely. Formerly, padding space was left untouched. Consequently, if the padding space within a struct is used to store data (e.g. in the context of a contract upgrade), you have to be aware that ``delete`` will now also clear the added member (while it wouldn't have been cleared in the past). .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1; contract C { struct S { uint64 y; uint64 z; } S s; function f() public { // ... delete s; // s occupies only first 16 bytes of the 32 bytes slot // delete will write zero to the full slot } } We have the same behavior for implicit delete, for example when array of structs is shortened. - Function modifiers are implemented in a slightly different way regarding function parameters and return variables. This especially has an effect if the placeholder ``_;`` is evaluated multiple times in a modifier. In the old code generator, each function parameter and return variable has a fixed slot on the stack. If the function is run multiple times because ``_;`` is used multiple times or used in a loop, then a change to the function parameter's or return variable's value is visible in the next execution of the function. The new code generator implements modifiers using actual functions and passes function parameters on. This means that multiple evaluations of a function's body will get the same values for the parameters, and the effect on return variables is that they are reset to their default (zero) value for each execution. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0; contract C { function f(uint a) public pure mod() returns (uint r) { r = a++; } modifier mod() { _; _; } } If you execute ``f(0)`` in the old code generator, it will return ``1``, while it will return ``0`` when using the new code generator. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1 <0.9.0; contract C { bool active = true; modifier mod() { _; active = false; _; } function foo() external mod() returns (uint ret) { if (active) ret = 1; // Same as ``return 1`` } } The function ``C.foo()`` returns the following values: - Old code generator: ``1`` as the return variable is initialized to ``0`` only once before the first ``_;`` evaluation and then overwritten by the ``return 1;``. It is not initialized again for the second ``_;`` evaluation and ``foo()`` does not explicitly assign it either (due to ``active == false``), thus it keeps its first value. - New code generator: ``0`` as all parameters, including return parameters, will be re-initialized before each ``_;`` evaluation. .. index:: ! evaluation order; expression - For the old code generator, the evaluation order of expressions is unspecified. For the new code generator, we try to evaluate in source order (left to right), but do not guarantee it. This can lead to semantic differences. For example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.1; contract C { function preincr_u8(uint8 a) public pure returns (uint8) { return ++a + a; } } The function ``preincr_u8(1)`` returns the following values: - Old code generator: ``3`` (``1 + 2``) but the return value is unspecified in general - New code generator: ``4`` (``2 + 2``) but the return value is not guaranteed .. index:: ! evaluation order; function arguments On the other hand, function argument expressions are evaluated in the same order by both code generators with the exception of the global functions ``addmod`` and ``mulmod``. For example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.1; contract C { function add(uint8 a, uint8 b) public pure returns (uint8) { return a + b; } function g(uint8 a, uint8 b) public pure returns (uint8) { return add(++a + ++b, a + b); } } The function ``g(1, 2)`` returns the following values: - Old code generator: ``10`` (``add(2 + 3, 2 + 3)``) but the return value is unspecified in general - New code generator: ``10`` but the return value is not guaranteed The arguments to the global functions ``addmod`` and ``mulmod`` are evaluated right-to-left by the old code generator and left-to-right by the new code generator. For example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.1; contract C { function f() public pure returns (uint256 aMod, uint256 mMod) { uint256 x = 3; // Old code gen: add/mulmod(5, 4, 3) // New code gen: add/mulmod(4, 5, 5) aMod = addmod(++x, ++x, x); mMod = mulmod(++x, ++x, x); } } The function ``f()`` returns the following values: - Old code generator: ``aMod = 0`` and ``mMod = 2`` - New code generator: ``aMod = 4`` and ``mMod = 0`` - The new code generator imposes a hard limit of ``type(uint64).max`` (``0xffffffffffffffff``) for the free memory pointer. Allocations that would increase its value beyond this limit revert. The old code generator does not have this limit. For example: .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >0.8.0; contract C { function f() public { uint[] memory arr; // allocation size: 576460752303423481 // assumes freeMemPtr points to 0x80 initially uint solYulMaxAllocationBeforeMemPtrOverflow = (type(uint64).max - 0x80 - 31) / 32; // freeMemPtr overflows UINT64_MAX arr = new uint[](solYulMaxAllocationBeforeMemPtrOverflow); } } The function ``f()`` behaves as follows: - Old code generator: runs out of gas while zeroing the array contents after the large memory allocation - New code generator: reverts due to free memory pointer overflow (does not run out of gas) Internals ========= .. _internal-function-pointers-in-ir: Internal function pointers -------------------------- .. index:: function pointers The old code generator uses code offsets or tags for values of internal function pointers. This is especially complicated since these offsets are different at construction time and after deployment and the values can cross this border via storage. Because of that, both offsets are encoded at construction time into the same value (into different bytes). In the new code generator, function pointers use internal IDs that are allocated in sequence. Since calls via jumps are not possible, calls through function pointers always have to use an internal dispatch function that uses the ``switch`` statement to select the right function. The ID ``0`` is reserved for uninitialized function pointers which then cause a panic in the dispatch function when called. In the old code generator, internal function pointers are initialized with a special function that always causes a panic. This causes a storage write at construction time for internal function pointers in storage. .. note:: The compiler is free to omit internal functions that are never explicitly referenced by name. As a consequence, assigning to a function type variable in inline assembly does not guarantee that the assigned value will be included in the internal dispatch. The function must also be explicitly referenced elsewhere in the code. Cleanup ------- .. index:: cleanup, dirty bits The old code generator only performs cleanup before an operation whose result could be affected by the values of the dirty bits. The new code generator performs cleanup after any operation that can result in dirty bits. The hope is that the optimizer will be powerful enough to eliminate redundant cleanup operations. For example: .. code-block:: solidity :force: // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.1; contract C { function f(uint8 a) public pure returns (uint r1, uint r2) { a = ~a; assembly { r1 := a } r2 = a; } } The function ``f(1)`` returns the following values: - Old code generator: (``fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe``, ``00000000000000000000000000000000000000000000000000000000000000fe``) - New code generator: (``00000000000000000000000000000000000000000000000000000000000000fe``, ``00000000000000000000000000000000000000000000000000000000000000fe``) Note that, unlike the new code generator, the old code generator does not perform a cleanup after the bit-not assignment (``a = ~a``). This results in different values being assigned (within the inline assembly block) to return value ``r1`` between the old and new code generators. However, both code generators perform a cleanup before the new value of ``a`` is assigned to ``r2``. ================================================ FILE: docs/language-influences.rst ================================================ ################### Language Influences ################### Solidity is a `curly-bracket language `_ that has been influenced and inspired by several well-known programming languages. Solidity is most profoundly influenced by C++, but also borrowed concepts from languages like Python, JavaScript, and others. The influence from C++ can be seen in the syntax for variable declarations, for loops, the concept of overloading functions, implicit and explicit type conversions and many other details. In the early days of the language, Solidity used to be partly influenced by JavaScript. This was due to function-level scoping of variables and the use of the keyword ``var``. The JavaScript influence was reduced starting from version 0.4.0. Now, the main remaining similarity to JavaScript is that functions are defined using the keyword ``function``. Solidity also supports import syntax and semantics that are similar to those available in JavaScript. Besides those points, Solidity looks like most other curly-bracket languages and has no major JavaScript influence anymore. Another influence to Solidity was Python. Solidity's modifiers were added trying to model Python's decorators with a much more restricted functionality. Furthermore, multiple inheritance, C3 linearization, and the ``super`` keyword are taken from Python as well as the general assignment and copy semantics of value and reference types. ================================================ FILE: docs/layout-of-source-files.rst ================================================ ******************************** Layout of a Solidity Source File ******************************** Source files can contain an arbitrary number of :ref:`contract definitions`, import_ , :ref:`pragma` and :ref:`using for` directives and :ref:`struct`, :ref:`enum`, :ref:`function`, :ref:`error` and :ref:`constant variable` definitions. .. index:: ! license, spdx SPDX License Identifier ======================= Trust in smart contracts can be better established if their source code is available. Since making source code available always touches on legal problems with regards to copyright, the Solidity compiler encourages the use of machine-readable `SPDX license identifiers `_. Every source file should start with a comment indicating its license: ``// SPDX-License-Identifier: MIT`` The compiler does not validate that the license is part of the `list allowed by SPDX `_, but it does include the supplied string in the :ref:`bytecode metadata `. If you do not want to specify a license or if the source code is not open-source, please use the special value ``UNLICENSED``. Note that ``UNLICENSED`` (no usage allowed, not present in SPDX license list) is different from ``UNLICENSE`` (grants all rights to everyone). Solidity follows `the npm recommendation `_. Supplying this comment of course does not free you from other obligations related to licensing like having to mention a specific license header in each source file or the original copyright holder. The comment is recognized by the compiler anywhere in the file at the file level, but it is recommended to put it at the top of the file. More information about how to use SPDX license identifiers can be found at the `SPDX website `_. .. index:: ! pragma .. _pragma: Pragmas ======= The ``pragma`` keyword is used to enable certain compiler features or checks. A pragma directive is always local to a source file, so you have to add the pragma to all your files if you want to enable it in your whole project. If you :ref:`import` another file, the pragma from that file does *not* automatically apply to the importing file. .. index:: ! pragma;version .. _version_pragma: Version Pragma -------------- Source files can (and should) be annotated with a version pragma to reject compilation with future compiler versions that might introduce incompatible changes. We try to keep these to an absolute minimum and introduce them in a way that changes in semantics also require changes in the syntax, but this is not always possible. Because of this, it is always a good idea to read through the changelog at least for releases that contain breaking changes. These releases always have versions of the form ``0.x.0`` or ``x.0.0``. The version pragma is used as follows: ``pragma solidity ^0.5.2;`` A source file with the line above does not compile with a compiler earlier than version 0.5.2, and it also does not work on a compiler starting from version 0.6.0 (this second condition is added by using ``^``). Because there will be no breaking changes until version ``0.6.0``, you can be sure that your code compiles the way you intended. The exact version of the compiler is not fixed, so that bugfix releases are still possible. It is possible to specify more complex rules for the compiler version, these follow the same syntax used by `npm `_. .. note:: Using the version pragma *does not* change the version of the compiler. It also *does not* enable or disable features of the compiler. It just instructs the compiler to check whether its version matches the one required by the pragma. If it does not match, the compiler issues an error. .. index:: ! ABI coder, ! pragma; abicoder, pragma; ABIEncoderV2 .. _abi_coder: ABI Coder Pragma ---------------- By using ``pragma abicoder v1`` or ``pragma abicoder v2`` you can select between the two implementations of the ABI encoder and decoder. The new ABI coder (v2) is able to encode and decode arbitrarily nested arrays and structs. Apart from supporting more types, it involves more extensive validation and safety checks, which may result in higher gas costs, but also heightened security. It is considered non-experimental as of Solidity 0.6.0 and it is enabled by default starting with Solidity 0.8.0. The old ABI coder can still be selected using ``pragma abicoder v1;``. .. warning:: The ABI coder v1 is deprecated and scheduled for removal. Use ABI coder v2 instead. The set of types supported by the new encoder is a strict superset of the ones supported by the old one. Contracts that use it can interact with ones that do not without limitations. The reverse is possible only as long as the non-``abicoder v2`` contract does not try to make calls that would require decoding types only supported by the new encoder. The compiler can detect this and will issue an error. Simply enabling ``abicoder v2`` for your contract is enough to make the error go away. .. note:: This pragma applies to all the code defined in the file where it is activated, regardless of where that code ends up eventually. This means that a contract whose source file is selected to compile with ABI coder v1 can still contain code that uses the new encoder by inheriting it from another contract. This is allowed if the new types are only used internally and not in external function signatures. .. note:: Up to Solidity 0.7.4, it was possible to select the ABI coder v2 by using ``pragma experimental ABIEncoderV2``, but it was not possible to explicitly select coder v1 because it was the default. .. index:: ! pragma; experimental .. _experimental_pragma: Experimental Pragma ------------------- The second pragma is the experimental pragma. It can be used to enable features of the compiler or language that are not yet enabled by default. The following experimental pragmas are currently supported: .. index:: ! pragma; ABIEncoderV2 ABIEncoderV2 ~~~~~~~~~~~~ Because the ABI coder v2 is not considered experimental anymore, it can be selected via ``pragma abicoder v2`` (please see above) since Solidity 0.7.4. .. index:: ! pragma; SMTChecker .. _smt_checker: SMTChecker ~~~~~~~~~~ If you use ``pragma experimental SMTChecker;``, then you get additional :ref:`safety warnings` which are obtained by querying an SMT solver. The component does not yet support all features of the Solidity language and likely outputs many warnings. In case it reports unsupported features, the analysis may not be fully sound. .. note:: The ``SMTChecker`` pragma is deprecated and will be removed. To enable SMTChecker, simply select :ref:`select an engine` when invoking the compiler. .. index:: source file, ! import, module, source unit .. _import: Importing other Source Files ============================ Syntax and Semantics -------------------- Solidity supports import statements to help modularise your code that are similar to those available in JavaScript (from ES6 on). However, Solidity does not support the concept of a `default export `_. At a global level, you can use import statements of the following form: .. code-block:: solidity import "filename"; The ``filename`` part is called an *import path*. This statement imports all global symbols from "filename" (and symbols imported there) into the current global scope (different than in ES6 but backwards-compatible for Solidity). This form is not recommended for use, because it unpredictably pollutes the namespace. If you add new top-level items inside "filename", they automatically appear in all files that import like this from "filename". It is better to import specific symbols explicitly. The following example creates a new global symbol ``symbolName`` whose members are all the global symbols from ``"filename"``: .. code-block:: solidity import * as symbolName from "filename"; which results in all global symbols being available in the format ``symbolName.symbol``. A variant of this syntax that is not part of ES6, but possibly useful is: .. code-block:: solidity import "filename" as symbolName; which is equivalent to ``import * as symbolName from "filename";``. If there is a naming collision, you can rename symbols while importing. For example, the code below creates new global symbols ``alias`` and ``symbol2`` which reference ``symbol1`` and ``symbol2`` from inside ``"filename"``, respectively. .. code-block:: solidity import {symbol1 as alias, symbol2} from "filename"; .. index:: virtual filesystem, source unit name, import; path, filesystem path, import callback, Remix IDE Import Paths ------------ In order to be able to support reproducible builds on all platforms, the Solidity compiler has to abstract away the details of the filesystem where source files are stored. For this reason import paths do not refer directly to files in the host filesystem. Instead the compiler maintains an internal database (*virtual filesystem* or *VFS* for short) where each source unit is assigned a unique *source unit name* which is an opaque and unstructured identifier. The import path specified in an import statement is translated into a source unit name and used to find the corresponding source unit in this database. Using the :ref:`Standard JSON ` API it is possible to directly provide the names and content of all the source files as a part of the compiler input. In this case source unit names are truly arbitrary. If, however, you want the compiler to automatically find and load source code into the VFS, your source unit names need to be structured in a way that makes it possible for an :ref:`import callback ` to locate them. When using the command-line compiler the default import callback supports only loading source code from the host filesystem, which means that your source unit names must be paths. Some environments provide custom callbacks that are more versatile. For example the `Remix IDE `_ provides one that lets you `import files from HTTP, IPFS and Swarm URLs or refer directly to packages in NPM registry `_. For a complete description of the virtual filesystem and the path resolution logic used by the compiler see :ref:`Path Resolution `. .. index:: ! comment, natspec Comments ======== Single-line comments (``//``) and multi-line comments (``/*...*/``) are possible. .. code-block:: solidity // This is a single-line comment. /* This is a multi-line comment. */ .. note:: A single-line comment is terminated by any unicode line terminator (LF, VF, FF, CR, NEL, LS or PS) in UTF-8 encoding. The terminator is still part of the source code after the comment, so if it is not an ASCII symbol (these are NEL, LS and PS), it will lead to a parser error. Additionally, there is another type of comment called a NatSpec comment, which is detailed in the :ref:`style guide`. They are written with a triple slash (``///``) or a double asterisk block (``/** ... */``) and they should be used directly above function declarations or statements. ================================================ FILE: docs/make.bat ================================================ @ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. latexpdf to make LaTeX files and run them through pdflatex echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Solidity.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Solidity.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end ================================================ FILE: docs/metadata.rst ================================================ .. _metadata: ################# Contract Metadata ################# .. index:: metadata, contract verification The Solidity compiler automatically generates a JSON file. The file contains two kinds of information about the compiled contract: - How to interact with the contract: ABI, and NatSpec documentation. - How to reproduce the compilation and verify a deployed contract: compiler version, compiler settings, and source files used. The compiler appends by default the IPFS hash of the metadata file to the end of the runtime bytecode (not necessarily the creation bytecode) of each contract, so that, if published, you can retrieve the file in an authenticated way without having to resort to a centralized data provider. The other available options are the Swarm hash and not appending the metadata hash to the bytecode. These can be configured via the :ref:`Standard JSON Interface`. You have to publish the metadata file to IPFS, Swarm, or another service so that others can access it. You create the file by using the ``solc --metadata`` command together with the ``--output-dir`` parameter. Without the parameter, the metadata will be written to standard output. The metadata contains IPFS and Swarm references to the source code, so you have to upload all source files in addition to the metadata file. For IPFS, the hash contained in the CID returned by ``ipfs add`` (not the direct sha2-256 hash of the file) shall match with the one contained in the bytecode. The metadata file has the following format. The example below is presented in a human-readable way. Properly formatted metadata should use quotes correctly, reduce whitespace to a minimum, and sort the keys of all objects in alphabetical order to arrive at a canonical formatting. Comments are not permitted and are used here only for explanatory purposes. .. code-block:: javascript { // Required: Details about the compiler, contents are specific // to the language. "compiler": { // Optional: Hash of the compiler binary which produced this output "keccak256": "0x123...", // Required for Solidity: Version of the compiler "version": "0.8.2+commit.661d1103" }, // Required: Source code language, basically selects a "sub-version" // of the specification "language": "Solidity", // Required: Generated information about the contract. "output": { // Required: ABI definition of the contract. See "Contract ABI Specification" "abi": [/* ... */], // Required: NatSpec developer documentation of the contract. See https://docs.soliditylang.org/en/latest/natspec-format.html for details. "devdoc": { // Contents of the @author NatSpec field of the contract "author": "John Doe", // Contents of the @dev NatSpec field of the contract "details": "Interface of the ERC20 standard as defined in the EIP. See https://eips.ethereum.org/EIPS/eip-20 for details", "errors": { "MintToZeroAddress()" : { "details": "Cannot mint to zero address" } }, "events": { "Transfer(address,address,uint256)": { "details": "Emitted when `value` tokens are moved from one account (`from`) toanother (`to`).", "params": { "from": "The sender address", "to": "The receiver address", "value": "The token amount" } } }, "kind": "dev", "methods": { "transfer(address,uint256)": { // Contents of the @dev NatSpec field of the method "details": "Returns a boolean value indicating whether the operation succeeded. Must be called by the token holder address", // Contents of the @param NatSpec fields of the method "params": { "_value": "The amount tokens to be transferred", "_to": "The receiver address" }, // Contents of the @return NatSpec field. "returns": { // Return var name (here "success") if exists. "_0" as key if return var is unnamed "success": "a boolean value indicating whether the operation succeeded" } } }, "stateVariables": { "owner": { // Contents of the @dev NatSpec field of the state variable "details": "Must be set during contract creation. Can then only be changed by the owner" } }, // Contents of the @title NatSpec field of the contract "title": "MyERC20: an example ERC20", "version": 1 // NatSpec version }, // Required: NatSpec user documentation of the contract. See "NatSpec Format" "userdoc": { "errors": { "ApprovalCallerNotOwnerNorApproved()": [ { "notice": "The caller must own the token or be an approved operator." } ] }, "events": { "Transfer(address,address,uint256)": { "notice": "`_value` tokens have been moved from `from` to `to`" } }, "kind": "user", "methods": { "transfer(address,uint256)": { "notice": "Transfers `_value` tokens to address `_to`" } }, "version": 1 // NatSpec version } }, // Required: Compiler settings. // Reflects the settings in the JSON input during compilation, except: // - Different format: "libraries" field // - Added field in metadata.settings: "compilationTarget" // - Not in metadata.settings: "stopAfter", "debug.debugInfo", "outputSelection" // See the standard JSON input's "settings" field docs for the rest. "settings": { // Required for Solidity: File path and the name of the contract or library this // metadata is created for. This field is not present in the standard JSON input settings. "compilationTarget": { "myDirectory/myFile.sol": "MyContract" }, // Optional (false if omitted): Indicates whether experimental mode has been enabled. // Always matches the value of the `experimental` flag in CBOR metadata. // Note that experimental mode being enabled does not necessarily mean that any // experimental features were actually used, or if they were, that those features // affected the bytecode. "experimental": true, // Required for Solidity: Addresses for libraries used. // Note that metadata has a different format for "libraries" field than the standard JSON input. // metadata format = { "MyLib.sol:MyLib": "0x123123..." } // standard JSON input format = { "MyLib.sol": { "MyLib": "0x123123..." } } "libraries": { "MyLib.sol:MyLib": "0x123123..." }, // ... // ... // ... // The rest of the fields and their defaults same as in std JSON input. }, // Required: Compilation source files/source units, keys are file paths "sources": { "settable": { // Required (unless "url" is used): literal contents of the source file "content": "contract settable is owned { uint256 private x = 0; function set(uint256 _x) public { if (msg.sender == owner) x = _x; } }", // Required: keccak256 hash of the source file "keccak256": "0x234..." }, "myDirectory/myFile.sol": { // Required: keccak256 hash of the source file "keccak256": "0x123...", // Optional: SPDX license identifier as given in the source file "license": "MIT", // Required (unless "content" is used, see above): Sorted URL(s) // to the source file, protocol is more or less arbitrary, but an // IPFS URL is recommended "urls": [ "bzz-raw://7d7a...", "dweb:/ipfs/QmN..." ] } }, // Required: The version of the metadata format "version": 1 } .. warning:: Since the bytecode of the resulting contract contains the metadata hash by default, any change to the metadata might result in a change of the bytecode. This includes changes to a filename or path, and since the metadata includes a hash of all the sources used, a single whitespace change results in different metadata, and different bytecode. .. note:: The ABI definition above has no fixed order. It can change with compiler versions. Starting from Solidity version 0.5.12, though, the array maintains a certain order. .. _encoding-of-the-metadata-hash-in-the-bytecode: Encoding of the Metadata Hash in the Bytecode ============================================= The compiler currently by default appends the `IPFS hash (in CID v0) `_ of the canonical metadata file and the compiler version to the end of the bytecode. Optionally, a Swarm hash instead of the IPFS, or an experimental flag is used. Below are all the possible fields: .. code-block:: javascript { // Present if "bytecodeHash" was "ipfs" in compiler settings "ipfs": "", // Present if "bytecodeHash" was "bzzr1" in compiler settings "bzzr1": "", // Previous versions were using "bzzr0" instead of "bzzr1" "bzzr0": "", // Present if experimental mode has been enabled either via "--experimental" flag or // "settings.experimental" option in Standard JSON "experimental": true, "solc": "" } Because we might support other ways to retrieve the metadata file in the future, this information is stored `CBOR `_-encoded. The last two bytes in the bytecode indicate the length of the CBOR encoded information. By looking at this length, the relevant part of the bytecode can be decoded with a CBOR decoder. Check the `Metadata Playground `_ to see it in action. Whereas release builds of solc use a 3 byte encoding of the version as shown above (one byte each for major, minor and patch version number), pre-release builds will instead use a complete version string including commit hash and build date. The commandline flag ``--no-cbor-metadata`` can be used to skip metadata from getting appended at the end of the deployed bytecode. Equivalently, the boolean field ``settings.metadata.appendCBOR`` in Standard JSON input can be set to false. .. note:: The CBOR mapping can also contain other keys, so it is better to fully decode the data by looking at the end of the bytecode for the CBOR length, and to use a proper CBOR parser. Do not rely on it starting with ``0xa264`` or ``0xa2 0x64 'i' 'p' 'f' 's'``. Usage for Automatic Interface Generation and NatSpec ==================================================== The metadata is used in the following way: A component that wants to interact with a contract (e.g. a wallet) retrieves the code of the contract. It decodes the CBOR encoded section containing the IPFS/Swarm hash of the metadata file. With that hash, the metadata file is retrieved. That file is JSON-decoded into a structure like above. The component can then use the ABI to automatically generate a rudimentary user interface for the contract. Furthermore, the wallet can use the NatSpec user documentation to display a human-readable confirmation message to the user whenever they interact with the contract, together with requesting authorization for the transaction signature. For additional information, read :doc:`Ethereum Natural Language Specification (NatSpec) format `. Usage for Source Code Verification ================================== If pinned/published, it is possible to retrieve the metadata of the contract from IPFS/Swarm. The metadata file also contains the URLs or the IPFS hashes of the source files, as well as the compilation settings, i.e. everything needed to reproduce a compilation. With this information it is then possible to verify the source code of a contract by reproducing the compilation, and comparing the bytecode from the compilation with the bytecode of the deployed contract. This automatically verifies the metadata since its hash is part of the bytecode, as well as the source codes, because their hashes are part of the metadata. Any change in the files or settings would result in a different metadata hash. The metadata here serves as a fingerprint of the whole compilation. `Sourcify `_ makes use of this feature for "full/perfect verification", as well as pinning the files publicly on IPFS to be accessed with the metadata hash. ================================================ FILE: docs/natspec-format.rst ================================================ .. _natspec: ############## NatSpec Format ############## Solidity contracts can use a special form of comments to provide rich documentation for functions, return variables and more. This special form is named the Ethereum Natural Language Specification Format (NatSpec). .. note:: NatSpec was inspired by `Doxygen `_. While it uses Doxygen-style comments and tags, there is no intention to keep strict compatibility with Doxygen. Please carefully examine the supported tags listed below. This documentation is segmented into developer-focused messages and end-user-facing messages. These messages may be shown to the end user (the human) at the time that they will interact with the contract (i.e. sign a transaction). It is recommended that Solidity contracts are fully annotated using NatSpec for all public interfaces (everything in the ABI). NatSpec includes the formatting for comments that the smart contract author will use, and which are understood by the Solidity compiler. Also detailed below is output of the Solidity compiler, which extracts these comments into a machine-readable format. NatSpec may also include annotations used by third-party tools. These are most likely accomplished via the ``@custom:`` tag, and a good use case is analysis and verification tools. .. _header-doc-example: Documentation Example ===================== Documentation is inserted above each ``contract``, ``interface``, ``library``, ``function``, ``enum``, ``enum`` value and ``event`` using the Doxygen notation format. A ``public`` state variable is equivalent to a ``function`` for the purposes of NatSpec. - For Solidity you may choose ``///`` for single or multi-line comments, or ``/**`` and ending with ``*/``. - For Vyper, use ``"""`` indented to the inner contents with bare comments. See the `Vyper documentation `__. The following example shows a contract and a function using all available tags. .. note:: The Solidity compiler only interprets tags if they are external or public. You are welcome to use similar comments for your internal and private functions, but those will not be parsed. This may change in the future. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.2 < 0.9.0; /// @title A simulator for trees /// @author Larry A. Gardner /// @notice You can use this contract for only the most basic simulation /// @dev All function calls are currently implemented without side effects /// @custom:experimental This is an experimental contract. contract Tree { /// @notice Calculate tree age in years, rounded up, for live trees /// @dev The Alexandr N. Tetearing algorithm could increase precision /// @param rings The number of rings from dendrochronological sample /// @return Age in years, rounded up for partial years /// @return Name of the tree function age(uint256 rings) external virtual pure returns (uint256, string memory) { return (rings + 1, "tree"); } /// @notice Returns the amount of leaves the tree has. /// @dev Returns only a fixed number. function leaves() external virtual pure returns(uint256) { return 2; } } contract Plant { function leaves() external virtual pure returns(uint256) { return 3; } } contract KumquatTree is Tree, Plant { function age(uint256 rings) external override pure returns (uint256, string memory) { return (rings + 2, "Kumquat"); } /// Return the amount of leaves that this specific kind of tree has /// @inheritdoc Tree function leaves() external override(Tree, Plant) pure returns(uint256) { return 3; } } .. _header-tags: Tags ==== All tags are optional. The following table explains the purpose of each NatSpec tag and where it may be used. As a special case, if no tags are used then the Solidity compiler will interpret a ``///`` or ``/**`` comment in the same way as if it were tagged with ``@notice``. =============== ====================================================================================== ============================= Tag Context =============== ====================================================================================== ============================= ``@title`` A title that should describe the contract/interface contract, library, interface, struct, enum, enum values ``@author`` The name of the author contract, library, interface, struct, enum, enum values ``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum, enum values error ``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum, enum values, error ``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event, enum values, error ``@return`` Documents the return variables of a contract's function function, enum, enum values, public state variable ``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, enum, enum values, public state variable ``@custom:...`` Custom tag, semantics is application-defined everywhere =============== ====================================================================================== ============================= If your function returns multiple values, like ``(int quotient, int remainder)`` then use multiple ``@return`` statements in the same format as the ``@param`` statements. Custom tags start with ``@custom:`` and must be followed by one or more lowercase letters or hyphens. It cannot start with a hyphen however. They can be used everywhere and are part of the developer documentation. .. _header-dynamic: Dynamic expressions ------------------- The Solidity compiler will pass through NatSpec documentation from your Solidity source code to the JSON output as described in this guide. The consumer of this JSON output, for example the end-user client software, may present this to the end-user directly or it may apply some pre-processing. For example, some client software will render: .. code:: Solidity /// @notice This function will multiply `a` by 7 to the end-user as: .. code:: text This function will multiply 10 by 7 if a function is being called and the input ``a`` is assigned a value of 10. .. _header-inheritance: Inheritance Notes ----------------- Functions without NatSpec will automatically inherit the documentation of their base function. Exceptions to this are: * When the parameter names are different. * When there is more than one base function. * When there is an explicit ``@inheritdoc`` tag which specifies which contract should be used to inherit. .. _header-output: Documentation Output ==================== When parsed by the compiler, documentation such as the one from the above example will produce two different JSON files. One is meant to be consumed by the end user as a notice when a function is executed and the other to be used by the developer. If the above contract is saved as ``ex1.sol`` then you can generate the documentation using: .. code-block:: shell solc --userdoc --devdoc ex1.sol And the output is below. .. note:: Starting Solidity version 0.6.11 the NatSpec output also contains a ``version`` and a ``kind`` field. Currently the ``version`` is set to ``1`` and ``kind`` must be one of ``user`` or ``dev``. In the future it is possible that new versions will be introduced, deprecating older ones. .. _header-user-doc: User Documentation ------------------ The above documentation will produce the following user documentation JSON file as output for the ``Tree`` contract: .. code-block:: json { "version" : 1, "kind" : "user", "methods" : { "age(uint256)" : { "notice" : "Calculate tree age in years, rounded up, for live trees" }, "leaves()" : { "notice" : "Returns the amount of leaves the tree has." } }, "notice" : "You can use this contract for only the most basic simulation" } Note that the key by which to find the methods is the function's canonical signature as defined in the :ref:`Contract ABI ` and not simply the function's name. .. _header-developer-doc: Developer Documentation ----------------------- Apart from the user documentation file, a developer documentation JSON file should also be produced and should look like this: .. code-block:: json { "version" : 1, "kind" : "dev", "author" : "Larry A. Gardner", "details" : "All function calls are currently implemented without side effects", "custom:experimental" : "This is an experimental contract.", "methods" : { "age(uint256)" : { "details" : "The Alexandr N. Tetearing algorithm could increase precision", "params" : { "rings" : "The number of rings from dendrochronological sample" }, "returns" : { "_0" : "Age in years, rounded up for partial years", "_1" : "Name of the tree" } }, "leaves()" : { "details" : "Returns only a fixed number." } }, "title" : "A simulator for trees" } ================================================ FILE: docs/path-resolution.rst ================================================ .. _path-resolution: ********************** Import Path Resolution ********************** In order to be able to support reproducible builds on all platforms, the Solidity compiler has to abstract away the details of the filesystem where source files are stored. Paths used in imports must work the same way everywhere while the command-line interface must be able to work with platform-specific paths to provide good user experience. This section aims to explain in detail how Solidity reconciles these requirements. .. index:: ! virtual filesystem, ! VFS, ! source unit name .. _virtual-filesystem: Virtual Filesystem ================== The compiler maintains an internal database (*virtual filesystem* or *VFS* for short) where each source unit is assigned a unique *source unit name* which is an opaque and unstructured identifier. When you use the :ref:`import statement `, you specify an *import path* that references a source unit name. .. index:: ! import callback, ! Host Filesystem Loader, ! --no-import-callback .. _import-callback: Import Callback --------------- The VFS is initially populated only with files the compiler has received as input. Additional files can be loaded during compilation using an *import callback*, which is different depending on the type of compiler you use (see below). If the compiler does not find any source unit name matching the import path in the VFS, it invokes the callback, which is responsible for obtaining the source code to be placed under that name. An import callback is free to interpret source unit names in an arbitrary way, not just as paths. If there is no callback available when one is needed or if it fails to locate the source code, compilation fails. By default, the command-line compiler provides the *Host Filesystem Loader* - a rudimentary callback that interprets a source unit name as a path in the local filesystem. This callback can be disabled using the ``--no-import-callback`` command-line option. The `JavaScript interface `_ does not provide any by default, but one can be provided by the user. This mechanism can be used to obtain source code from locations other than the local filesystem (which may not even be accessible, e.g. when the compiler is running in a browser). For example the `Remix IDE `_ provides a versatile callback that lets you `import files from HTTP, IPFS and Swarm URLs or refer directly to packages in NPM registry `_. .. note:: Host Filesystem Loader's file lookup is platform-dependent. For example backslashes in a source unit name can be interpreted as directory separators or not and the lookup can be case-sensitive or not, depending on the underlying platform. For portability it is recommended to avoid using import paths that will work correctly only with a specific import callback or only on one platform. For example you should always use forward slashes since they work as path separators also on platforms that support backslashes. Initial Content of the Virtual Filesystem ----------------------------------------- The initial content of the VFS depends on how you invoke the compiler: #. **solc / command-line interface** When you compile a file using the command-line interface of the compiler, you provide one or more paths to files containing Solidity code: .. code-block:: bash solc contract.sol /usr/local/dapp-bin/token.sol The source unit name of a file loaded this way is constructed by converting its path to a canonical form and, if possible, making it relative to either the base path or one of the include paths. See :ref:`CLI Path Normalization and Stripping ` for a detailed description of this process. .. index:: standard JSON #. **Standard JSON** When using the :ref:`Standard JSON ` API (via either the `JavaScript interface `_ or the ``--standard-json`` command-line option) you provide input in JSON format, containing, among other things, the content of all your source files: .. code-block:: json { "language": "Solidity", "sources": { "contract.sol": { "content": "import \"./util.sol\";\ncontract C {}" }, "util.sol": { "content": "library Util {}" }, "/usr/local/dapp-bin/token.sol": { "content": "contract Token {}" } }, "settings": {"outputSelection": {"*": { "*": ["metadata", "evm.bytecode"]}}} } The ``sources`` dictionary becomes the initial content of the virtual filesystem and its keys are used as source unit names. .. _initial-vfs-content-standard-json-with-import-callback: #. **Standard JSON (via import callback)** With Standard JSON it is also possible to tell the compiler to use the import callback to obtain the source code: .. code-block:: json { "language": "Solidity", "sources": { "/usr/local/dapp-bin/token.sol": { "urls": [ "/projects/mytoken.sol", "https://example.com/projects/mytoken.sol" ] } }, "settings": {"outputSelection": {"*": { "*": ["metadata", "evm.bytecode"]}}} } If an import callback is available, the compiler will give it the strings specified in ``urls`` one by one, until one is loaded successfully or the end of the list is reached. The source unit names are determined the same way as when using ``content`` - they are keys of the ``sources`` dictionary and the content of ``urls`` does not affect them in any way. .. index:: standard input, stdin, #. **Standard input** On the command-line it is also possible to provide the source by sending it to compiler's standard input: .. code-block:: bash echo 'import "./util.sol"; contract C {}' | solc - ``-`` used as one of the arguments instructs the compiler to place the content of the standard input in the virtual filesystem under a special source unit name: ````. Once the VFS is initialized, additional files can still be added to it only through the import callback. .. index:: ! import; path Imports ======= The import statement specifies an *import path*. Based on how the import path is specified, we can divide imports into two categories: - :ref:`Direct imports `, where you specify the full source unit name directly. - :ref:`Relative imports `, where you specify a path starting with ``./`` or ``../`` to be combined with the source unit name of the importing file. .. code-block:: solidity :caption: contracts/contract.sol import "./math/math.sol"; import "contracts/tokens/token.sol"; In the above ``./math/math.sol`` and ``contracts/tokens/token.sol`` are import paths while the source unit names they translate to are ``contracts/math/math.sol`` and ``contracts/tokens/token.sol`` respectively. .. index:: ! direct import, import; direct .. _direct-imports: Direct Imports -------------- An import that does not start with ``./`` or ``../`` is a *direct import*. .. code-block:: solidity import "/project/lib/util.sol"; // source unit name: /project/lib/util.sol import "lib/util.sol"; // source unit name: lib/util.sol import "@openzeppelin/address.sol"; // source unit name: @openzeppelin/address.sol import "https://example.com/token.sol"; // source unit name: https://example.com/token.sol After applying any :ref:`import remappings ` the import path simply becomes the source unit name. .. note:: A source unit name is just an identifier and even if its value happens to look like a path, it is not subject to the normalization rules you would typically expect in a shell. Any ``/./`` or ``/../`` segments or sequences of multiple slashes remain a part of it. When the source is provided via Standard JSON interface it is entirely possible to associate different content with source unit names that would refer to the same file on disk. When the source is not available in the virtual filesystem, the compiler passes the source unit name to the import callback. The Host Filesystem Loader will attempt to use it as a path and look up the file on disk. At this point the platform-specific normalization rules kick in and names that were considered different in the VFS may actually result in the same file being loaded. For example ``/project/lib/math.sol`` and ``/project/lib/../lib///math.sol`` are considered completely different in the VFS even though they refer to the same file on disk. .. note:: Even if an import callback ends up loading source code for two different source unit names from the same file on disk, the compiler will still see them as separate source units. It is the source unit name that matters, not the physical location of the code. .. index:: ! relative import, ! import; relative .. _relative-imports: Relative Imports ---------------- An import starting with ``./`` or ``../`` is a *relative import*. Such imports specify a path relative to the source unit name of the importing source unit: .. code-block:: solidity :caption: /project/lib/math.sol import "./util.sol" as util; // source unit name: /project/lib/util.sol import "../token.sol" as token; // source unit name: /project/token.sol .. code-block:: solidity :caption: lib/math.sol import "./util.sol" as util; // source unit name: lib/util.sol import "../token.sol" as token; // source unit name: token.sol .. note:: Relative imports **always** start with ``./`` or ``../`` so ``import "util.sol"``, unlike ``import "./util.sol"``, is a direct import. While both paths would be considered relative in the host filesystem, ``util.sol`` is actually absolute in the VFS. Let us define a *path segment* as any non-empty part of the path that does not contain a separator and is bounded by two path separators. A separator is a forward slash or the beginning/end of the string. For example in ``./abc/..//`` there are three path segments: ``.``, ``abc`` and ``..``. The compiler resolves the import into a source unit name based on the import path, in the following way: #. We start with the source unit name of the importing source unit. #. The last path segment with preceding slashes is removed from the resolved name. #. Then, for every segment in the import path, starting from the leftmost one: - If the segment is ``.``, it is skipped. - If the segment is ``..``, the last path segment with preceding slashes is removed from the resolved name. - Otherwise, the segment (preceded by a single slash if the resolved name is not empty), is appended to the resolved name. The removal of the last path segment with preceding slashes is understood to work as follows: 1. Everything past the last slash is removed (i.e. ``a/b//c.sol`` becomes ``a/b//``). 2. All trailing slashes are removed (i.e. ``a/b//`` becomes ``a/b``). Note that the process normalizes the part of the resolved source unit name that comes from the import path according to the usual rules for UNIX paths, i.e. all ``.`` and ``..`` are removed and multiple slashes are squashed into a single one. On the other hand, the part that comes from the source unit name of the importing module remains unnormalized. This ensures that the ``protocol://`` part does not turn into ``protocol:/`` if the importing file is identified with a URL. If your import paths are already normalized, you can expect the above algorithm to produce very intuitive results. Here are some examples of what you can expect if they are not: .. code-block:: solidity :caption: lib/src/../contract.sol import "./util/./util.sol"; // source unit name: lib/src/../util/util.sol import "./util//util.sol"; // source unit name: lib/src/../util/util.sol import "../util/../array/util.sol"; // source unit name: lib/src/array/util.sol import "../.././../util.sol"; // source unit name: util.sol import "../../.././../util.sol"; // source unit name: util.sol .. note:: The use of relative imports containing leading ``..`` segments is not recommended. The same effect can be achieved in a more reliable way by using direct imports with :ref:`base path and include paths `. .. index:: ! base path, ! --base-path, ! include paths, ! --include-path .. _base-and-include-paths: Base Path and Include Paths =========================== The base path and include paths represent directories that the Host Filesystem Loader will load files from. When a source unit name is passed to the loader, it prepends the base path to it and performs a filesystem lookup. If the lookup does not succeed, the same is done with all directories on the include path list. It is recommended to set the base path to the root directory of your project and use include paths to specify additional locations that may contain libraries your project depends on. This lets you import from these libraries in a uniform way, no matter where they are located in the filesystem relative to your project. For example, if you use npm to install packages and your contract imports ``@openzeppelin/contracts/utils/Strings.sol``, you can use these options to tell the compiler that the library can be found in one of the npm package directories: .. code-block:: bash solc contract.sol \ --base-path . \ --include-path node_modules/ \ --include-path /usr/local/lib/node_modules/ Your contract will compile (with the same exact metadata) no matter whether you install the library in the local or global package directory or even directly under your project root. By default the base path is empty, which leaves the source unit name unchanged. When the source unit name is a relative path, this results in the file being looked up in the directory the compiler has been invoked from. It is also the only value that results in absolute paths in source unit names being actually interpreted as absolute paths on disk. If the base path itself is relative, it is interpreted as relative to the current working directory of the compiler. .. note:: Include paths cannot have empty values and must be used together with a non-empty base path. .. note:: Include paths and base path can overlap as long as it does not make import resolution ambiguous. For example, you can specify a directory inside base path as an include directory or have an include directory that is a subdirectory of another include directory. The compiler will only issue an error if the source unit name passed to the Host Filesystem Loader represents an existing path when combined with multiple include paths or an include path and base path. .. _cli-path-normalization-and-stripping: CLI Path Normalization and Stripping ------------------------------------ On the command-line the compiler behaves just as you would expect from any other program: it accepts paths in a format native to the platform and relative paths are relative to the current working directory. The source unit names assigned to files whose paths are specified on the command-line, however, should not change just because the project is being compiled on a different platform or because the compiler happens to have been invoked from a different directory. To achieve this, paths to source files coming from the command-line must be converted to a canonical form, and, if possible, made relative to the base path or one of the include paths. The normalization rules are as follows: - If a path is relative, it is made absolute by prepending the current working directory to it. - Internal ``.`` and ``..`` segments are collapsed. - Platform-specific path separators are replaced with forward slashes. - Sequences of multiple consecutive path separators are squashed into a single separator (unless they are the leading slashes of an `UNC path `_). - If the path includes a root name (e.g. a drive letter on Windows) and the root is the same as the root of the current working directory, the root is replaced with ``/``. - Symbolic links in the path are **not** resolved. - The only exception is the path to the current working directory prepended to relative paths in the process of making them absolute. On some platforms the working directory is reported always with symbolic links resolved so for consistency the compiler resolves them everywhere. - The original case of the path is preserved even if the filesystem is case-insensitive but `case-preserving `_ and the actual case on disk is different. .. note:: There are situations where paths cannot be made platform-independent. For example on Windows the compiler can avoid using drive letters by referring to the root directory of the current drive as ``/`` but drive letters are still necessary for paths leading to other drives. You can avoid such situations by ensuring that all the files are available within a single directory tree on the same drive. After normalization the compiler attempts to make the source file path relative. It tries the base path first and then the include paths in the order they were given. If the base path is empty or not specified, it is treated as if it was equal to the path to the current working directory (with all symbolic links resolved). The result is accepted only if the normalized directory path is the exact prefix of the normalized file path. Otherwise the file path remains absolute. This makes the conversion unambiguous and ensures that the relative path does not start with ``../``. The resulting file path becomes the source unit name. .. note:: The relative path produced by stripping must remain unique within the base path and include paths. For example the compiler will issue an error for the following command if both ``/project/contract.sol`` and ``/lib/contract.sol`` exist: .. code-block:: bash solc /project/contract.sol --base-path /project --include-path /lib .. note:: Prior to version 0.8.8, CLI path stripping was not performed and the only normalization applied was the conversion of path separators. When working with older versions of the compiler it is recommended to invoke the compiler from the base path and to only use relative paths on the command-line. .. index:: ! allowed paths, ! --allow-paths, remapping; target .. _allowed-paths: Allowed Paths ============= As a security measure, the Host Filesystem Loader will refuse to load files from outside of a few locations that are considered safe by default: - Outside of Standard JSON mode: - The directories containing input files listed on the command-line. - The directories used as :ref:`remapping ` targets. If the target is not a directory (i.e does not end with ``/``, ``/.`` or ``/..``) the directory containing the target is used instead. - Base path and include paths. - In Standard JSON mode: - Base path and include paths. Additional directories can be whitelisted using the ``--allow-paths`` option. The option accepts a comma-separated list of paths: .. code-block:: bash cd /home/user/project/ solc token/contract.sol \ lib/util.sol=libs/util.sol \ --base-path=token/ \ --include-path=/lib/ \ --allow-paths=../utils/,/tmp/libraries When the compiler is invoked with the command shown above, the Host Filesystem Loader will allow importing files from the following directories: - ``/home/user/project/token/`` (because ``token/`` contains the input file and also because it is the base path), - ``/lib/`` (because ``/lib/`` is one of the include paths), - ``/home/user/project/libs/`` (because ``libs/`` is a directory containing a remapping target), - ``/home/user/utils/`` (because of ``../utils/`` passed to ``--allow-paths``), - ``/tmp/libraries/`` (because of ``/tmp/libraries`` passed to ``--allow-paths``), .. note:: The working directory of the compiler is one of the paths allowed by default only if it happens to be the base path (or the base path is not specified or has an empty value). .. note:: The compiler does not check if allowed paths actually exist and whether they are directories. Non-existent or empty paths are simply ignored. If an allowed path matches a file rather than a directory, the file is considered whitelisted, too. .. note:: Allowed paths are case-sensitive even if the filesystem is not. The case must exactly match the one used in your imports. For example ``--allow-paths tokens`` will not match ``import "Tokens/IERC20.sol"``. .. warning:: Files and directories only reachable through symbolic links from allowed directories are not automatically whitelisted. For example if ``token/contract.sol`` in the example above was actually a symlink pointing at ``/etc/passwd`` the compiler would refuse to load it unless ``/etc/`` was one of the allowed paths too. .. index:: ! remapping; import, ! import; remapping, ! remapping; context, ! remapping; prefix, ! remapping; target .. _import-remapping: Import Remapping ================ Import remapping allows you to redirect imports to a different location in the virtual filesystem. The mechanism works by changing the translation between import paths and source unit names. For example you can set up a remapping so that any import from the virtual directory ``github.com/ethereum/dapp-bin/library/`` would be seen as an import from ``dapp-bin/library/`` instead. You can limit the scope of a remapping by specifying a *context*. This allows creating remappings that apply only to imports located in a specific library or a specific file. Without a context a remapping is applied to every matching import in all the files in the virtual filesystem. Import remappings have the form of ``context:prefix=target``: - ``context`` must match the beginning of the source unit name of the file containing the import. - ``prefix`` must match the beginning of the source unit name resulting from the import. - ``target`` is the value the prefix is replaced with. For example, if you clone https://github.com/ethereum/dapp-bin/ locally to ``/project/dapp-bin`` and run the compiler with: .. code-block:: bash solc github.com/ethereum/dapp-bin/=dapp-bin/ --base-path /project source.sol you can use the following in your source file: .. code-block:: solidity import "github.com/ethereum/dapp-bin/library/math.sol"; // source unit name: dapp-bin/library/math.sol The compiler will look for the file in the VFS under ``dapp-bin/library/math.sol``. If the file is not available there, the source unit name will be passed to the Host Filesystem Loader, which will then look in ``/project/dapp-bin/library/math.sol``. .. warning:: Information about remappings is stored in contract metadata. Since the binary produced by the compiler has a hash of the metadata embedded in it, any modification to the remappings will result in different bytecode. For this reason you should be careful not to include any local information in remapping targets. For example if your library is located in ``/home/user/packages/mymath/math.sol``, a remapping like ``@math/=/home/user/packages/mymath/`` would result in your home directory being included in the metadata. To be able to reproduce the same bytecode with such a remapping on a different machine, you would need to recreate parts of your local directory structure in the VFS and (if you rely on Host Filesystem Loader) also in the host filesystem. To avoid having your local directory structure embedded in the metadata, it is recommended to designate the directories containing libraries as *include paths* instead. For example, in the example above ``--include-path /home/user/packages/`` would let you use imports starting with ``mymath/``. Unlike remapping, the option on its own will not make ``mymath`` appear as ``@math`` but this can be achieved by creating a symbolic link or renaming the package subdirectory. As a more complex example, suppose you rely on a module that uses an old version of dapp-bin that you checked out to ``/project/dapp-bin_old``, then you can run: .. code-block:: bash solc module1:github.com/ethereum/dapp-bin/=dapp-bin/ \ module2:github.com/ethereum/dapp-bin/=dapp-bin_old/ \ --base-path /project \ source.sol This means that all imports in ``module2`` point to the old version but imports in ``module1`` point to the new version. Here are the detailed rules governing the behavior of remappings: #. **Remappings only affect the translation between import paths and source unit names.** Source unit names added to the VFS in any other way cannot be remapped. For example the paths you specify on the command-line and the ones in ``sources.urls`` in Standard JSON are not affected. .. code-block:: bash solc /project/=/contracts/ /project/contract.sol # source unit name: /project/contract.sol In the example above the compiler will load the source code from ``/project/contract.sol`` and place it under that exact source unit name in the VFS, not under ``/contract/contract.sol``. #. **Context and prefix must match source unit names, not import paths.** - This means that you cannot remap ``./`` or ``../`` directly since they are replaced during the translation to source unit name but you can remap the part of the name they are replaced with: .. code-block:: bash solc ./=a/ /project/=b/ /project/contract.sol # source unit name: /project/contract.sol .. code-block:: solidity :caption: /project/contract.sol import "./util.sol" as util; // source unit name: b/util.sol - You cannot remap base path or any other part of the path that is only added internally by an import callback: .. code-block:: bash solc /project/=/contracts/ /project/contract.sol --base-path /project # source unit name: contract.sol .. code-block:: solidity :caption: /project/contract.sol import "util.sol" as util; // source unit name: util.sol #. **Target is inserted directly into the source unit name and does not necessarily have to be a valid path.** - It can be anything as long as the import callback can handle it. In case of the Host Filesystem Loader this includes also relative paths. When using the JavaScript interface you can even use URLs and abstract identifiers if your callback can handle them. - Remapping happens after relative imports have already been resolved into source unit names. This means that targets starting with ``./`` and ``../`` have no special meaning and are relative to the base path rather than to the location of the source file. - Remapping targets are not normalized so ``@root/=./a/b//`` will remap ``@root/contract.sol`` to ``./a/b//contract.sol`` and not ``a/b/contract.sol``. - If the target does not end with a slash, the compiler will not add one automatically: .. code-block:: bash solc /project/=/contracts /project/contract.sol # source unit name: /project/contract.sol .. code-block:: solidity :caption: /project/contract.sol import "/project/util.sol" as util; // source unit name: /contractsutil.sol #. **Context and prefix are patterns and matches must be exact.** - ``a//b=c`` will not match ``a/b``. - source unit names are not normalized so ``a/b=c`` will not match ``a//b`` either. - Parts of file and directory names can match as well. ``/newProject/con:/new=old`` will match ``/newProject/contract.sol`` and remap it to ``oldProject/contract.sol``. #. **At most one remapping is applied to a single import.** - If multiple remappings match the same source unit name, the one with the longest matching context is chosen. - If contexts are identical, the one with the longest matching prefix is chosen. - If contexts and prefixes are identical, the one specified last wins. - Remappings do not work on other remappings. For example ``a=b b=c c=d`` will not result in ``a`` being remapped to ``d``. #. **Prefix cannot be empty but context and target are optional.** - If ``target`` is the empty string, ``prefix`` is simply removed from import paths. - Empty ``context`` means that the remapping applies to all imports in all source units. .. index:: Remix IDE, file:// Using URLs in imports ===================== Most URL prefixes such as ``https://`` or ``data://`` have no special meaning in import paths. The only exception is ``file://`` which is stripped from source unit names by the Host Filesystem Loader. When compiling locally you can use import remapping to replace the protocol and domain part with a local path: .. code-block:: bash solc :https://github.com/ethereum/dapp-bin=/usr/local/dapp-bin contract.sol Note the leading ``:``, which is necessary when the remapping context is empty. Otherwise the ``https:`` part would be interpreted by the compiler as the context. ================================================ FILE: docs/requirements.txt ================================================ # Older versions of sphinx-rtd-theme do not work with never docutils but have a bug in the dependency # which could result in it being installed anyway and the style (especially bullet points) being broken. # See https://github.com/readthedocs/sphinx_rtd_theme/issues/1115 # theme >=3.0.0 removes the display_version option in favor of version_selector and language_selector # Use rtd theme version that supports sphinx>=8.0 sphinx_rtd_theme>=3.0.0 pygments-lexer-solidity>=0.7.0 sphinx-syntax>=1.0.1 # Sphinx version constraints for sphinx-syntax compatibility sphinx>=8.0.0, <9.0.0 ================================================ FILE: docs/resources.rst ================================================ ######### Resources ######### General Resources ================= * `Ethereum.org Developers page `_ * `Ethereum StackExchange `_ * `Solidity website `_ * `Solidity changelog `_ * `Solidity codebase on GitHub `_ * `Solidity language users chat `_ * `Solidity compiler developers chat `_ * `awesome-solidity `_ * `Solidity by Example `_ * `Solidity documentation community translations `_ * `Solidity and Smart Contract Glossary `_ Integrated (Ethereum) Development Environments ============================================== * `Ape `_ A Python-based web3 development tool for compiling, testing, and interacting with smart contracts. * `Brownie `_ A Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine. 💡 Note: As per the official docs, Brownie is no longer actively maintained. Future releases may come sporadically - or never at all. Check out Ape Framework (first in list) for all your python Ethereum development needs. * `Dapp `_ Tool for building, testing and deploying smart contracts from the command-line. * `Foundry `_ Fast, portable and modular toolkit for Ethereum application development written in Rust. * `Hardhat `_ Ethereum development environment with local Ethereum network, debugging features and plugin ecosystem. * `Remix `_ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. * `Truffle `_ Ethereum development framework. 💡 Note: Consensys announced the sunset of Truffle on September 21, 2023. Current users may check out the migration path and available product support `here. `_ Editor Integrations =================== * Emacs * `Emacs Solidity `_ Plugin for the Emacs editor providing syntax highlighting and compilation error reporting. * IntelliJ * `IntelliJ IDEA plugin `_ Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs). * Sublime Text * `Package for SublimeText - Solidity language syntax `_ Solidity syntax highlighting for SublimeText editor. * Vim * `Vim Solidity by Thesis `_ Syntax highlighting for Solidity in Vim. * `Vim Solidity by TovarishFin `_ Vim syntax file for Solidity. * `Vim Syntastic `_ Plugin for the Vim editor providing compile checking. * Visual Studio Code (VS Code) * `Aderyn Visual Studio Code extension `_ Solidity Smart contract analyzer designed to help find vulnerabilities. It supports projects built with Hardhat, Foundry, or any custom framework. * `Ethereum Remix Visual Studio Code extension `_ Ethereum Remix extension pack for VS Code 💡 Note: As per the official repository, this extension has been removed from the VSCODE marketplace and will be replaced by a dedicated stand-alone desktop application. * `Solidity Visual Studio Code extension, by Juan Blanco `_ Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler. * `Solidity Visual Studio Code extension, by Nomic Foundation `_ Solidity and Hardhat support by the Hardhat team, including: syntax highlighting, jump to definition, renames, quick fixes and inline solc warnings and errors. * `Solidity Visual Auditor extension `_ Adds security centric syntax and semantic highlighting to Visual Studio Code. * `Truffle for VS Code `_ Build, debug and deploy smart contracts on Ethereum and EVM-compatible blockchains. 💡 Note: This extension has built-in support for the Truffle Suite which is being sunset. For information on ongoing support, migration options and FAQs, visit the `Consensys blog. `_ Solidity Tools ============== * `ABI to Solidity interface converter `_ A script for generating contract interfaces from the ABI of a smart contract. * `abi-to-sol `_ Tool to generate Solidity interface source from a given ABI JSON. * `Aderyn `_ Command Line Tool that helps find vulnerabilities in Solidity smart contracts. It supports projects built with Hardhat, Foundry, or any custom framework. * `Doxity `_ Documentation Generator for Solidity. * `ethdebug `_ A standard debugging data format for smart contracts on Ethereum-compatible networks. * `Ethlint `_ Linter to identify and fix style and security issues in Solidity. * `evmdis `_ EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. * `EVM Lab `_ A collection of tools to interact with the EVM. The package includes a VM, Etherchain API, and a trace-viewer with gas cost display. * `hevm `_ EVM debugger and symbolic execution engine. * `leafleth `_ A documentation generator for Solidity smart-contracts. * `Scaffold-ETH 2 `_ Forkable Ethereum development stack focused on fast product iterations. * `Slippy `_ A simple and powerful linter for Solidity. * `sol2uml `_ Unified Modeling Language (UML) class diagram generator for Solidity contracts. * `solc-select `_ A script to quickly switch between Solidity compiler versions. * `Solidity prettier plugin `_ A Prettier Plugin for Solidity. * `Solidity REPL `_ Try Solidity instantly with a command-line Solidity console. * `solgraph `_ Visualize Solidity control flow and highlight potential security vulnerabilities. * `Solhint `_ Solidity linter that provides security, style guide and best practice rules for smart contract validation. * `Sourcify `_ Decentralized automated contract verification service and public repository of contract metadata. * `Sūrya `_ Utility tool for smart contract systems, offering a number of visual outputs and information about the contracts' structure. Also supports querying the function call graph. * `Universal Mutator `_ A tool for mutation generation, with configurable rules and support for Solidity and Vyper. * `Wake `_ A Python-based Solidity development and testing framework with built-in vulnerability detectors. Third-Party Solidity Parsers and Grammars ========================================= * `Solidity Parser for JavaScript `_ A Solidity parser for JS built on top of a robust ANTLR4 grammar. ================================================ FILE: docs/robots.txt.template ================================================ User-Agent: * Sitemap: http://docs.soliditylang.org/sitemap.xml Host: docs.soliditylang.org Allow: /en/latest/ Allow: /en/v0.7.6/ Allow: /en/v{{ LATEST_VERSION }}/ Allow: /_/downloads/en/latest/ Allow: /_/downloads/en/0.7.6/ Allow: /_/downloads/en/{{ LATEST_VERSION }}/ # Prevent documentation for the development branches and older Solidity # versions from showing up in search results. Disallow: /en/* Disallow: /_/downloads/en/* ================================================ FILE: docs/security-considerations.rst ================================================ .. _security_considerations: ####################### Security Considerations ####################### While it is usually quite easy to build software that works as expected, it is much harder to check that nobody can use it in a way that was **not** anticipated. In Solidity, this is even more important because you can use smart contracts to handle tokens or, possibly, even more valuable things. Furthermore, every execution of a smart contract happens in public and, in addition to that, the source code is often available. Of course, you always have to consider how much is at stake: You can compare a smart contract with a web service that is open to the public (and thus, also to malicious actors) and perhaps even open-source. If you only store your grocery list on that web service, you might not have to take too much care, but if you manage your bank account using that web service, you should be more careful. This section will list some pitfalls and general security recommendations but can, of course, never be complete. Also, keep in mind that even if your smart contract code is bug-free, the compiler or the platform itself might have a bug. A list of some publicly known security-relevant bugs of the compiler can be found in the :ref:`list of known bugs`, which is also machine-readable. Note that there is a `Bug Bounty Program `_ that covers the code generator of the Solidity compiler. As always, with open-source documentation, please help us extend this section (especially, some examples would not hurt)! NOTE: In addition to the list below, you can find more security recommendations and best practices `in Guy Lando's knowledge list `_ and `the Consensys GitHub repo `_. ******** Pitfalls ******** Private Information and Randomness ================================== Everything you use in a smart contract is publicly visible, even local variables and state variables marked ``private``. Using random numbers in smart contracts is quite tricky if you do not want block builders to be able to cheat. Reentrancy ========== Any interaction from a contract (A) with another contract (B) and any transfer of Ether hands over control to that contract (B). This makes it possible for B to call back into A before this interaction is completed. To give an example, the following code contains a bug (it is just a snippet and not a complete contract): .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract Fund { /// @dev Mapping of ether shares of the contract. mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { // This will report a warning (deprecation) if (payable(msg.sender).send(shares[msg.sender])) shares[msg.sender] = 0; } } The problem is not too serious here because of the limited gas as part of ``send``, but it still exposes a weakness: Ether transfer can always include code execution, so the recipient could be a contract that calls back into ``withdraw``. This would let it get multiple refunds and, basically, retrieve all the Ether in the contract. In particular, the following contract will allow an attacker to refund multiple times as it uses ``call`` which does not limit the amount of gas that is forwarded by default: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract Fund { /// @dev Mapping of ether shares of the contract. mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { (bool success,) = msg.sender.call{value: shares[msg.sender]}(""); if (success) shares[msg.sender] = 0; } } To avoid reentrancy, you can use the Checks-Effects-Interactions pattern as demonstrated below: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.2 <0.9.0; contract Fund { /// @dev Mapping of ether shares of the contract. mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { uint share = shares[msg.sender]; shares[msg.sender] = 0; (bool success, ) = payable(msg.sender).call{value: share}(""); require(success); } } The Checks-Effects-Interactions pattern ensures that all code paths through a contract complete all required checks of the supplied parameters before modifying the contract's state (Checks); only then it makes any changes to the state (Effects); it may make calls to functions in other contracts *after* all planned state changes have been written to storage (Interactions). This is a common foolproof way to prevent *reentrancy attacks*, where an externally called malicious contract can double-spend an allowance, double-withdraw a balance, among other things, by using logic that calls back into the original contract before it has finalized its transaction. Note that reentrancy is not only an effect of Ether transfer but of any function call on another contract. Furthermore, you also have to take multi-contract situations into account. A called contract could modify the state of another contract you depend on. Gas Limit and Loops =================== Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully: Due to the block gas limit, transactions can only consume a certain amount of gas. Either explicitly or just due to normal operation, the number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. This may not apply to ``view`` functions that are only executed to read data from the blockchain. Still, such functions may be called by other contracts as part of on-chain operations and stall those. Please be explicit about such cases in the documentation of your contracts. Sending and Receiving Ether =========================== - Neither contracts nor "externally-owned accounts" are currently able to prevent someone from sending them Ether. Contracts can react on and reject a regular transfer, but there are ways to move Ether without creating a message call. One way is to simply "mine to" the contract address and the second way is using ``selfdestruct(x)``. - If a contract receives Ether (without a function being called), either the :ref:`receive Ether ` or the :ref:`fallback ` function is executed. If it does not have a ``receive`` nor a ``fallback`` function, the Ether will be rejected (by throwing an exception). During the execution of one of these functions, the contract can only rely on the "gas stipend" it is passed (2300 gas) being available to it at that time. This stipend is not enough to modify storage (do not take this for granted though, the stipend might change with future hard forks). To be sure that your contract can receive Ether in that way, check the gas requirements of the receive and fallback functions (for example in the "details" section in Remix). - There is a way to forward more gas to the receiving contract using ``addr.call{value: x}("")``. This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas, subject to additional limits imposed by some EVM versions (such as the `63/64th rule `_ introduced by ``tangerineWhistle``), and opens up the ability for the recipient to perform more expensive actions (and it returns a failure code instead of automatically propagating the error). This might include calling back into the sending contract or other state changes you might not have thought of. So it allows for great flexibility for honest users but also for malicious actors. - Use the most precise units to represent the Wei amount as possible, as you lose any that is rounded due to a lack of precision. - If you want to send Ether using ``address.transfer``, there are certain details to be aware of: 1. If the recipient is a contract, it causes its receive or fallback function to be executed which can, in turn, call back the sending contract. 2. Sending Ether can fail due to the call depth going above 1024. Since the caller is in total control of the call depth, they can force the transfer to fail; take this possibility into account or use ``send`` and make sure to always check its return value. Better yet, write your contract using a pattern where the recipient can withdraw Ether instead. 3. Sending Ether can also fail because the execution of the recipient contract requires more than the allotted amount of gas (explicitly by using :ref:`require `, :ref:`assert `, :ref:`revert ` or because the operation is too expensive) - it "runs out of gas" (OOG). If you use ``transfer`` or ``send`` with a return value check, this might provide a means for the recipient to block progress in the sending contract. Again, the best practice here is to use a :ref:`"withdraw" pattern instead of a "send" pattern `. Call Stack Depth ================ External function calls can fail at any time because they exceed the maximum call stack size limit of 1024. In such situations, Solidity throws an exception. Malicious actors might be able to force the call stack to a high value before they interact with your contract. Note that, since `Tangerine Whistle `_ hardfork, the `63/64 rule `_ makes call stack depth attack impractical. Also note that the call stack and the expression stack are unrelated, even though both have a size limit of 1024 stack slots. Note that ``.send()`` does **not** throw an exception if the call stack is depleted but rather returns ``false`` in that case. The low-level functions ``.call()``, ``.delegatecall()`` and ``.staticcall()`` behave in the same way. Authorized Proxies ================== If your contract can act as a proxy, i.e. if it can call arbitrary contracts with user-supplied data, then the user can essentially assume the identity of the proxy contract. Even if you have other protective measures in place, it is best to build your contract system such that the proxy does not have any permissions (not even for itself). If needed, you can accomplish that using a second proxy: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; contract ProxyWithMoreFunctionality { PermissionlessProxy proxy; function callOther(address addr, bytes memory payload) public returns (bool, bytes memory) { return proxy.callOther(addr, payload); } // Other functions and other functionality } // This is the full contract, it has no other functionality and // requires no privileges to work. contract PermissionlessProxy { function callOther(address addr, bytes memory payload) public returns (bool, bytes memory) { return addr.call(payload); } } tx.origin ========= Never use ``tx.origin`` for authorization. Let's say you have a wallet contract like this: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract TxUserWallet { address owner; constructor() { owner = msg.sender; } function transferTo(address payable dest, uint amount) public { // THE BUG IS RIGHT HERE, you must use msg.sender instead of tx.origin require(tx.origin == owner); // This will report a warning (deprecation) dest.transfer(amount); } } Now someone tricks you into sending Ether to the address of this attack wallet: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; interface TxUserWallet { function transferTo(address payable dest, uint amount) external; } contract TxAttackWallet { address payable owner; constructor() { owner = payable(msg.sender); } receive() external payable { TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance); } } If your wallet had checked ``msg.sender`` for authorization, it would get the address of the attack wallet, instead of the owner's address. But by checking ``tx.origin``, it gets the original address that kicked off the transaction, which is still the owner's address. The attack wallet instantly drains all your funds. .. _underflow-overflow: Two's Complement / Underflows / Overflows ========================================= As in many programming languages, Solidity's integer types are not actually integers. They resemble integers when the values are small, but cannot represent arbitrarily large numbers. The following code causes an overflow because the result of the addition is too large to be stored in the type ``uint8``: .. code-block:: solidity uint8 x = 255; uint8 y = 1; return x + y; Solidity has two modes in which it deals with these overflows: Checked and Unchecked or "wrapping" mode. The default checked mode will detect overflows and cause a failing assertion. You can disable this check using ``unchecked { ... }``, causing the overflow to be silently ignored. The above code would return ``0`` if wrapped in ``unchecked { ... }``. Even in checked mode, do not assume you are protected from overflow bugs. In this mode, overflows will always revert. If it is not possible to avoid the overflow, this can lead to a smart contract being stuck in a certain state. In general, read about the limits of two's complement representation, which even has some more special edge cases for signed numbers. Try to use ``require`` to limit the size of inputs to a reasonable range and use the :ref:`SMT checker` to find potential overflows. .. _clearing-mappings: Clearing Mappings ================= The Solidity type ``mapping`` (see :ref:`mapping-types`) is a storage-only key-value data structure that does not keep track of the keys that were assigned a non-zero value. Because of that, cleaning a mapping without extra information about the written keys is not possible. If a ``mapping`` is used as the base type of a dynamic storage array, deleting or popping the array will have no effect over the ``mapping`` elements. The same happens, for example, if a ``mapping`` is used as the type of a member field of a ``struct`` that is the base type of a dynamic storage array. The ``mapping`` is also ignored in assignments of structs or arrays containing a ``mapping``. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; contract Map { mapping(uint => uint)[] array; function allocate(uint newMaps) public { for (uint i = 0; i < newMaps; i++) array.push(); } function writeMap(uint map, uint key, uint value) public { array[map][key] = value; } function readMap(uint map, uint key) public view returns (uint) { return array[map][key]; } function eraseMaps() public { delete array; } } Consider the example above and the following sequence of calls: ``allocate(10)``, ``writeMap(4, 128, 256)``. At this point, calling ``readMap(4, 128)`` returns 256. If we call ``eraseMaps``, the length of the state variable ``array`` is zeroed, but since its ``mapping`` elements cannot be zeroed, their information stays alive in the contract's storage. After deleting ``array``, calling ``allocate(5)`` allows us to access ``array[4]`` again, and calling ``readMap(4, 128)`` returns 256 even without another call to ``writeMap``. If your ``mapping`` information must be deleted, consider using a library similar to `iterable mapping `_, allowing you to traverse the keys and delete their values in the appropriate ``mapping``. Internal Function Pointers in Upgradeable Contracts =================================================== Updating the code of your contract may :ref:`invalidate the values of variables of internal function types`. Consider such values ephemeral and avoid storing them in state variables. If you do, you must ensure that they never persist across code updates and are never used by other contracts having access to the same storage space as a result of a delegatecall or account abstraction. Minor Details ============= - Types that do not occupy the full 32 bytes might contain "dirty higher order bits". This is especially important if you access ``msg.data`` - it poses a malleability risk: You can craft transactions that call a function ``f(uint8 x)`` with a raw byte argument of ``0xff000001`` and with ``0x00000001``. Both are fed to the contract and both will look like the number ``1`` as far as ``x`` is concerned, but ``msg.data`` will be different, so if you use ``keccak256(msg.data)`` for anything, you will get different results. *************** Recommendations *************** Take Warnings Seriously ======================= If the compiler warns you about something, you should change it. Even if you do not think that this particular warning has security implications, there might be another issue buried beneath it. Any compiler warning we issue can be silenced by slight changes to the code. Always use the latest version of the compiler to be notified about all recently introduced warnings. Messages of type ``info``, issued by the compiler, are not dangerous and simply represent extra suggestions and optional information that the compiler thinks might be useful to the user. Restrict the Amount of Ether ============================ Restrict the amount of Ether (or other tokens) that can be stored in a smart contract. If your source code, the compiler or the platform has a bug, these funds may be lost. If you want to limit your loss, limit the amount of Ether. Keep it Small and Modular ========================= Keep your contracts small and easily understandable. Single out unrelated functionality in other contracts or into libraries. General recommendations about the source code quality of course apply: Limit the amount of local variables, the length of functions and so on. Document your functions so that others can see what your intention was and whether it is different than what the code does. Use the Checks-Effects-Interactions Pattern =========================================== Most functions will first perform some checks and they should be done first (who called the function, are the arguments in range, did they send enough Ether, does the person have tokens, etc.). As the second step, if all checks passed, effects to the state variables of the current contract should be made. Interaction with other contracts should be the very last step in any function. Early contracts delayed some effects and waited for external function calls to return in a non-error state. This is often a serious mistake because of the reentrancy problem explained above. Note that, also, calls to known contracts might in turn cause calls to unknown contracts, so it is probably better to just always apply this pattern. Include a Fail-Safe Mode ======================== While making your system fully decentralized will remove any intermediary, it might be a good idea, especially for new code, to include some kind of fail-safe mechanism: You can add a function in your smart contract that performs some self-checks like "Has any Ether leaked?", "Is the sum of the tokens equal to the balance of the contract?" or similar things. Keep in mind that you cannot use too much gas for that, so help through off-chain computations might be needed there. If the self-check fails, the contract automatically switches into some kind of "failsafe" mode, which, for example, disables most of the features, hands over control to a fixed and trusted third party or just converts the contract into a simple "give me back my Ether" contract. Ask for Peer Review =================== The more people examine a piece of code, the more issues are found. Asking people to review your code also helps as a cross-check to find out whether your code is easy to understand - a very important criterion for good smart contracts. ================================================ FILE: docs/smtchecker.rst ================================================ .. _formal_verification: ################################## SMTChecker and Formal Verification ################################## Using formal verification it is possible to perform an automated mathematical proof that your source code fulfills a certain formal specification. The specification is still formal (just as the source code), but usually much simpler. Note that formal verification itself can only help you understand the difference between what you did (the specification) and how you did it (the actual implementation). You still need to check whether the specification is what you wanted and that you did not miss any unintended effects of it. Solidity implements a formal verification approach based on `SMT (Satisfiability Modulo Theories) `_ and `Horn `_ solving. The SMTChecker module automatically tries to prove that the code satisfies the specification given by ``require`` and ``assert`` statements. That is, it considers ``require`` statements as assumptions and tries to prove that the conditions inside ``assert`` statements are always true. If an assertion failure is found, a counterexample may be given to the user showing how the assertion can be violated. If no warning is given by the SMTChecker for a property, it means that the property is safe. The other verification targets that the SMTChecker checks at compile time are: - Arithmetic underflow and overflow. - Division by zero. - Trivial conditions and unreachable code. - Popping an empty array. - Out of bounds index access. - Insufficient funds for a transfer. All the targets above are automatically checked by default if all engines are enabled, except underflow and overflow for Solidity >=0.8.7. The potential warnings that the SMTChecker reports are: - `` happens here.``. This means that the SMTChecker proved that a certain property fails. A counterexample may be given, however in complex situations it may also not show a counterexample. This result may also be a false positive in certain cases, when the SMT encoding adds abstractions for Solidity code that is either hard or impossible to express. - `` might happen here``. This means that the solver could not prove either case within the given timeout. Since the result is unknown, the SMTChecker reports the potential failure for soundness. This may be solved by increasing the query timeout, but the problem might also simply be too hard for the engine to solve. To enable the SMTChecker, you must select :ref:`which engine should run`, where the default is no engine. Selecting the engine enables the SMTChecker on all files. .. note:: Prior to Solidity 0.8.4, the default way to enable the SMTChecker was via ``pragma experimental SMTChecker;`` and only the contracts containing the pragma would be analyzed. That pragma has been deprecated, and although it still enables the SMTChecker for backwards compatibility, it will be removed in Solidity 0.9.0. Note also that now using the pragma even in a single file enables the SMTChecker for all files. .. note:: The lack of warnings for a verification target represents an undisputed mathematical proof of correctness, assuming no bugs in the SMTChecker and the underlying solver. Keep in mind that these problems are *very hard* and sometimes *impossible* to solve automatically in the general case. Therefore, several properties might not be solved or might lead to false positives for large contracts. Every proven property should be seen as an important achievement. For advanced users, see :ref:`SMTChecker Tuning ` to learn a few options that might help proving more complex properties. ******** Tutorial ******** Overflow ======== .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0; contract Overflow { uint immutable x; uint immutable y; function add(uint x_, uint y_) internal pure returns (uint) { return x_ + y_; } constructor(uint x_, uint y_) { (x, y) = (x_, y_); } function stateAdd() public view returns (uint) { return add(x, y); } } The contract above shows an overflow check example. The SMTChecker does not check underflow and overflow by default for Solidity >=0.8.7, so we need to use the command-line option ``--model-checker-targets "underflow,overflow"`` or the JSON option ``settings.modelChecker.targets = ["underflow", "overflow"]``. See :ref:`this section for targets configuration`. Here, it reports the following: .. code-block:: text Warning: CHC: Overflow (resulting value larger than 2**256 - 1) happens here. Counterexample: x = 1, y = 115792089237316195423570985008687907853269984665640564039457584007913129639935 = 0 Transaction trace: Overflow.constructor(1, 115792089237316195423570985008687907853269984665640564039457584007913129639935) State: x = 1, y = 115792089237316195423570985008687907853269984665640564039457584007913129639935 Overflow.stateAdd() Overflow.add(1, 115792089237316195423570985008687907853269984665640564039457584007913129639935) -- internal call --> o.sol:9:20: | 9 | return x_ + y_; | ^^^^^^^ If we add ``require`` statements that filter out overflow cases, the SMTChecker proves that no overflow is reachable (by not reporting warnings): .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0; contract Overflow { uint immutable x; uint immutable y; function add(uint x_, uint y_) internal pure returns (uint) { return x_ + y_; } constructor(uint x_, uint y_) { (x, y) = (x_, y_); } function stateAdd() public view returns (uint) { require(x < type(uint128).max); require(y < type(uint128).max); return add(x, y); } } Assert ====== An assertion represents an invariant in your code: a property that must be true *for all transactions, including all input and storage values*, otherwise there is a bug. The code below defines a function ``f`` that guarantees no overflow. Function ``inv`` defines the specification that ``f`` is monotonically increasing: for every possible pair ``(a, b)``, if ``b > a`` then ``f(b) > f(a)``. Since ``f`` is indeed monotonically increasing, the SMTChecker proves that our property is correct. You are encouraged to play with the property and the function definition to see what results come out! .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0; contract Monotonic { function f(uint x) internal pure returns (uint) { require(x < type(uint128).max); return x * 42; } function inv(uint a, uint b) public pure { require(b > a); assert(f(b) > f(a)); } } We can also add assertions inside loops to verify more complicated properties. The following code searches for the maximum element of an unrestricted array of numbers, and asserts the property that the found element must be greater or equal every element in the array. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0; contract Max { function max(uint[] memory a) public pure returns (uint) { uint m = 0; for (uint i = 0; i < a.length; ++i) if (a[i] > m) m = a[i]; for (uint i = 0; i < a.length; ++i) assert(m >= a[i]); return m; } } Note that in this example the SMTChecker will automatically try to prove three properties: 1. ``++i`` in the first loop does not overflow. 2. ``++i`` in the second loop does not overflow. 3. The assertion is always true. .. note:: The properties involve loops, which makes it *much much* harder than the previous examples, so beware of loops! All the properties are correctly proven safe. Feel free to change the properties and/or add restrictions on the array to see different results. For example, changing the code to .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0; contract Max { function max(uint[] memory a) public pure returns (uint) { require(a.length >= 5); uint m = 0; for (uint i = 0; i < a.length; ++i) if (a[i] > m) m = a[i]; for (uint i = 0; i < a.length; ++i) assert(m > a[i]); return m; } } gives us: .. code-block:: text Warning: CHC: Assertion violation happens here. Counterexample: a = [0, 0, 0, 0, 0] = 0 Transaction trace: Test.constructor() Test.max([0, 0, 0, 0, 0]) --> max.sol:14:4: | 14 | assert(m > a[i]); State Properties ================ So far the examples only demonstrated the use of the SMTChecker over pure code, proving properties about specific operations or algorithms. A common type of properties in smart contracts are properties that involve the state of the contract. Multiple transactions might be needed to make an assertion fail for such a property. As an example, consider a 2D grid where both axis have coordinates in the range (-2^127, 2^127 - 1). Let us place a robot at position (0, 0). The robot can only move diagonally, one step at a time, and cannot move outside the grid. The robot's state machine can be represented by the smart contract below. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0; contract Robot { int x = 0; int y = 0; modifier wall { require(x > type(int128).min && x < type(int128).max); require(y > type(int128).min && y < type(int128).max); _; } function moveLeftUp() wall public { --x; ++y; } function moveLeftDown() wall public { --x; --y; } function moveRightUp() wall public { ++x; ++y; } function moveRightDown() wall public { ++x; --y; } function inv() public view { assert((x + y) % 2 == 0); } } Function ``inv`` represents an invariant of the state machine that ``x + y`` must be even. The SMTChecker manages to prove that regardless how many commands we give the robot, even if infinitely many, the invariant can *never* fail. The interested reader may want to prove that fact manually as well. Hint: this invariant is inductive. We can also trick the SMTChecker into giving us a path to a certain position we think might be reachable. We can add the property that (2, 4) is *not* reachable, by adding the following function. .. code-block:: solidity function reach_2_4() public view { assert(!(x == 2 && y == 4)); } This property is false, and while proving that the property is false, the SMTChecker tells us exactly *how* to reach (2, 4): .. code-block:: text Warning: CHC: Assertion violation happens here. Counterexample: x = 2, y = 4 Transaction trace: Robot.constructor() State: x = 0, y = 0 Robot.moveLeftUp() State: x = (- 1), y = 1 Robot.moveRightUp() State: x = 0, y = 2 Robot.moveRightUp() State: x = 1, y = 3 Robot.moveRightUp() State: x = 2, y = 4 Robot.reach_2_4() --> r.sol:35:4: | 35 | assert(!(x == 2 && y == 4)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Note that the path above is not necessarily deterministic, as there are other paths that could reach (2, 4). The choice of which path is shown might change depending on the used solver, its version, or just randomly. External Calls and Reentrancy ============================= Every external call is treated as a call to unknown code by the SMTChecker. The reasoning behind that is that even if the code of the called contract is available at compile time, there is no guarantee that the deployed contract will indeed be the same as the contract where the interface came from at compile time. In some cases, it is possible to automatically infer properties over state variables that are still true even if the externally called code can do anything, including reenter the caller contract. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0; interface Unknown { function run() external; } contract Mutex { uint x; bool lock; Unknown immutable unknown; constructor(Unknown u) { require(address(u) != address(0)); unknown = u; } modifier mutex { require(!lock); lock = true; _; lock = false; } function set(uint x_) mutex public { x = x_; } function run() mutex public { uint xPre = x; unknown.run(); assert(xPre == x); } } The example above shows a contract that uses a mutex flag to forbid reentrancy. The solver is able to infer that when ``unknown.run()`` is called, the contract is already "locked", so it would not be possible to change the value of ``x``, regardless of what the unknown called code does. If we "forget" to use the ``mutex`` modifier on function ``set``, the SMTChecker is able to synthesize the behavior of the externally called code so that the assertion fails: .. code-block:: text Warning: CHC: Assertion violation happens here. Counterexample: x = 1, lock = true, unknown = 1 Transaction trace: Mutex.constructor(1) State: x = 0, lock = false, unknown = 1 Mutex.run() unknown.run() -- untrusted external call, synthesized as: Mutex.set(1) -- reentrant call --> m.sol:32:3: | 32 | assert(xPre == x); | ^^^^^^^^^^^^^^^^^ .. _smtchecker_options: ***************************** SMTChecker Options and Tuning ***************************** Timeout ======= The SMTChecker uses a hardcoded resource limit (``rlimit``) chosen per solver, which is not precisely related to time. We chose the ``rlimit`` option as the default because it gives more determinism guarantees than time inside the solver. This options translates roughly to "a few seconds timeout" per query. Of course many properties are very complex and need a lot of time to be solved, where determinism does not matter. If the SMTChecker does not manage to solve the contract properties with the default ``rlimit``, a timeout can be given in milliseconds via the CLI option ``--model-checker-timeout