Skip to content

Commit

Permalink
[Compiler] fix object creation (#1184)
Browse files Browse the repository at this point in the history
* fix object creation

* Update tests/Neo.Compiler.CSharp.TestContracts/Contract_PropertyMethod.cs

* remove set property

* Merge branch 'master' into fix-object-creation

# Conflicts:
#	tests/Neo.Compiler.CSharp.TestContracts/Contract_PropertyMethod.cs
#	tests/Neo.Compiler.CSharp.UnitTests/TestingArtifacts/Contract_PropertyMethod.cs
#	tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Property_Method.cs

* Update tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Property_Method.cs

Co-authored-by: Shargon <[email protected]>

---------

Co-authored-by: Shargon <[email protected]>
  • Loading branch information
Jim8y and shargon authored Oct 8, 2024
1 parent 6e49189 commit 17ec6d2
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
using Neo.VM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Neo.Compiler;
Expand Down Expand Up @@ -48,6 +50,76 @@ private void ConvertObjectCreationExpression(SemanticModel model, BaseObjectCrea

private void ConvertObjectCreationExpressionInitializer(SemanticModel model, InitializerExpressionSyntax initializer)
{
// Handle different types of initializer expressions:
//
// ObjectInitializerExpression:
// Example: new Person { Name = "John", Age = 30 }
// Used for initializing properties of an object.
//
// CollectionInitializerExpression:
// Example: new List<int> { 1, 2, 3 }
// Used for initializing collections like lists or sets.
//
// ArrayInitializerExpression:
// Example: new int[] { 1, 2, 3 }
// Used for initializing arrays.
//
// ComplexElementInitializerExpression:
// Example: new Dictionary<string, int> { { "one", 1 }, { "two", 2 } }
// Used for initializing complex elements like dictionary entries.
//
// NullLiteralExpression:
// Example: new Person { Name = null }
// Used when explicitly setting a property to null in an initializer.

if (initializer.IsKind(SyntaxKind.CollectionInitializerExpression))
{
ITypeSymbol type;
if (initializer.Expressions.Count > 0)
{
var firstExpression = initializer.Expressions[0];
var typeInfo = model.GetTypeInfo(firstExpression);
type = typeInfo.Type!;
}
else
{
// Handle empty collection case if necessary
throw new CompilationException(initializer, DiagnosticId.SyntaxNotSupported, "Cannot determine item type from an empty collection initializer.");
}

AddInstruction(OpCode.DROP);
if (type.SpecialType == SpecialType.System_Byte)
{
var values = initializer.Expressions.Select(p => model.GetConstantValue(p)).ToArray();
if (values.Any(p => !p.HasValue))
{
Push(values.Length);
AddInstruction(OpCode.NEWBUFFER);
for (var i = 0; i < initializer.Expressions.Count; i++)
{
AddInstruction(OpCode.DUP);
Push(i);
ConvertExpression(model, initializer.Expressions[i]);
AddInstruction(OpCode.SETITEM);
}
}
else
{
var data = values.Select(p => (byte)System.Convert.ChangeType(p.Value, typeof(byte))!).ToArray();
Push(data);
ChangeType(VM.Types.StackItemType.Buffer);
}
}
else
{
for (var i = initializer.Expressions.Count - 1; i >= 0; i--)
ConvertExpression(model, initializer.Expressions[i]);
Push(initializer.Expressions.Count);
AddInstruction(OpCode.PACK);
}
return;
}

foreach (ExpressionSyntax e in initializer.Expressions)
{
if (e is not AssignmentExpressionSyntax ae)
Expand All @@ -63,9 +135,38 @@ private void ConvertObjectCreationExpressionInitializer(SemanticModel model, Ini
AddInstruction(OpCode.SETITEM);
break;
case IPropertySymbol property:
ConvertExpression(model, ae.Right);
AddInstruction(OpCode.OVER);
CallMethodWithConvention(model, property.SetMethod!, CallingConvention.Cdecl);
// Special handling for Map and List initialization is required due to their unique initialization syntax and behavior.
// Map and List properties are not defined explicitly like regular types

// Examples:
// Map: new Map<string, int> { ["key"] = 42 };
// This is equivalent to: map["key"] = 42;
// Regular: new MyClass { Property = value };
// This uses the standard property setter.
if (property.ContainingType.Name is "Map")
{
// Duplicate the object reference for Map and List
AddInstruction(OpCode.DUP);

if (ae.Left is ImplicitElementAccessSyntax elementAccess)
{
ConvertExpression(model, elementAccess.ArgumentList.Arguments[0].Expression);
}
else
{
ConvertExpression(model, ae.Left);
}
// Convert the value to be assigned (for both Map and List)
ConvertExpression(model, ae.Right);
AddInstruction(OpCode.SETITEM);
}
else
{
// For regular properties:
ConvertExpression(model, ae.Right);
AddInstruction(OpCode.OVER);
CallMethodWithConvention(model, property.SetMethod!, CallingConvention.Cdecl);
}
break;
default:
throw new CompilationException(ae.Left, DiagnosticId.SyntaxNotSupported, $"Unsupported symbol: {symbol}");
Expand Down
30 changes: 30 additions & 0 deletions tests/Neo.Compiler.CSharp.TestContracts/Contract_PropertyMethod.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Neo.SmartContract.Framework;

namespace Neo.Compiler.CSharp.TestContracts;

public class Contract_PropertyMethod : SmartContract.Framework.SmartContract
Expand All @@ -13,6 +15,30 @@ public static void testProperty2()
var p = new Person("NEO3", 10);
}

public static Person testProperty3()
{
return new Person()
{
Name = "NEO3",
};
}

public static Map<string, string> testProperty4()
{
return new Map<string, string>()
{
["Name"] = "NEO3",
};
}

public static List<int> testProperty5()
{
return new List<int>()
{
1, 2, 3, 4, 5
};
}

public static (string, int, string) testPropertyInit()
{
var p = new Person("NEO3", 10) { Address = "123 Blockchain St" };
Expand All @@ -30,5 +56,9 @@ public Person(string name, int age)
Name = name;
Age = age;
}

public Person()
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ public abstract class Contract_NEP11(Neo.SmartContract.Testing.SmartContractInit
{
#region Compiled data

public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_NEP11"",""groups"":[],""features"":{},""supportedstandards"":[""NEP-11""],""abi"":{""methods"":[{""name"":""symbol"",""parameters"":[],""returntype"":""String"",""offset"":0,""safe"":true},{""name"":""decimals"",""parameters"":[],""returntype"":""Integer"",""offset"":7,""safe"":true},{""name"":""totalSupply"",""parameters"":[],""returntype"":""Integer"",""offset"":9,""safe"":true},{""name"":""balanceOf"",""parameters"":[{""name"":""owner"",""type"":""Hash160""}],""returntype"":""Integer"",""offset"":35,""safe"":true},{""name"":""ownerOf"",""parameters"":[{""name"":""tokenId"",""type"":""ByteArray""}],""returntype"":""Hash160"",""offset"":218,""safe"":true},{""name"":""properties"",""parameters"":[{""name"":""tokenId"",""type"":""ByteArray""}],""returntype"":""Map"",""offset"":377,""safe"":true},{""name"":""tokens"",""parameters"":[],""returntype"":""InteropInterface"",""offset"":419,""safe"":true},{""name"":""tokensOf"",""parameters"":[{""name"":""owner"",""type"":""Hash160""}],""returntype"":""InteropInterface"",""offset"":447,""safe"":true},{""name"":""transfer"",""parameters"":[{""name"":""to"",""type"":""Hash160""},{""name"":""tokenId"",""type"":""ByteArray""},{""name"":""data"",""type"":""Any""}],""returntype"":""Boolean"",""offset"":536,""safe"":false},{""name"":""_initialize"",""parameters"":[],""returntype"":""Void"",""offset"":837,""safe"":false}],""events"":[{""name"":""Transfer"",""parameters"":[{""name"":""from"",""type"":""Hash160""},{""name"":""to"",""type"":""Hash160""},{""name"":""amount"",""type"":""Integer""},{""name"":""tokenId"",""type"":""ByteArray""}]}]},""permissions"":[{""contract"":""0x726cb6e0cd8628a1350a611384688911ab75f51b"",""methods"":[""sha256""]},{""contract"":""0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0"",""methods"":[""deserialize"",""serialize""]},{""contract"":""0xfffdc93764dbaddd97c48f252a53ea4643faa3fd"",""methods"":[""getContract""]},{""contract"":""*"",""methods"":[""onNEP11Payment""]}],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");
public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_NEP11"",""groups"":[],""features"":{},""supportedstandards"":[""NEP-11""],""abi"":{""methods"":[{""name"":""symbol"",""parameters"":[],""returntype"":""String"",""offset"":0,""safe"":true},{""name"":""decimals"",""parameters"":[],""returntype"":""Integer"",""offset"":7,""safe"":true},{""name"":""totalSupply"",""parameters"":[],""returntype"":""Integer"",""offset"":9,""safe"":true},{""name"":""balanceOf"",""parameters"":[{""name"":""owner"",""type"":""Hash160""}],""returntype"":""Integer"",""offset"":35,""safe"":true},{""name"":""ownerOf"",""parameters"":[{""name"":""tokenId"",""type"":""ByteArray""}],""returntype"":""Hash160"",""offset"":218,""safe"":true},{""name"":""properties"",""parameters"":[{""name"":""tokenId"",""type"":""ByteArray""}],""returntype"":""Map"",""offset"":377,""safe"":true},{""name"":""tokens"",""parameters"":[],""returntype"":""InteropInterface"",""offset"":424,""safe"":true},{""name"":""tokensOf"",""parameters"":[{""name"":""owner"",""type"":""Hash160""}],""returntype"":""InteropInterface"",""offset"":452,""safe"":true},{""name"":""transfer"",""parameters"":[{""name"":""to"",""type"":""Hash160""},{""name"":""tokenId"",""type"":""ByteArray""},{""name"":""data"",""type"":""Any""}],""returntype"":""Boolean"",""offset"":541,""safe"":false},{""name"":""_initialize"",""parameters"":[],""returntype"":""Void"",""offset"":842,""safe"":false}],""events"":[{""name"":""Transfer"",""parameters"":[{""name"":""from"",""type"":""Hash160""},{""name"":""to"",""type"":""Hash160""},{""name"":""amount"",""type"":""Integer""},{""name"":""tokenId"",""type"":""ByteArray""}]}]},""permissions"":[{""contract"":""0x726cb6e0cd8628a1350a611384688911ab75f51b"",""methods"":[""sha256""]},{""contract"":""0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0"",""methods"":[""deserialize"",""serialize""]},{""contract"":""0xfffdc93764dbaddd97c48f252a53ea4643faa3fd"",""methods"":[""getContract""]},{""contract"":""*"",""methods"":[""onNEP11Payment""]}],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");

/// <summary>
/// Optimization: "All"
/// </summary>
public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATA7znO4OTpJcbCoGp54UQN2G/OrAtkZXNlcmlhbGl6ZQEAAQ/A7znO4OTpJcbCoGp54UQN2G/OrAlzZXJpYWxpemUBAAEP/aP6Q0bqUyolj8SX3a3bZDfJ/f8LZ2V0Q29udHJhY3QBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIGc2hhMjU2AQABDwAA/UgDDARURVNUQBBAWNgmFwwBAEH2tGviQZJd6DFK2CYERRBKYEBXAQF4cGgLlyYFCCINeErZKFDKABSzq6omJQwgVGhlIGFyZ3VtZW50ICJvd25lciIgaXMgaW52YWxpZC46QZv2Z84REYhOEFHQUBLAcHhowUVTi1BBkl3oMUrYJgRFENshQFcCAkGb9mfOERGIThBR0FASwHB4aMFFU4tQQZJd6DFK2CYERRDbIXFpeZ5xaRC1JgQJQGkQsyYQeGjBRVOLUEEvWMXtIg9peGjBRVOLUEHmPxiECEBXAwF4ygBAtyY8DDdUaGUgYXJndW1lbnQgInRva2VuSWQiIHNob3VsZCBiZSA2NCBvciBsZXNzIGJ5dGVzIGxvbmcuOhMRiE4QUdBBm/ZnzhLAcHhowUVTi1BBkl3oMUrYJjRFDC5UaGUgdG9rZW4gd2l0aCBnaXZlbiAidG9rZW5JZCIgZG9lcyBub3QgZXhpc3QuOnFpNwAAcmoQzkBXAgETEYhOEFHQQZv2Z84SwHB4aMFFU4tQQZJd6DE3AABxyGkRzktT0EBXAQATEYhOEFHQQZv2Z84SwHATaMFFQd8wuJpAVwEBeHBoC5cmBQgiDXhK2ShQygAUs6uqJiQMH1RoZSBhcmd1bWVudCAib3duZXIiIGlzIGludmFsaWQ6FBGIThBR0EGb9mfOEsBwE3howUVTi1BB3zC4mkBXAwN4cGgLlyYFCCINeErZKFDKABSzq6omIgwdVGhlIGFyZ3VtZW50ICJ0byIgaXMgaW52YWxpZC46ExGIThBR0EGb9mfOEsBweWjBRVOLUEGSXegxNwAAcWkQznJqQfgn7IyqJgQJQGp4mCYleEppEFHQRWk3AQBKeWjBRVOLUEHmPxiERQ95ajQPEXl4NAp6eXhqNEUIQFcCA3p4NdD9//9FQZv2Z84UEYhOEFHQUBLAcHh5i9socXoQtyYQEGlowUVTi1BB5j8YhEBpaMFFU4tQQS9Yxe1AVwEEwkp4z0p5z0oRz0p6zwwIVHJhbnNmZXJBlQFvYXlwaAuXqiQFCSILeTcCAHBoC5eqJiB7ehF4FMAfDA5vbk5FUDExUGF5bWVudHlBYn1bUkVAVgFAfGetTA=="));
public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATA7znO4OTpJcbCoGp54UQN2G/OrAtkZXNlcmlhbGl6ZQEAAQ/A7znO4OTpJcbCoGp54UQN2G/OrAlzZXJpYWxpemUBAAEP/aP6Q0bqUyolj8SX3a3bZDfJ/f8LZ2V0Q29udHJhY3QBAAEPG/V1qxGJaIQTYQo1oSiGzeC2bHIGc2hhMjU2AQABDwAA/U0DDARURVNUQBBAWNgmFwwBAEH2tGviQZJd6DFK2CYERRBKYEBXAQF4cGgLlyYFCCINeErZKFDKABSzq6omJQwgVGhlIGFyZ3VtZW50ICJvd25lciIgaXMgaW52YWxpZC46QZv2Z84REYhOEFHQUBLAcHhowUVTi1BBkl3oMUrYJgRFENshQFcCAkGb9mfOERGIThBR0FASwHB4aMFFU4tQQZJd6DFK2CYERRDbIXFpeZ5xaRC1JgQJQGkQsyYQeGjBRVOLUEEvWMXtIg9peGjBRVOLUEHmPxiECEBXAwF4ygBAtyY8DDdUaGUgYXJndW1lbnQgInRva2VuSWQiIHNob3VsZCBiZSA2NCBvciBsZXNzIGJ5dGVzIGxvbmcuOhMRiE4QUdBBm/ZnzhLAcHhowUVTi1BBkl3oMUrYJjRFDC5UaGUgdG9rZW4gd2l0aCBnaXZlbiAidG9rZW5JZCIgZG9lcyBub3QgZXhpc3QuOnFpNwAAcmoQzkBXAgETEYhOEFHQQZv2Z84SwHB4aMFFU4tQQZJd6DE3AABxyEoMBG5hbWVpEc7QQFcBABMRiE4QUdBBm/ZnzhLAcBNowUVB3zC4mkBXAQF4cGgLlyYFCCINeErZKFDKABSzq6omJAwfVGhlIGFyZ3VtZW50ICJvd25lciIgaXMgaW52YWxpZDoUEYhOEFHQQZv2Z84SwHATeGjBRVOLUEHfMLiaQFcDA3hwaAuXJgUIIg14StkoUMoAFLOrqiYiDB1UaGUgYXJndW1lbnQgInRvIiBpcyBpbnZhbGlkLjoTEYhOEFHQQZv2Z84SwHB5aMFFU4tQQZJd6DE3AABxaRDOcmpB+CfsjKomBAlAaniYJiV4SmkQUdBFaTcBAEp5aMFFU4tQQeY/GIRFD3lqNA8ReXg0Cnp5eGo0RQhAVwIDeng1y/3//0VBm/ZnzhQRiE4QUdBQEsBweHmL2yhxehC3JhAQaWjBRVOLUEHmPxiEQGlowUVTi1BBL1jF7UBXAQTCSnjPSnnPShHPSnrPDAhUcmFuc2ZlckGVAW9heXBoC5eqJAUJIgt5NwIAcGgLl6omIHt6EXgUwB8MDm9uTkVQMTFQYXltZW50eUFifVtSRUBWAUB17R06"));

#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ public abstract class Contract_PropertyMethod(Neo.SmartContract.Testing.SmartCon
{
#region Compiled data

public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_PropertyMethod"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""testProperty"",""parameters"":[],""returntype"":""Array"",""offset"":0,""safe"":false},{""name"":""testProperty2"",""parameters"":[],""returntype"":""Void"",""offset"":50,""safe"":false},{""name"":""testPropertyInit"",""parameters"":[],""returntype"":""Array"",""offset"":71,""safe"":false}],""events"":[]},""permissions"":[],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");
public static Neo.SmartContract.Manifest.ContractManifest Manifest => Neo.SmartContract.Manifest.ContractManifest.Parse(@"{""name"":""Contract_PropertyMethod"",""groups"":[],""features"":{},""supportedstandards"":[],""abi"":{""methods"":[{""name"":""testProperty"",""parameters"":[],""returntype"":""Array"",""offset"":0,""safe"":false},{""name"":""testProperty2"",""parameters"":[],""returntype"":""Void"",""offset"":50,""safe"":false},{""name"":""testProperty3"",""parameters"":[],""returntype"":""Any"",""offset"":71,""safe"":false},{""name"":""testProperty4"",""parameters"":[],""returntype"":""Map"",""offset"":94,""safe"":false},{""name"":""testProperty5"",""parameters"":[],""returntype"":""Array"",""offset"":110,""safe"":false},{""name"":""testPropertyInit"",""parameters"":[],""returntype"":""Array"",""offset"":120,""safe"":false}],""events"":[]},""permissions"":[],""trusts"":[],""extra"":{""nef"":{""optimization"":""All""}}}");

/// <summary>
/// Optimization: "All"
/// </summary>
public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAINXAQALEAsTwBoMBE5FTzMSTTQPcMVKaBDOz0poEc7PQFcAA3lKeBBR0EV6SngRUdBFQFcBAAsQCxPAGgwETkVPMxJNNN1wQFcBAAsQCxPAGgwETkVPMxJNNMgMETEyMyBCbG9ja2NoYWluIFN0SxJR0HDFSmgQzs9KaBHOz0poEs7PQGh8TO4="));
public static Neo.SmartContract.NefFile Nef => Neo.IO.Helper.AsSerializable<Neo.SmartContract.NefFile>(Convert.FromBase64String(@"TkVGM1Rlc3RpbmdFbmdpbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALRXAQALEAsTwBoMBE5FTzMSTTQPcMVKaBDOz0poEc7PQFcAA3lKeBBR0EV6SngRUdBFQFcBAAsQCxPAGgwETkVPMxJNNN1wQAsQCxPASjQNDARORU8zSxBR0EBXAAFAyEoMBE5hbWUMBE5FTzPQQMJFFRQTEhEVwEBXAQALEAsTwBoMBE5FTzMSTTSXDBExMjMgQmxvY2tjaGFpbiBTdEsSUdBwxUpoEM7PSmgRzs9KaBLOz0Dp1QFJ"));

#endregion

Expand All @@ -33,6 +33,24 @@ public abstract class Contract_PropertyMethod(Neo.SmartContract.Testing.SmartCon
[DisplayName("testProperty2")]
public abstract void TestProperty2();

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("testProperty3")]
public abstract object? TestProperty3();

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("testProperty4")]
public abstract IDictionary<object, object>? TestProperty4();

/// <summary>
/// Unsafe method
/// </summary>
[DisplayName("testProperty5")]
public abstract IList<object>? TestProperty5();

/// <summary>
/// Unsafe method
/// </summary>
Expand Down
42 changes: 42 additions & 0 deletions tests/Neo.Compiler.CSharp.UnitTests/UnitTest_Property_Method.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.SmartContract.Testing;
using Neo.VM.Types;
using System.Numerics;
using Array = Neo.VM.Types.Array;

namespace Neo.Compiler.CSharp.UnitTests
{
Expand All @@ -27,6 +29,46 @@ public void TestPropertyMethod2()
// No errors
}

[TestMethod]
public void TestPropertyMethod3()
{
var person = Contract.TestProperty3()! as Array;
AssertGasConsumed(1309080); // Adjust this value based on actual gas consumption

Assert.IsNotNull(person);
Assert.AreEqual(3, person.Count);
Assert.AreEqual((person[0] as StackItem)!.GetString(), "NEO3");
Assert.AreEqual(person[1], new BigInteger(0));
}

[TestMethod]
public void TestPropertyMethod4()
{
var map = Contract.TestProperty4()!;
AssertGasConsumed(1230570); // Adjust this value based on actual gas consumption

Assert.IsNotNull(map);
Assert.AreEqual(1, map.Count);

var key = (ByteString)"Name";
Assert.IsTrue(map.ContainsKey(key));
Assert.AreEqual((map[key] as StackItem)!.GetString(), "NEO3");
}

[TestMethod]
public void TestPropertyMethod5()
{
var list = Contract.TestProperty5()!;
AssertGasConsumed(1046190); // Adjust this value based on actual gas consumption

Assert.IsNotNull(list);
Assert.AreEqual(5, list.Count);
for (var i = 0; i < 5; i++)
{
Assert.AreEqual(i + 1, (int)(BigInteger)list[i]);
}
}

[TestMethod]
public void TestPropertyInit()
{
Expand Down
Loading

0 comments on commit 17ec6d2

Please sign in to comment.