{"id":397747,"date":"2024-06-29T13:39:07","date_gmt":"2024-06-29T13:39:07","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=397747"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=397747","title":{"rendered":"<span>BTCPay Server: \u0442\u043e\u043f-10 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u043a\u043e\u0434\u0435 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f Bitcoin<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0430\u0448\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u043f\u0438\u0448\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043d\u0430 \u0442\u0435\u043c\u0443 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043a\u043e\u0434\u0430. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u0443\u0434\u0438\u0442\u0430 \u043a\u043e\u0434\u0430, \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0438\u0437\u043a\u0438 \u0432\u0441\u0435\u043c \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f\u043c, \u043d\u043e \u0432\u0441\u0435 \u0438\u0437 \u0432\u0430\u0441 \u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u041c\u043e\u0436\u0435\u0442, \u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u044d\u0442\u0438\u043c, \u043d\u043e \u0441\u0442\u0430\u0442\u044c\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0444\u0435\u0440\u0435 \u0431\u0435\u0437 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0435\u0441\u0451\u0442 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0438\u0441\u043a\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c8d\/430\/e6e\/c8d430e6ef45d71ad682861dafcbadb0.png\" width=\"1600\" height=\"902\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c8d\/430\/e6e\/c8d430e6ef45d71ad682861dafcbadb0.png\"\/><\/figure>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p><a href=\"https:\/\/btcpayserver.org\/\">BTCPay Server<\/a> \u2014 \u044d\u0442\u043e \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0431\u0438\u0442\u043a\u043e\u0439\u043d-\u043f\u043b\u0430\u0442\u0435\u0436\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0431\u0438\u0442\u043a\u043e\u0439\u043d\u044b \u0431\u0435\u0437 \u043a\u043e\u043c\u0438\u0441\u0441\u0438\u0439 \u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u043e\u0432.<\/p>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043d\u0430 <a href=\"https:\/\/github.com\/btcpayserver\">GitHub<\/a>.<\/p>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430 <a href=\"https:\/\/pvs-studio.ru\/ru\/pvs-studio\/\">PVS-Studio<\/a>, \u0442. \u043a. \u043e\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 C# \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 Visual Studio. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 IDE \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0430\u043d\u0430\u043b\u0438\u0437 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u044e \u0432\u043e\u0448\u043b\u0438 10 \u0441\u0430\u043c\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u043c\u0438.<\/p>\n<h2>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0430\u043d\u0430\u043b\u0438\u0437\u0430<\/h2>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 1<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3022\/\">V3022<\/a> Expression &#8216;request.PaymentTolerance &lt; 0 &amp;&amp; request.PaymentTolerance &amp;gt; 100&#8217; is always false. Probably the &#8216;||&#8217; operator should be used here. BTCPayServer\\Controllers\\GreenField\\GreenfieldStoresController.cs 241<\/p>\n<pre><code class=\"cs\">private IActionResult Validate(StoreBaseData request) {   ....   if (request.PaymentTolerance &lt; 0 &amp;&amp; request.PaymentTolerance > 100)     ModelState.AddModelError(nameof(request.PaymentTolerance),       \"PaymentTolerance can only be between 0 and 100 percent\");   .... }<\/code><\/pre>\n<p>\u0421 \u043e\u0442\u043c\u0435\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043d\u0435\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430 \u0432 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439. \u0418\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u0430\u0447\u043d\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u044e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u043a\u043e\u0434\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0435\u0441\u0442\u044c \u0433\u043b\u0443\u043f\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430.<\/p>\n<p>\u0422\u0430\u043a, \u0432 \u044d\u0442\u043e\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0435 \u043a\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u043f\u0443\u0442\u0430\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b &#8216;&amp;&amp;&#8217; \u0438 &#8216;||&#8217;. \u041a\u043e\u0434 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 0 \u0434\u043e 100, \u043d\u043e \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0434\u0430\u043d\u043e.<\/p>\n<p>\u041a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043d\u0435\u0432\u0435\u0440\u043d\u043e \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0439\u0434\u0451\u0442 \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e \u043a\u043e\u0434\u0443 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043e\u0448\u0438\u0431\u043a\u0435 \u0432 \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 2<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3001\/\">V3001<\/a> There are identical sub-expressions &#8216;e.Name == InvoiceEvent.FailedToConfirm&#8217; to the left and to the right of the &#8216;||&#8217; operator. BTCPayServer\\HostedServices\\BitpayIPNSender.cs 264<\/p>\n<pre><code class=\"cs\">public Task StartAsync(CancellationToken cancellationToken) {   ....   if (invoice.FullNotifications)   {     if (e.Name == InvoiceEvent.Expired ||         e.Name == InvoiceEvent.PaidInFull ||         e.Name == InvoiceEvent.FailedToConfirm || \/\/ &lt;=         e.Name == InvoiceEvent.MarkedInvalid ||         e.Name == InvoiceEvent.MarkedCompleted ||         e.Name == InvoiceEvent.FailedToConfirm || \/\/ &lt;=         e.Name == InvoiceEvent.Completed ||         e.Name == InvoiceEvent.ExpiredPaidPartial     )     {       await Notify(invoice, e, false, sendMail);       sendMail = false;     }   }    if (e.Name == InvoiceEvent.Confirmed)   {     await Notify(invoice, e, false, sendMail);     sendMail = false;   }   .... }<\/code><\/pre>\n<p>\u041e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0441\u0432\u0438\u0434\u0435\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443\u044e\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430 \u043f\u0438\u0441\u0430\u043b\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c copy-paste. \u041a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u0432\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b. <\/p>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u0432\u0435 \u0442\u0440\u0430\u043a\u0442\u043e\u0432\u043a\u0438 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u043b\u0438\u0448\u043d\u044f\u044f, \u043d\u0430\u0434\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0431\u044b\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443.<\/p>\n<\/li>\n<\/ol>\n<p>\u042f \u043f\u043e\u043b\u0430\u0433\u0430\u044e, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u043e\u0439.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0432\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b:<\/p>\n<pre><code class=\"cs\">public class InvoiceEvent : IHasInvoiceId {   public const string Created = \"invoice_created\";   public const string ReceivedPayment = \"invoice_receivedPayment\";   public const string PaymentSettled = \"invoice_paymentSettled\";   public const string MarkedCompleted = \"invoice_markedComplete\";   public const string MarkedInvalid = \"invoice_markedInvalid\";   public const string Expired = \"invoice_expired\";   public const string ExpiredPaidPartial = \"invoice_expiredPaidPartial\";   public const string PaidInFull = \"invoice_paidInFull\";   public const string PaidAfterExpiration = \"invoice_paidAfterExpiration\";   public const string FailedToConfirm = \"invoice_failedToConfirm\";   public const string Confirmed = \"invoice_confirmed\";   public const string Completed = \"invoice_completed\";   .... }<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 3 \u0433\u0440\u0443\u043f\u043f\u044b:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043e\u043f\u0438\u0439 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043e\u0439 <em>PaidAfterExpiration<\/em>, \u0442. \u043a. \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439\u0441\u044f \u043a\u043e\u0434 \u0438 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430 \u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u0440\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 3<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3061\/\">V3061<\/a> Parameter &#8216;storeId&#8217; is always rewritten in method body before being used. BTCPayServer\\Controllers\\UIStoresController.cs 890<\/p>\n<pre><code class=\"cs\">[HttpPost(\"{storeId}\/tokens\/create\")] public async Task&lt;IActionResult> CreateToken(string storeId, ....) {   if (!ModelState.IsValid)   {     return View(nameof(CreateToken), model);   }   model.Label = model.Label ?? String.Empty;   var userId = GetUserId();   if (userId == null)     return Challenge(AuthenticationSchemes.Cookie);   storeId = model.StoreId; \/\/ &lt;=   .... }<\/code><\/pre>\n<p>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <em>storeId<\/em> \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u044d\u0442\u043e \u0441\u0432\u0438\u0434\u0435\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u0442. \u043a. \u043a\u043e\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0443\u0436\u0435 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0435\u0451 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 4<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3095\/\">V3095<\/a> The &#8216;request&#8217; object was used before it was verified against null. Check lines: 355, 364. BTCPayServer\\Controllers\\GreenField\\GreenfieldPullPaymentController.cs 355<\/p>\n<pre><code class=\"cs\">public async Task&lt;IActionResult> CreatePayoutThroughStore(   string storeId, CreatePayoutThroughStoreRequest request) {   if (request.Approved is true)   {     if (!(await _authorizationService.AuthorizeAsync(....)).Succeeded)     {       return this.CreateAPIPermissionError(....);     }   }    if (request is null ||     !PaymentMethodId.TryParse(request?.PaymentMethod, ....))   {     ModelState.AddModelError(nameof(request.PaymentMethod),       \"Invalid payment method\");     return this.CreateValidationError(ModelState);   }   .... }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <em>request<\/em> \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0431\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a, \u0430 \u043f\u043e\u0442\u043e\u043c \u0441 \u043d\u0438\u043c\u0438. \u0421 \u044d\u0442\u0438\u043c \u043a\u043e\u0434\u043e\u043c \u0442\u043e\u0447\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u043d\u0435 \u0442\u0430\u043a.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 5<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3008\/\">V3008<\/a> The &#8216;model.StoreName&#8217; variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 166, 165. BTCPayServer\\Controllers\\GreenField\\GreenfieldStoresController.cs 166<\/p>\n<pre><code class=\"cs\">private void ToModel(StoreBaseData restModel, StoreData model, ....) {   var blob = model.GetStoreBlob();   model.StoreName = restModel.Name;   model.StoreName = restModel.Name;   model.StoreWebsite = restModel.Website;   model.SpeedPolicy = restModel.SpeedPolicy;   model.SetDefaultPaymentId(defaultPaymentMethod);   .... }<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b \u0434\u0432\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f. \u041a\u0430\u043a \u0438 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u043e\u043c\u0435\u0440 2, \u0442\u0443\u0442 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 copy-paste \u0441\u0442\u0438\u043b\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 6<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3029\/\">V3029<\/a> The conditional expressions of the &#8216;if&#8217; statements situated alongside each other are identical. Check lines: 59, 64. BTCPayServer\\Hosting\\BTCpayMiddleware.cs 59<\/p>\n<pre><code class=\"cs\">public async Task Invoke(HttpContext httpContext) {   CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;   CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;   try   {     var bitpayAuth = GetBitpayAuth(httpContext, out bool isBitpayAuth);     var isBitpayAPI = IsBitpayAPI(httpContext, isBitpayAuth);     if (isBitpayAPI &amp;&amp; httpContext.Request.Method == \"OPTIONS\")     {       httpContext.Response.StatusCode = 200;       httpContext.Response.SetHeader(\"Access-Control-Allow-Origin\", \"*\");       if (httpContext.Request.Headers.ContainsKey(\"....\"))       {         httpContext.Response.SetHeader(\"Access-Control-Allow-Headers\",         httpContext.Request.Headers[\"....\"].FirstOrDefault());       }       return; \/\/ We bypass MVC completely     }     httpContext.SetIsBitpayAPI(isBitpayAPI);     if (isBitpayAPI) \/\/ &lt;=     {       httpContext.Response.SetHeader(\"Access-Control-Allow-Origin\", \"*\");       httpContext.SetBitpayAuth(bitpayAuth);     }     if (isBitpayAPI) \/\/ &lt;=     {       await _Next(httpContext);       return;     }     ....   }   .... }<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <em>isBitpayAPI<\/em> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u043f\u043e\u0434\u0440\u044f\u0434. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f, \u0430 \u0431\u043b\u043e\u043a\u0438 \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0431\u043b\u043e\u043a\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u043d\u0430\u0434\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">isBitpayAPI = IsBitpayAPI(httpContext, isBitpayAuth);<\/code><\/pre>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 7<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3125\/\">V3125<\/a> The &#8216;request&#8217; object was used after it was verified against null. Check lines: 136, 130. BTCPayServer\\Controllers\\GreenField\\GreenfieldLightningNodeApiController.cs 136<\/p>\n<pre><code class=\"cs\">public virtual async Task&lt;IActionResult> OpenChannel(....) {   var lightningClient = await GetLightningClient(cryptoCode, true);   if (request?.NodeURI is null)   {     ModelState.AddModelError(nameof(request.NodeURI),       \"A valid node info was not provided to open a channel with\");   }    if (request.ChannelAmount == null)   {     ModelState.AddModelError(nameof(request.ChannelAmount), \"....\");   }   .... }<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440 4: \u0442\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <em>request<\/em> \u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0441\u0442\u044c, \u0442\u043e \u043d\u0435\u0442. \u041d\u043e \u0442\u0443\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440.<\/p>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u0443\u0447\u0430\u0441\u0442\u043a\u0438 \u043a\u043e\u0434\u0430, \u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"cs\">if (!ModelState.IsValid) {   return this.CreateValidationError(ModelState); }<\/code><\/pre>\n<p>\u0422. \u0435. \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0430 \u0432 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0437\u0430\u0431\u044b\u043b\u0438 \u0435\u0451 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 8<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3168\/\">V3168<\/a> Awaiting on expression with potential null value can lead to NullReferenceException. BTCPayServer\\HostedServices\\InvoiceWatcher.cs 383<\/p>\n<pre><code class=\"cs\">private async Task&lt;bool> UpdateConfirmationCount(InvoiceEntity invoice) {   ....   var transactionResult = await _explorerClientProvider.GetExplorerClient(     payment.GetCryptoCode())?.GetTransactionAsync(....);   .... }<\/code><\/pre>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 &#8216;?.&#8217;, \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u0432\u043e\u0437\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <em>null<\/em>. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <em>await null<\/em> \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e <em>NullReferenceException<\/em>. <\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 9<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3022\/\">V3022<\/a> Expression &#8216;items == null&#8217; is always false. BTCPayServer\\Services\\Invoices\\InvoiceRepository.cs 427<\/p>\n<pre><code class=\"cs\">public async Task MassArchive(string[] invoiceIds, bool archive = true) {   using var context = _applicationDbContextFactory.CreateContext();   var items = context.Invoices.Where(a => invoiceIds.Contains(a.Id));   if (items == null)   {     return;   }    foreach (InvoiceData invoice in items)   {     invoice.Archived = archive;   }    await context.SaveChangesAsync(); }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <em>Where<\/em> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0435 <em>null<\/em>, \u0430 \u043f\u0443\u0441\u0442\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u0432 \u043d\u0435\u0439 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0425\u043e\u0442\u044f \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u0435\u0442\u043e\u0434 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0439, \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u043c\u0435\u0442\u043e\u0434\u0443:<\/p>\n<pre><code class=\"cs\">public static IQueryable&lt;TEntity> Where&lt;TEntity>(....) where TEntity : class {   return System.Linq.Queryable.Where(obj, predicate); }<\/code><\/pre>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u0430\u0432\u0442\u043e\u0440 \u043a\u043e\u0434\u0430 \u0445\u043e\u0442\u0435\u043b \u043d\u0435 \u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043f\u0443\u0441\u0442\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u043d\u043e \u0438\u0437-\u0437\u0430 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 10<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3108\/\">V3108<\/a> It is not recommended to return &#8216;null&#8217; from &#8216;ToString()&#8217; method. BTCPayServer\\Controllers\\UILNURLController.cs 364<\/p>\n<pre><code class=\"cs\">public class LightningAddressSettings {   ....   public override string ToString()   {     return null;   }   .... }<\/code><\/pre>\n<p>\u041c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043e\u0448\u0438\u0431\u043a\u0430, \u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <em>null<\/em> \u0438\u0437 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <em>ToString<\/em> \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0438\u0434\u0435\u044f, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043f\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u043c Microsoft. \u041e\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u0438\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445, \u0438\u043d\u043e\u0433\u0434\u0430 \u0434\u0430\u0436\u0435 \u043d\u0435\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412\u0441\u0435\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u0432\u044b\u0434\u0430\u043b 239 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439, \u0447\u0442\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0422\u0430\u043c \u0435\u0449\u0451 \u0435\u0441\u0442\u044c \u0447\u0442\u043e \u043f\u043e\u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c. \u041d\u043e 10 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439, \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445, \u043c\u043e\u0433\u0443\u0442 \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u0434\u043e\u0432\u0435\u0440\u0438\u0435 \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u043c\u0443 \u0441 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u043b\u043e\u0433\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0432\u043d\u0435\u0434\u0440\u044f\u043b\u0430\u0441\u044c, \u0434\u0430\u0436\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u0411\u0443\u0434\u0435\u043c \u0440\u0430\u0434\u044b, \u0435\u0441\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u044f\u0442 \u043d\u0430\u0448\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043a\u043e\u0434\u0430. \u0413\u043e\u0442\u043e\u0432\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044e.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u0430\u0432\u0442\u043e\u0440\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 BTCPay Server, \u0441\u043a\u0430\u0447\u0430\u0439\u0442\u0435 <a href=\"https:\/\/pvs-studio.ru\/ru\/pvs-studio\/try-free\/?utm_source=website&amp;utm_medium=habr&amp;utm_campaign=article&amp;utm_content=1051\">PVS-Studio<\/a>. \u041e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u043d\u0430\u043b\u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u044f\u0437\u044b\u043a\u043e\u0432, \u043a\u0430\u043a C, C++, C# \u0438 Java.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u0441 \u0430\u043d\u0433\u043b\u043e\u044f\u0437\u044b\u0447\u043d\u043e\u0439 \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u0435\u0439, \u0442\u043e \u043f\u0440\u043e\u0448\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043f\u0435\u0440\u0435\u0432\u043e\u0434: Sviatoslav Razmyslov. <a href=\"https:\/\/pvs-studio.com\/en\/blog\/posts\/csharp\/1051\/\">BTCPay Server: top 10 bugs in Bitcoin payment processor code<\/a>.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/735726\/\"> https:\/\/habr.com\/ru\/articles\/735726\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0430\u0448\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u043f\u0438\u0448\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043d\u0430 \u0442\u0435\u043c\u0443 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043a\u043e\u0434\u0430. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u0443\u0434\u0438\u0442\u0430 \u043a\u043e\u0434\u0430, \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u043b\u0438\u0437\u043a\u0438 \u0432\u0441\u0435\u043c \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f\u043c, \u043d\u043e \u0432\u0441\u0435 \u0438\u0437 \u0432\u0430\u0441 \u0442\u043e\u0447\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u041c\u043e\u0436\u0435\u0442, \u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u044d\u0442\u0438\u043c, \u043d\u043e \u0441\u0442\u0430\u0442\u044c\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u0432 \u044d\u0442\u043e\u0439 \u0441\u0444\u0435\u0440\u0435 \u0431\u0435\u0437 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0435\u0441\u0451\u0442 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0438\u0441\u043a\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p><a href=\"https:\/\/btcpayserver.org\/\">BTCPay Server<\/a> \u2014 \u044d\u0442\u043e \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0431\u0438\u0442\u043a\u043e\u0439\u043d-\u043f\u043b\u0430\u0442\u0435\u0436\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0431\u0438\u0442\u043a\u043e\u0439\u043d\u044b \u0431\u0435\u0437 \u043a\u043e\u043c\u0438\u0441\u0441\u0438\u0439 \u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u043d\u0438\u043a\u043e\u0432.<\/p>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u043d\u0430 <a href=\"https:\/\/github.com\/btcpayserver\">GitHub<\/a>.<\/p>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440\u0430 <a href=\"https:\/\/pvs-studio.ru\/ru\/pvs-studio\/\">PVS-Studio<\/a>, \u0442. \u043a. \u043e\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 C# \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 Visual Studio. \u0414\u043b\u044f \u044d\u0442\u043e\u0439 IDE \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0430\u043d\u0430\u043b\u0438\u0437 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b.<\/p>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u044e \u0432\u043e\u0448\u043b\u0438 10 \u0441\u0430\u043c\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u044b\u043c\u0438.<\/p>\n<h2>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0430\u043d\u0430\u043b\u0438\u0437\u0430<\/h2>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 1<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3022\/\">V3022<\/a> Expression &#8216;request.PaymentTolerance &lt; 0 &amp;&amp; request.PaymentTolerance &amp;gt; 100&#8217; is always false. Probably the &#8216;||&#8217; operator should be used here. BTCPayServer\\Controllers\\GreenField\\GreenfieldStoresController.cs 241<\/p>\n<pre><code class=\"cs\">private IActionResult Validate(StoreBaseData request) {   ....   if (request.PaymentTolerance &lt; 0 &amp;&amp; request.PaymentTolerance > 100)     ModelState.AddModelError(nameof(request.PaymentTolerance),       \"PaymentTolerance can only be between 0 and 100 percent\");   .... }<\/code><\/pre>\n<p>\u0421 \u043e\u0442\u043c\u0435\u043d\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438\u0437-\u0437\u0430 \u043d\u0435\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430 \u0432 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439. \u0418\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u0430\u0447\u043d\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u044e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u043a\u043e\u0434\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0435\u0441\u0442\u044c \u0433\u043b\u0443\u043f\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430.<\/p>\n<p>\u0422\u0430\u043a, \u0432 \u044d\u0442\u043e\u043c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0435 \u043a\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u043f\u0443\u0442\u0430\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b &#8216;&amp;&amp;&#8217; \u0438 &#8216;||&#8217;. \u041a\u043e\u0434 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 0 \u0434\u043e 100, \u043d\u043e \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0434\u0430\u043d\u043e.<\/p>\n<p>\u041a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u043d\u0435\u0432\u0435\u0440\u043d\u043e \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0439\u0434\u0451\u0442 \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e \u043a\u043e\u0434\u0443 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043e\u0448\u0438\u0431\u043a\u0435 \u0432 \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 2<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3001\/\">V3001<\/a> There are identical sub-expressions &#8216;e.Name == InvoiceEvent.FailedToConfirm&#8217; to the left and to the right of the &#8216;||&#8217; operator. BTCPayServer\\HostedServices\\BitpayIPNSender.cs 264<\/p>\n<pre><code class=\"cs\">public Task StartAsync(CancellationToken cancellationToken) {   ....   if (invoice.FullNotifications)   {     if (e.Name == InvoiceEvent.Expired ||         e.Name == InvoiceEvent.PaidInFull ||         e.Name == InvoiceEvent.FailedToConfirm || \/\/ &lt;=         e.Name == InvoiceEvent.MarkedInvalid ||         e.Name == InvoiceEvent.MarkedCompleted ||         e.Name == InvoiceEvent.FailedToConfirm || \/\/ &lt;=         e.Name == InvoiceEvent.Completed ||         e.Name == InvoiceEvent.ExpiredPaidPartial     )     {       await Notify(invoice, e, false, sendMail);       sendMail = false;     }   }    if (e.Name == InvoiceEvent.Confirmed)   {     await Notify(invoice, e, false, sendMail);     sendMail = false;   }   .... }<\/code><\/pre>\n<p>\u041e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f \u0441\u0432\u0438\u0434\u0435\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443\u044e\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430 \u043f\u0438\u0441\u0430\u043b\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c copy-paste. \u041a\u0430\u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u0432\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b. <\/p>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u0432\u0435 \u0442\u0440\u0430\u043a\u0442\u043e\u0432\u043a\u0438 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u043b\u0438\u0448\u043d\u044f\u044f, \u043d\u0430\u0434\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u0431\u044b\u043b\u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443.<\/p>\n<\/li>\n<\/ol>\n<p>\u042f \u043f\u043e\u043b\u0430\u0433\u0430\u044e, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u043e\u0439.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0432\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b:<\/p>\n<pre><code class=\"cs\">public class InvoiceEvent : IHasInvoiceId {   public const string Created = \"invoice_created\";   public const string ReceivedPayment = \"invoice_receivedPayment\";   public const string PaymentSettled = \"invoice_paymentSettled\";   public const string MarkedCompleted = \"invoice_markedComplete\";   public const string MarkedInvalid = \"invoice_markedInvalid\";   public const string Expired = \"invoice_expired\";   public const string ExpiredPaidPartial = \"invoice_expiredPaidPartial\";   public const string PaidInFull = \"invoice_paidInFull\";   public const string PaidAfterExpiration = \"invoice_paidAfterExpiration\";   public const string FailedToConfirm = \"invoice_failedToConfirm\";   public const string Confirmed = \"invoice_confirmed\";   public const string Completed = \"invoice_completed\";   .... }<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 3 \u0433\u0440\u0443\u043f\u043f\u044b:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u043a\u043e\u043f\u0438\u0439 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043e\u0439 <em>PaidAfterExpiration<\/em>, \u0442. \u043a. \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439\u0441\u044f \u043a\u043e\u0434 \u0438 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430 \u043f\u043e\u0445\u043e\u0436\u0438 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u0440\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0442\u0435\u0436\u0435\u0439.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 3<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3061\/\">V3061<\/a> Parameter &#8216;storeId&#8217; is always rewritten in method body before being used. BTCPayServer\\Controllers\\UIStoresController.cs 890<\/p>\n<pre><code class=\"cs\">[HttpPost(\"{storeId}\/tokens\/create\")] public async Task&lt;IActionResult> CreateToken(string storeId, ....) {   if (!ModelState.IsValid)   {     return View(nameof(CreateToken), model);   }   model.Label = model.Label ?? String.Empty;   var userId = GetUserId();   if (userId == null)     return Challenge(AuthenticationSchemes.Cookie);   storeId = model.StoreId; \/\/ &lt;=   .... }<\/code><\/pre>\n<p>\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <em>storeId<\/em> \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u044d\u0442\u043e \u0441\u0432\u0438\u0434\u0435\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u0442. \u043a. \u043a\u043e\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0443\u0436\u0435 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0435\u0451 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 4<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3095\/\">V3095<\/a> The &#8216;request&#8217; object was used before it was verified against null. Check lines: 355, 364. BTCPayServer\\Controllers\\GreenField\\GreenfieldPullPaymentController.cs 355<\/p>\n<pre><code class=\"cs\">public async Task&lt;IActionResult> CreatePayoutThroughStore(   string storeId, CreatePayoutThroughStoreRequest request) {   if (request.Approved is true)   {     if (!(await _authorizationService.AuthorizeAsync(....)).Succeeded)     {       return this.CreateAPIPermissionError(....);     }   }    if (request is null ||     !PaymentMethodId.TryParse(request?.PaymentMethod, ....))   {     ModelState.AddModelError(nameof(request.PaymentMethod),       \"Invalid payment method\");     return this.CreateValidationError(ModelState);   }   .... }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <em>request<\/em> \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0431\u0435\u0437 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a, \u0430 \u043f\u043e\u0442\u043e\u043c \u0441 \u043d\u0438\u043c\u0438. \u0421 \u044d\u0442\u0438\u043c \u043a\u043e\u0434\u043e\u043c \u0442\u043e\u0447\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u043d\u0435 \u0442\u0430\u043a.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 5<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3008\/\">V3008<\/a> The &#8216;model.StoreName&#8217; variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 166, 165. BTCPayServer\\Controllers\\GreenField\\GreenfieldStoresController.cs 166<\/p>\n<pre><code class=\"cs\">private void ToModel(StoreBaseData restModel, StoreData model, ....) {   var blob = model.GetStoreBlob();   model.StoreName = restModel.Name;   model.StoreName = restModel.Name;   model.StoreWebsite = restModel.Website;   model.SpeedPolicy = restModel.SpeedPolicy;   model.SetDefaultPaymentId(defaultPaymentMethod);   .... }<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b \u0434\u0432\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f. \u041a\u0430\u043a \u0438 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u043e\u043c\u0435\u0440 2, \u0442\u0443\u0442 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 copy-paste \u0441\u0442\u0438\u043b\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 6<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3029\/\">V3029<\/a> The conditional expressions of the &#8216;if&#8217; statements situated alongside each other are identical. Check lines: 59, 64. BTCPayServer\\Hosting\\BTCpayMiddleware.cs 59<\/p>\n<pre><code class=\"cs\">public async Task Invoke(HttpContext httpContext) {   CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;   CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;   try   {     var bitpayAuth = GetBitpayAuth(httpContext, out bool isBitpayAuth);     var isBitpayAPI = IsBitpayAPI(httpContext, isBitpayAuth);     if (isBitpayAPI &amp;&amp; httpContext.Request.Method == \"OPTIONS\")     {       httpContext.Response.StatusCode = 200;       httpContext.Response.SetHeader(\"Access-Control-Allow-Origin\", \"*\");       if (httpContext.Request.Headers.ContainsKey(\"....\"))       {         httpContext.Response.SetHeader(\"Access-Control-Allow-Headers\",         httpContext.Request.Headers[\"....\"].FirstOrDefault());       }       return; \/\/ We bypass MVC completely     }     httpContext.SetIsBitpayAPI(isBitpayAPI);     if (isBitpayAPI) \/\/ &lt;=     {       httpContext.Response.SetHeader(\"Access-Control-Allow-Origin\", \"*\");       httpContext.SetBitpayAuth(bitpayAuth);     }     if (isBitpayAPI) \/\/ &lt;=     {       await _Next(httpContext);       return;     }     ....   }   .... }<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <em>isBitpayAPI<\/em> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u043f\u043e\u0434\u0440\u044f\u0434. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f, \u0430 \u0431\u043b\u043e\u043a\u0438 \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u0431\u043b\u043e\u043a\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u043d\u0430\u0434\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">isBitpayAPI = IsBitpayAPI(httpContext, isBitpayAuth);<\/code><\/pre>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 7<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3125\/\">V3125<\/a> The &#8216;request&#8217; object was used after it was verified against null. Check lines: 136, 130. BTCPayServer\\Controllers\\GreenField\\GreenfieldLightningNodeApiController.cs 136<\/p>\n<pre><code class=\"cs\">public virtual async Task&lt;IActionResult> OpenChannel(....) {   var lightningClient = await GetLightningClient(cryptoCode, true);   if (request?.NodeURI is null)   {     ModelState.AddModelError(nameof(request.NodeURI),       \"A valid node info was not provided to open a channel with\");   }    if (request.ChannelAmount == null)   {     ModelState.AddModelError(nameof(request.ChannelAmount), \"....\");   }   .... }<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440 4: \u0442\u043e\u0436\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <em>request<\/em> \u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0441\u0442\u044c, \u0442\u043e \u043d\u0435\u0442. \u041d\u043e \u0442\u0443\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440.<\/p>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u0435 \u0443\u0447\u0430\u0441\u0442\u043a\u0438 \u043a\u043e\u0434\u0430, \u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c\u0438:<\/p>\n<pre><code class=\"cs\">if (!ModelState.IsValid) {   return this.CreateValidationError(ModelState); }<\/code><\/pre>\n<p>\u0422. \u0435. \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043e\u0441\u0432\u0435\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0430 \u0432 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0437\u0430\u0431\u044b\u043b\u0438 \u0435\u0451 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c.<\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 8<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3168\/\">V3168<\/a> Awaiting on expression with potential null value can lead to NullReferenceException. BTCPayServer\\HostedServices\\InvoiceWatcher.cs 383<\/p>\n<pre><code class=\"cs\">private async Task&lt;bool> UpdateConfirmationCount(InvoiceEntity invoice) {   ....   var transactionResult = await _explorerClientProvider.GetExplorerClient(     payment.GetCryptoCode())?.GetTransactionAsync(....);   .... }<\/code><\/pre>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 &#8216;?.&#8217;, \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u0432\u043e\u0437\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <em>null<\/em>. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <em>await null<\/em> \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e <em>NullReferenceException<\/em>. <\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 9<\/h4>\n<p><a href=\"https:\/\/pvs-studio.ru\/ru\/docs\/warnings\/v3022\/\">V3022<\/a> Expression &#8216;items == null&#8217; is always false. BTCPayServer\\Services\\Invoices\\InvoiceRepository.cs 427<\/p>\n<pre><code class=\"cs\">public async Task MassArchive(string[] invoiceIds, bool archive = true) {   using var context = _applicationDbContextFactory.CreateContext();   var items = context.Invoices.Where(a => invoiceIds.Contains(a.Id));   if (items == null)   {     return;   }    foreach (InvoiceData<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-397747","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/397747","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=397747"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/397747\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=397747"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=397747"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=397747"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}