void GenerateEventHelper(List <GeneratedEventMetadata> generatedEvents)
        {
            var eventMetadataHash         = GeneratedEventMetadata.GetHash(generatedEvents);
            var eventMetadataHashHex      = HexUtil.GetHexFromBytes(eventMetadataHash);
            var eventMetadataHashHexBytes = Encoding.ASCII.GetBytes(eventMetadataHashHex);

            var outputFilePath = Path.Combine(_generatedContractsDirectory, EventHelperFile + G_CS_FILE_EXT);

            if (!_returnFullSources && FileStartsWithHash(outputFilePath, eventMetadataHashHexBytes))
            {
                _logger("Skipping writing already up-to-date source file: " + EventHelperFile);
                return;
            }

            var generator = new EventHelperGenerator(generatedEvents, _namespace);

            var(generatedCode, syntaxTree) = generator.GenerateSourceCode();
            using (var fs = new StreamWriter(outputFilePath, append: false, encoding: StringUtil.UTF8))
            {
                _logger("Writing source file: " + outputFilePath);
                fs.WriteLine("//" + eventMetadataHashHex);
                fs.WriteLine(generatedCode);

                var generatedCSharpEntry = new SolCodeGenCSharpResult(outputFilePath, generatedCode, syntaxTree);
                _genResults.GeneratedCSharpEntries.Add(generatedCSharpEntry);
            }
        }
Example #2
0
        void GenerateSolcOutputDataFiles(
            OutputDescription solcOutput,
            Dictionary <string, string> soliditySourceContent,
            byte[] codeBaseHash)
        {
            var codeBaseHashBytes    = HexUtil.GetHexFromBytes(codeBaseHash);
            var codeBaseHashHexBytes = Encoding.ASCII.GetBytes(codeBaseHashBytes);

            var outputHelperFilePath = Path.Combine(_generatedContractsDirectory, SolcOutputDataHelperFile + G_CS_FILE_EXT);
            var outputResxFilePath   = Path.Combine(_generatedContractsDirectory, SolcOutputDataResxFile + G_RESX_FILE_EXT);

            if (!_returnFullSources && FileStartsWithHash(outputHelperFilePath, codeBaseHashHexBytes) && File.Exists(outputResxFilePath))
            {
                Console.WriteLine("Skipping writing already up-to-date source file: " + SolcOutputDataHelperFile);
                Console.WriteLine("Skipping writing already up-to-date source file: " + SolcOutputDataResxFile);
                return;
            }

            var solcOutputDataResxGenerator = new SolcOutputDataResxGenerator(solcOutput, soliditySourceContent, _solSourceDirectory, _solidityCompilerVersion);
            var solcOutputDataResxWriter    = solcOutputDataResxGenerator.GenerateResx();

            using (var fs = new StreamWriter(outputResxFilePath, append: false, encoding: new UTF8Encoding(false)))
            {
                solcOutputDataResxWriter.Save(fs);
                _genResults.GeneratedResxFilePath = outputResxFilePath;
            }

            if (_returnFullSources)
            {
                _genResults.GeneratedResxResources = solcOutputDataResxWriter.Resources;
            }
        }
Example #3
0
        /// <summary>
        /// Creates the 4 byte function selector from a function signature string
        /// </summary>
        /// <param name="functionSignature">Function signature, ex: "baz(uint32,bool)"</param>
        /// <param name="hexPrefix">True to prepend the hex string with "0x"</param>
        /// <returns>8 character lowercase hex string (from first 4 bytes of the sha3 hash of utf8 encoded function signature)</returns>
        public static string GetMethodIDHex(string functionSignature, bool hexPrefix = false)
        {
            var    bytes         = UTF8.GetBytes(functionSignature);
            var    hash          = KeccakHash.ComputeHash(bytes).Slice(0, 4);
            string funcSignature = HexUtil.GetHexFromBytes(hash, hexPrefix: hexPrefix);

            return(funcSignature);
        }
Example #4
0
        public void Extension_String()
        {
            var hexString = "d52828f9194553d3c96ca255140ed7b223b4edbe686d5be594fcc984f3e2e2d1fc5779027451e033e6264db1708fdc12ad7629d902372c68cd43651d7bcee0e689d158bc94d53ed1d3bad84120a9740420b7d77cb908cec42b113530ecc3b7174666279e";
            var decoded   = hexString.HexToBytes();
            var recoded   = HexUtil.GetHexFromBytes(decoded);

            Assert.Equal(hexString, recoded);
        }
Example #5
0
        public void Decode_Uppercase()
        {
            var hexString = "D52828F9194553D3C96CA255140ED7B223B4EDBE686D5BE594FCC984F3E2E2D1FC5779027451E033E6264DB1708FDC12AD7629D902372C68CD43651D7BCEE0E689D158BC94D53ED1D3BAD84120A9740420B7D77CB908CEC42B113530ECC3B7174666279E";
            var decoded   = HexUtil.HexToBytes(hexString);
            var recoded   = HexUtil.GetHexFromBytes(decoded);

            Assert.Equal(hexString.ToLowerInvariant(), recoded);
        }
        protected override string GenerateUsingDeclarations()
        {
            var hashHex            = HexUtil.GetHexFromBytes(_codebaseHash);
            var sourceAttrTypeName = typeof(GeneratedSolcDataAttribute).FullName;
            var assemblyAttr       = $"[assembly: {sourceAttrTypeName}(\"{hashHex}\")]";

            return(assemblyAttr);
        }
Example #7
0
        public static string GetHex(params IAbiTypeEncoder[] encoders)
        {
            // get length of all encoded params
            int totalLen = GetEncodedLength(encoders);

            // create buffer to write encoded params into
            Span <byte>     data = stackalloc byte[totalLen];
            AbiEncodeBuffer buff = new AbiEncodeBuffer(data, encoders.GetTypeInfo());

            // encode transaction arguments
            WriteParams(encoders, ref buff);

            // hex encode
            return(HexUtil.GetHexFromBytes(data, hexPrefix: true));
        }
Example #8
0
        public void Int24_1()
        {
            int num     = 77216;
            var encoder = EncoderFactory.LoadEncoder("int24", num);

            Assert.IsType <Int32Encoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.Equal(32, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "int24");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data, hexPrefix: false);

            Assert.Equal("0000000000000000000000000000000000000000000000000000000000012da0", result);
        }
Example #9
0
        public void Int56()
        {
            var num     = (long)-11118;
            var encoder = EncoderFactory.LoadEncoder("int56", num);

            Assert.IsType <Int64Encoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.Equal(32, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "int56");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data, hexPrefix: false);

            Assert.Equal("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd492", result);
        }
Example #10
0
        public void Address()
        {
            Address myAddr  = "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe";
            var     encoder = EncoderFactory.LoadEncoder("address", myAddr);

            Assert.IsType <AddressEncoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.Equal(32, encodedSize);
            Span <byte> data   = new byte[encodedSize];
            var         buffer = new AbiEncodeBuffer(data, "address");

            encoder.Encode(ref buffer);
            Assert.Equal(0, buffer.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data, hexPrefix: false);

            Assert.Equal("00000000000000000000000011f4d0a3c12e86b4b5f39b213f7e19d048276dae", result);
        }
Example #11
0
        public void Int256_2()
        {
            BigInteger num     = 4294923588;
            var        encoder = EncoderFactory.LoadEncoder("int256", num);

            Assert.IsType <Int256Encoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.Equal(32, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "int256");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data, hexPrefix: false);

            Assert.Equal("00000000000000000000000000000000000000000000000000000000ffff5544", result);
        }
Example #12
0
        public void DynamicBoolArray()
        {
            IEnumerable <bool> arr = new[] { true, true, false, true, };
            var encoder            = EncoderFactory.LoadEncoder("bool[]", arr, EncoderFactory.LoadEncoder("bool", default(bool)));

            Assert.IsType <DynamicArrayEncoder <bool> >(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(192, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "bool[]");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", result);
        }
Example #13
0
        public void Int64FixedArray()
        {
            long[] bytes   = new long[] { 1, 4546, long.MaxValue, 0, long.MaxValue };
            var    encoder = EncoderFactory.LoadEncoder("int64[5]", bytes, EncoderFactory.LoadEncoder("int64", default(long)));

            Assert.IsType <FixedArrayEncoder <long> >(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(160, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "int64[5]");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000011c20000000000000000000000000000000000000000000000007fffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffff", result);
        }
Example #14
0
        public void UInt8FixedArray()
        {
            byte[] bytes   = HexUtil.HexToBytes("072696e746");
            var    encoder = EncoderFactory.LoadEncoder("uint8[5]", bytes, EncoderFactory.LoadEncoder("uint8", default(byte)));

            Assert.IsType <FixedArrayEncoder <byte> >(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(160, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "uint8[5]");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000e70000000000000000000000000000000000000000000000000000000000000046", result);
        }
Example #15
0
        public void Bytes_M()
        {
            byte[] bytes   = HexUtil.HexToBytes("072696e74657220746f6f6b20612067616c6c6579206");
            var    encoder = EncoderFactory.LoadEncoder("bytes22", bytes);

            Assert.IsType <BytesMEncoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(32, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "bytes22");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("072696e74657220746f6f6b20612067616c6c657920600000000000000000000", result);
        }
Example #16
0
        public void Bytes()
        {
            byte[] bytes   = HexUtil.HexToBytes("207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970");
            var    encoder = EncoderFactory.LoadEncoder("bytes", bytes);

            Assert.IsType <BytesEncoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(128, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "bytes");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003d207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970000000", result);
        }
Example #17
0
        public void StringUnicode()
        {
            var str     = "utf8; 4 bytes: 𠾴; 3 bytes: ⏰ works!";
            var encoder = EncoderFactory.LoadEncoder("string", str);

            Assert.IsType <StringEncoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(128, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "string");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028757466383b20342062797465733a20f0a0beb43b20332062797465733a20e28fb020776f726b7321000000000000000000000000000000000000000000000000", result);
        }
Example #18
0
        public void String()
        {
            var str     = "Hello, world!";
            var encoder = EncoderFactory.LoadEncoder("string", str);

            Assert.IsType <StringEncoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(96, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "string");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000", result);
        }
Example #19
0
        public void Boolean_False()
        {
            bool boolean = false;
            var  encoder = EncoderFactory.LoadEncoder("bool", boolean);

            Assert.IsType <BoolEncoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(32, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "bool");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("0000000000000000000000000000000000000000000000000000000000000000", result);
        }
Example #20
0
        public void LargeString()
        {
            var str     = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.";
            var encoder = EncoderFactory.LoadEncoder("string", str);

            Assert.IsType <StringEncoder>(encoder);
            var encodedSize = encoder.GetEncodedSize();

            Assert.True(encodedSize % 32 == 0);
            Assert.Equal(320, encodedSize);
            Span <byte> data = new byte[encodedSize];
            var         buff = new AbiEncodeBuffer(data, "string");

            encoder.Encode(ref buff);
            Assert.Equal(0, buff.HeadCursor.Length);
            var result = HexUtil.GetHexFromBytes(data);

            Assert.Equal("000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f54c6f72656d20497073756d2069732073696d706c792064756d6d792074657874206f6620746865207072696e74696e6720616e64207479706573657474696e6720696e6475737472792e204c6f72656d20497073756d20686173206265656e2074686520696e6475737472792773207374616e646172642064756d6d79207465787420657665722073696e6365207468652031353030732c207768656e20616e20756e6b6e6f776e207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970652073706563696d656e20626f6f6b2e0000000000000000000000", result);
        }
Example #21
0
        void GeneratedContractSourceFiles(
            ContractInfo[] contractInfos,
            List <GeneratedEventMetadata> generatedEvents)
        {
            int skippedAlreadyUpdated = 0;

            foreach (var contractInfo in contractInfos)
            {
                var(solFile, contractName, contract, hash, bytecode) = contractInfo;
                var hashHex          = HexUtil.GetHexFromBytes(hash);
                var hashHexBytes     = Encoding.ASCII.GetBytes(hashHex);
                var contactEventInfo = GeneratedEventMetadata.Parse(contractName, _namespace, contract).ToList();
                generatedEvents.AddRange(contactEventInfo);

                var outputFilePath = Path.Combine(_generatedContractsDirectory, contractName + G_CS_FILE_EXT);
                if (!_returnFullSources && FileStartsWithHash(outputFilePath, hashHexBytes))
                {
                    skippedAlreadyUpdated++;
                    continue;
                }

                var generator = new ContractGenerator(contractInfo, _solSourceDirectory, _namespace, contactEventInfo);
                var(generatedContractCode, syntaxTree) = generator.GenerateSourceCode();
                using (var fs = new StreamWriter(outputFilePath, append: false, encoding: StringUtil.UTF8))
                {
                    _logger("Writing source file: " + outputFilePath);
                    fs.WriteLine("//" + hashHex);
                    fs.WriteLine(generatedContractCode);

                    var generatedCSharpEntry = new SolCodeGenCSharpResult(outputFilePath, generatedContractCode, syntaxTree);
                    _genResults.GeneratedCSharpEntries.Add(generatedCSharpEntry);
                }
            }

            if (skippedAlreadyUpdated > 0)
            {
                _logger($"Detected already up-to-date generated files: {skippedAlreadyUpdated} contracts");
            }
        }
Example #22
0
        protected override void EndProcessing()
        {
            if (GlobalVariables.AccountKeys == null || GlobalVariables.AccountKeys.Length == 0)
            {
                Host.UI.WriteErrorLine($"No accounts are loaded. Use '{CmdLetExtensions.GetCmdletName<NewAccountsCommand>()}' to generate accounts.");
                return;
            }

            string filePath;

            if (Path.IsPathRooted(FilePath))
            {
                filePath = Path.GetFullPath(FilePath);
            }
            else
            {
                filePath = Path.GetFullPath(Path.Join(SessionState.Path.CurrentLocation.Path, FilePath));
            }

            if (EncryptData && string.IsNullOrWhiteSpace(Password))
            {
                Host.UI.WriteErrorLine($"No '{nameof(Password)}' parameter is provided. To write without encryption set the '{nameof(EncryptData)}' parameter to false");
                return;
            }

            if (!string.IsNullOrWhiteSpace(Password) && !EncryptData)
            {
                Host.UI.WriteErrorLine($"The '{nameof(EncryptData)}' parameter is set to false but the '{nameof(Password)}' parameter is provided. Pick one.");
                return;
            }

            var accounts = GlobalVariables.AccountKeys;

            var accountArrayHex = accounts
                                  .Select(a => new[]
            {
                a.Address.ToString(hexPrefix: true),
                HexUtil.GetHexFromBytes(a.Account.ToPrivateKeyArray(), hexPrefix: true)
            })
                                  .ToArray();

            JObject dataObj = new JObject();

            if (EncryptData)
            {
                var accountJson            = JsonConvert.SerializeObject(accountArrayHex, Formatting.Indented);
                var encrypedAccountsString = AesUtil.EncryptString(accountJson, Password);
                dataObj[LocalAccountsUtil.JSON_ENCRYPTED_ACCOUNTS_KEY] = encrypedAccountsString;
            }
            else
            {
                dataObj[LocalAccountsUtil.JSON_ACCOUNTS_KEY] = JArray.FromObject(accountArrayHex);
            }

            if (File.Exists(filePath))
            {
                var choices = new Collection <ChoiceDescription>(new[]
                {
                    new ChoiceDescription("Cancel"),
                    new ChoiceDescription("Overwrite")
                });
                var overwrite = Host.UI.PromptForChoice($"File already exists at {filePath}", "Continue and overwite existing file?", choices, 0);
                if (overwrite != 1)
                {
                    Host.UI.WriteErrorLine("Accounts not saved to file.");
                    return;
                }
            }

            var dataJson = dataObj.ToString(Formatting.Indented);

            File.WriteAllText(filePath, dataJson);

            if (EncryptData)
            {
                Host.UI.WriteLine($"Wrote {accounts.Length} encrypted accounts to: {filePath}");
            }
            else
            {
                Host.UI.WriteLine($"Wrote {accounts.Length} unencrypted accounts to: {filePath}");
            }
        }
Example #23
0
        public static AppOptions ParseProcessArgs(string[] args)
        {
            var opts = new AppOptions();

            // Parse process arguments.
            var processArgs = ProcessArgs.Parse(args);

            opts.EntryContractName         = null;
            opts.EntryContractFunctionName = null;
            if (!string.IsNullOrWhiteSpace(processArgs.Entry))
            {
                var entryParts = processArgs.Entry.Split('.', 2, StringSplitOptions.RemoveEmptyEntries);
                opts.EntryContractName = entryParts[0];
                if (entryParts.Length > 1)
                {
                    opts.EntryContractFunctionName = entryParts[1];
                }
            }

            string workspaceDir;

            if (!string.IsNullOrEmpty(processArgs.Directory))
            {
                workspaceDir = processArgs.Directory.Replace('\\', '/');
            }
            else if (!string.IsNullOrEmpty(processArgs.SingleFile))
            {
                // If workspace is not provided, derive a determistic temp directory for the single file.
                workspaceDir = Path.Combine(Path.GetTempPath(), HexUtil.GetHexFromBytes(SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(processArgs.SingleFile))));
                Directory.CreateDirectory(workspaceDir);
                workspaceDir = workspaceDir.Replace('\\', '/');
            }
            else
            {
                throw new Exception("A directory or single file for debugging must be specified.");
            }

            string outputDir = workspaceDir + "/" + GENERATED_DATA_DIR;

            opts.SourceOutputDir = outputDir + "/src";
            opts.BuildOutputDir  = outputDir + "/build";

            opts.SolCompilationSourcePath = workspaceDir;

            if (!string.IsNullOrEmpty(processArgs.SingleFile))
            {
                // Normalize file path.
                opts.SingleFile = processArgs.SingleFile.Replace('\\', '/');

                // Check if provided file is inside the workspace directory.
                if (opts.SingleFile.StartsWith(workspaceDir, StringComparison.OrdinalIgnoreCase))
                {
                    opts.SingleFile = opts.SingleFile.Substring(workspaceDir.Length).Trim('/');
                }
                else
                {
                    // File is outside of workspace so setup special pathing.
                    opts.SolCompilationSourcePath = opts.SingleFile;
                }
            }

            return(opts);
        }
Example #24
0
        void GenerateSources()
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            string[] solFiles;
            if (!string.IsNullOrEmpty(_solSourceSingleFile))
            {
                solFiles = new[] { _solSourceSingleFile };
            }
            else
            {
                solFiles = GetSolContractFiles(_solSourceDirectory);
            }

            var outputFlags = new[]
            {
                OutputType.Abi,
                OutputType.EvmBytecodeObject,
                OutputType.EvmBytecodeOpcodes,
                OutputType.EvmBytecodeSourceMap,
                OutputType.EvmDeployedBytecodeObject,
                OutputType.EvmDeployedBytecodeOpcodes,
                OutputType.EvmDeployedBytecodeSourceMap,
                OutputType.DevDoc,
                OutputType.UserDoc,
                OutputType.Metadata,
                OutputType.Ast
            };

            var solcOptimizerSettings = new Optimizer();

            if (_solcOptimzer > 0)
            {
                solcOptimizerSettings.Enabled = true;
                solcOptimizerSettings.Runs    = _solcOptimzer;
            }

            _logger("Compiling solidity files in " + _solSourceDirectory);
            var soliditySourceContent = new Dictionary <string, string>();
            var solcOutput            = _solcLib.Compile(solFiles, outputFlags, solcOptimizerSettings, soliditySourceFileContent: soliditySourceContent);

            sw.Stop();
            _logger($"Compiling solidity completed in {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");

            #region Generated hashes for solidity sources
            sw.Restart();

            // Calculate a deterministic hash of the solidity source code base, including file paths and the Meadow assembly version.
            var codeBaseHash = KeccakHash.FromString(string.Join('|', soliditySourceContent
                                                                 .OrderBy(k => k.Key)
                                                                 .SelectMany(k => new[] { k.Key, k.Value })
                                                                 .Concat(new[] { _assemblyVersion })));

            _genResults.SolcCodeBaseHash = HexUtil.GetHexFromBytes(codeBaseHash);

            var            flattenedContracts = solcOutput.ContractsFlattened.OrderBy(c => c.SolFile).ToArray();
            ContractInfo[] contractInfos      = new ContractInfo[solcOutput.ContractsFlattened.Length];

            for (var i = 0; i < contractInfos.Length; i++)
            {
                var c = flattenedContracts[i];

                // Check if any previous contracts have the same name as this one.
                int dupNames = 0;
                for (var f = 0; f < i; f++)
                {
                    if (flattenedContracts[f].ContractName == c.ContractName)
                    {
                        dupNames++;
                    }
                }

                string generatedContractName = c.ContractName;

                // If there are duplicate contract names, prepend a unique amount of underscore suffixes.
                if (dupNames > 0)
                {
                    generatedContractName += new string(Enumerable.Repeat('_', dupNames).ToArray());
                }

                contractInfos[i] = new ContractInfo(
                    Util.GetRelativeFilePath(_solSourceDirectory, c.SolFile),
                    generatedContractName,
                    c.Contract,
                    GetSourceHashesXor(c.Contract),
                    c.Contract.Evm.Bytecode.Object);
            }



            _logger($"Generated sol source file hashes in {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");
            sw.Stop();
            #endregion


            _logger("Writing generated output to directory: " + _generatedContractsDirectory);

            #region Output directory cleanup
            if (!Directory.Exists(_generatedContractsDirectory))
            {
                _logger("Creating directory: " + _generatedContractsDirectory);
                Directory.CreateDirectory(_generatedContractsDirectory);
            }
            else
            {
                var expectedFiles = contractInfos
                                    .Select(c => c.ContractName)
                                    .Concat(new[] { EventHelperFile, SolcOutputDataHelperFile })
                                    .Select(c => NormalizePath($"{_generatedContractsDirectory}/{c}{G_CS_FILE_EXT}"))
                                    .ToArray();

                var existingFiles = Directory
                                    .GetFiles(_generatedContractsDirectory, $"*{G_CS_FILE_EXT}", SearchOption.TopDirectoryOnly)
                                    .Where(f => f.EndsWith(".sol.cs", StringComparison.Ordinal) || f.EndsWith(".sol.resx", StringComparison.Ordinal))
                                    .Select(f => NormalizePath(f))
                                    .ToArray();

                // Delete existing files with no corresponding file that can be generated
                foreach (var existingFile in existingFiles)
                {
                    bool found = false;
                    foreach (var expected in expectedFiles)
                    {
                        if (expected.Equals(existingFile, StringComparison.InvariantCultureIgnoreCase))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        _logger("Deleting outdated file: " + existingFile);
                        File.Delete(existingFile);
                    }
                }
            }
            #endregion

            #region AST output generation
            sw.Restart();
            GenerateSolcOutputDataFiles(solcOutput, soliditySourceContent, codeBaseHash);
            sw.Stop();
            _logger($"Resx file for solc output generation took: {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");
            #endregion


            #region
            sw.Restart();
            var generatedEvents = new List <GeneratedEventMetadata>();
            GeneratedContractSourceFiles(contractInfos, generatedEvents);
            GenerateEventHelper(generatedEvents);
            sw.Stop();
            _logger($"Contract and event source code generation took: {Math.Round(sw.Elapsed.TotalSeconds, 2)} seconds");
            #endregion
        }