diff --git a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs index 357fb9094a..1533abb887 100644 --- a/src/Neo/SmartContract/ApplicationEngine.Runtime.cs +++ b/src/Neo/SmartContract/ApplicationEngine.Runtime.cs @@ -35,6 +35,11 @@ partial class ApplicationEngine /// public const int MaxNotificationSize = 1024; + /// + /// The maximum number of notifications per application execution. + /// + public const int MaxNotificationCount = 512; + private uint random_times = 0; /// @@ -393,9 +398,16 @@ protected internal void RuntimeNotifyV1(byte[] eventName, Array state) /// The arguments of the event. protected internal void SendNotification(UInt160 hash, string eventName, Array state) { + notifications ??= new List(); + // Restrict the number of notifications for Application executions. Do not check + // persisting triggers to avoid native persist failure. Do not check verification + // trigger since verification context is loaded with ReadOnly flag. + if (IsHardforkEnabled(Hardfork.HF_Echidna) && Trigger == TriggerType.Application && notifications.Count >= MaxNotificationCount) + { + throw new InvalidOperationException($"Maximum number of notifications `{MaxNotificationCount}` is reached."); + } NotifyEventArgs notification = new(ScriptContainer, hash, eventName, (Array)state.DeepCopy(asImmutable: true)); Notify?.Invoke(this, notification); - notifications ??= new List(); notifications.Add(notification); CurrentContext.GetState().NotificationCount++; }