diff --git a/src/Neo.SmartContract.Testing/Attributes/FieldOrderAttribute.cs b/src/Neo.SmartContract.Testing/Attributes/FieldOrderAttribute.cs
new file mode 100644
index 000000000..7935ef7fc
--- /dev/null
+++ b/src/Neo.SmartContract.Testing/Attributes/FieldOrderAttribute.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Neo.SmartContract.Testing.Attributes;
+
+[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
+public sealed class FieldOrderAttribute : Attribute
+{
+ ///
+ /// Gets the deserialization order of the property.
+ ///
+ public int Order { get; }
+
+ ///
+ /// Constructor
+ ///
+ /// Order
+ public FieldOrderAttribute(int order)
+ {
+ Order = order;
+ }
+}
diff --git a/src/Neo.SmartContract.Testing/Extensions/TestExtensions.cs b/src/Neo.SmartContract.Testing/Extensions/TestExtensions.cs
index 427c4ff8c..b09127c5c 100644
--- a/src/Neo.SmartContract.Testing/Extensions/TestExtensions.cs
+++ b/src/Neo.SmartContract.Testing/Extensions/TestExtensions.cs
@@ -1,5 +1,6 @@
+using Akka.Util;
using Neo.Cryptography.ECC;
-using Neo.SmartContract.Iterators;
+using Neo.SmartContract.Testing.Attributes;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
@@ -11,6 +12,9 @@ namespace Neo.SmartContract.Testing.Extensions
{
public static class TestExtensions
{
+ private static readonly Dictionary> _propertyCache = new();
+ private static readonly Dictionary _fieldCache = new();
+
///
/// Convert Array stack item to dotnet array
///
@@ -75,18 +79,84 @@ public static class TestExtensions
_ when type == typeof(UInt160) => new UInt160(stackItem.GetSpan().ToArray()),
_ when type == typeof(UInt256) => new UInt256(stackItem.GetSpan().ToArray()),
_ when type == typeof(ECPoint) => ECPoint.FromBytes(stackItem.GetSpan().ToArray(), ECCurve.Secp256r1),
- _ when type == typeof(IDictionary