Skip to content

Add invokeabi command for simplified contract invocation #4033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: dev
Choose a base branch
from

Conversation

Jim8y
Copy link
Contributor

@Jim8y Jim8y commented Jun 29, 2025

Summary

  • Introduces a new invokeabi command that simplifies contract method invocation
  • Automatically parses parameters based on the contract's ABI definition
  • Improves developer experience by removing the need for manual type specifications

Description

This PR adds a new CLI command invokeabi that makes it easier to invoke smart contract methods. Instead of requiring users to manually specify parameter types in a complex JSON format, the new command automatically determines parameter types from the contract's ABI.

Key features:

  • Simplified syntax: Accept parameters as a simple array
  • ABI-based validation: Validates method existence and parameter count
  • Type-aware parsing: Automatically converts values to appropriate types based on ABI
  • Comprehensive type support: Handles all Neo parameter types including arrays and maps
  • Clear error messages: Provides helpful feedback for invalid parameters or methods

Example usage:

Before (invoke command):

invoke 0x1234...abcd transfer [{"type":"Hash160","value":"0xabc..."},{"type":"Hash160","value":"0xdef..."},{"type":"Integer","value":"100"}]

After (invokeabi command):

invokeabi 0x1234...abcd transfer ["0xabc...","0xdef...",100]

Type of change

  • Bug fix (non-breaking change)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that causes existing functionality to not work as expected)
  • Documentation update

Test plan

The new command can be tested by:

  1. Deploy a contract with various parameter types
  2. Use invokeabi to call methods with different parameter combinations
  3. Verify that parameter parsing matches the ABI definition
  4. Test error handling for invalid methods and parameter types

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code where necessary
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@Jim8y Jim8y changed the base branch from master to dev June 29, 2025 16:09
This commit introduces a new `invokeabi` command that simplifies contract
method invocation by automatically parsing parameters based on the contract's
ABI definition.

Key features:
- Accepts parameters as a simple array instead of complex type specifications
- Automatically determines parameter types from the contract's ABI
- Validates method existence and parameter count against the ABI
- Supports all Neo contract parameter types including arrays and maps
- Provides clear error messages for invalid parameters or methods

Example usage:
```
# Old invoke command (requires explicit type specification)
invoke 0x1234...abcd transfer [{"type":"Hash160","value":"0xabc..."},{"type":"Hash160","value":"0xdef..."},{"type":"Integer","value":"100"}]

# New invokeabi command (types parsed from ABI)
invokeabi 0x1234...abcd transfer ["0xabc...","0xdef...",100]
```

This enhancement improves developer experience by reducing the complexity
of contract invocation while maintaining type safety through ABI validation.
@Jim8y Jim8y force-pushed the feature/invokeabi-command branch from 2114362 to 8983731 Compare June 29, 2025 16:10
Jim8y and others added 4 commits June 30, 2025 00:11
- Created comprehensive unit tests for ParseParameterFromAbi method
- Tests cover all supported parameter types: Boolean, Integer, String,
  Hash160, ByteArray, Array, Map, and Any
- Added tests for null value handling
- Added tests for error cases (invalid integers, invalid hashes, unsupported types)
- Set up Neo.CLI.Tests project infrastructure
- All 55 tests passing successfully
- Replaced incomplete mocking with proper contract state setup using AddContract extension
- Added proper NefFile initialization with valid script and metadata
- Commit snapshot changes to ensure contract is accessible in tests
- Added comprehensive integration tests for OnInvokeAbiCommand covering:
  - Contract not found scenarios
  - Method not found scenarios
  - Wrong parameter count validation
  - Too many arguments validation
  - Invalid parameter format handling
  - Successful parameter parsing for single and multiple parameters
  - Complex type handling (arrays, maps)
  - Sender and signer parameter support
- All 55 tests passing successfully
Comment on lines 227 to 231
if (i >= method.Parameters.Length)
{
ConsoleHelper.Error($"Too many arguments. Method '{operation}' expects {method.Parameters.Length} parameters.");
return;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a suggestion, the check could be moved outside the for loop. For example,

if (args?.Count > method.Parameters.Length)
{
ConsoleHelper.Error($"Too many arguments. Method '{operation}' expects {method.Parameters.Length} parameters.");
return;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree

- Applied optimization suggestion from ajara87: moved argument count check outside the loop
- Fixed test compilation errors by updating to Assert.ThrowsExactly
- Simplified test setup using TestUtils.CreateDefaultManifest() and TestUtils.GetContract()
- Fixed JArray initialization ambiguity in tests
- All tests now passing successfully

Changes address PR review comment: #4033 (comment)
Comment on lines 323 to 337
switch (value)
{
case JBoolean:
return ParseParameterFromAbi(ContractParameterType.Boolean, value);
case JNumber:
return ParseParameterFromAbi(ContractParameterType.Integer, value);
case JString:
return ParseParameterFromAbi(ContractParameterType.String, value);
case JArray:
return ParseParameterFromAbi(ContractParameterType.Array, value);
case JObject:
return ParseParameterFromAbi(ContractParameterType.Map, value);
default:
throw new ArgumentException($"Cannot infer type for value: {value}");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To simplify the method i suggest to move this switch to a private method:

Modify switch in ParseParameterFromAbi
case ContractParameterType.Any:
return InferParameterFromToken(value);

New method
private ContractParameter InferParameterFromToken(JToken value)
{
return value.Type switch
{
JBoolean => ParseParameterFromAbi(ContractParameterType.Boolean, value),
JNumber => ParseParameterFromAbi(ContractParameterType.Integer, value),
JString => ParseParameterFromAbi(ContractParameterType.String, value),
JArray => ParseParameterFromAbi(ContractParameterType.Array, value),
JObject => ParseParameterFromAbi(ContractParameterType.Map, value),
_ => throw new ArgumentException($"Cannot infer type for value: {value}")
};
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all applied, please check

Jim8y added 3 commits June 30, 2025 01:00
…e method

- Implemented suggestion from ajara87 to improve code organization
- Extracted switch logic for ContractParameterType.Any into InferParameterFromToken method
- Converted switch statement to modern switch expression syntax
- Improved code readability and maintainability by following single responsibility principle
- ParseParameterFromAbi method is now more focused and easier to understand

Changes address PR review comment: #4033 (comment)
@Jim8y
Copy link
Contributor Author

Jim8y commented Jun 29, 2025

fixing ut issues

Fixed compilation error in UT_MainService_Contracts.cs that was preventing CI from passing:
- Updated test setup to use manual ContractState creation instead of internal TestUtils.GetContract method
- Fixed NeoSystem field injection from static to instance field
- Improved invokeabi command logic to find methods by name first, then validate argument count
- Updated test assertions to match new error message format
- All tests now pass (21/21)
@Jim8y Jim8y force-pushed the feature/invokeabi-command branch from ccea4a8 to 0819565 Compare June 29, 2025 17:37
Wi1l-B0t
Wi1l-B0t previously approved these changes Jun 30, 2025
Copy link
Contributor

@Wi1l-B0t Wi1l-B0t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Co-authored-by: Will <201105916+Wi1l-B0t@users.noreply.github.com>
Jim8y and others added 2 commits June 30, 2025 10:06
Co-authored-by: Will <201105916+Wi1l-B0t@users.noreply.github.com>
Co-authored-by: Will <201105916+Wi1l-B0t@users.noreply.github.com>
@superboyiii
Copy link
Member

Checking...

/// <summary>
/// Parse a parameter value according to its ABI type
/// </summary>
private ContractParameter ParseParameterFromAbi(ContractParameterType type, JToken? value)
Copy link
Member

@cschuchardt88 cschuchardt88 Jun 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy this code instead, Simpler and cleaner and faster. All the logic is there. For example when a JToken is null

private static StackItem ToStackItem(ContractParameter parameter, List<(StackItem, ContractParameter)> context)
{
if (parameter is null) throw new ArgumentNullException(nameof(parameter));
if (parameter.Value is null) return StackItem.Null;
StackItem stackItem = null;
switch (parameter.Type)
{
case ContractParameterType.Array:
if (context is null)
context = [];
else
(stackItem, _) = context.FirstOrDefault(p => ReferenceEquals(p.Item2, parameter));
if (stackItem is null)
{
stackItem = new Array(((IList<ContractParameter>)parameter.Value).Select(p => ToStackItem(p, context)));
context.Add((stackItem, parameter));
}
break;
case ContractParameterType.Map:
if (context is null)
context = [];
else
(stackItem, _) = context.FirstOrDefault(p => ReferenceEquals(p.Item2, parameter));
if (stackItem is null)
{
Map map = new();
foreach (var pair in (IList<KeyValuePair<ContractParameter, ContractParameter>>)parameter.Value)
map[(PrimitiveType)ToStackItem(pair.Key, context)] = ToStackItem(pair.Value, context);
stackItem = map;
context.Add((stackItem, parameter));
}
break;
case ContractParameterType.Boolean:
stackItem = (bool)parameter.Value;
break;
case ContractParameterType.ByteArray:
case ContractParameterType.Signature:
stackItem = (byte[])parameter.Value;
break;
case ContractParameterType.Integer:
stackItem = (BigInteger)parameter.Value;
break;
case ContractParameterType.Hash160:
stackItem = ((UInt160)parameter.Value).ToArray();
break;
case ContractParameterType.Hash256:
stackItem = ((UInt256)parameter.Value).ToArray();
break;
case ContractParameterType.PublicKey:
stackItem = ((ECPoint)parameter.Value).EncodePoint(true);
break;
case ContractParameterType.String:
stackItem = (string)parameter.Value;
break;
default:
throw new ArgumentException($"ContractParameterType({parameter.Type}) is not supported to StackItem.");
}
return stackItem;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

case ContractParameterType.Integer:
param.Value = BigInteger.Parse(value.AsString());
break;
case ContractParameterType.ByteArray:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be combined with ContractParameterType.Signature

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @cschuchardt88

foreach (var kvp in map.Properties)
{
var key = new ContractParameter { Type = ContractParameterType.String, Value = kvp.Key };
var val = ParseParameterFromAbi(ContractParameterType.Any, kvp.Value);
Copy link
Member

@cschuchardt88 cschuchardt88 Jun 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't going to work with type of Any. This needs to be the correct type.

case ContractParameterType.Array:
if (value is JArray array)
{
param.Value = array.Select(v => ParseParameterFromAbi(ContractParameterType.Any, v)).ToArray();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isnt going to work with the type of Any. This needs to be the correct type.

Jim8y added 2 commits June 30, 2025 14:30
- Add validation for parameter count (both too many and too few arguments)
- Fix method overloading to correctly match based on parameter count
- Add defensive null checks for contract manifest and ABI
- Improve error messages with helpful format examples
- Optimize array parsing performance
- Update tests to match new error messages and add coverage for edge cases
@Jim8y
Copy link
Contributor Author

Jim8y commented Jun 30, 2025

comments from chris applied

try
{
var contractParam = ParseParameterFromAbi(paramDef.Type, paramValue);
contractParameters.Add(contractParam.ToJson());
Copy link
Member

@superboyiii superboyiii Jun 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could return wrong contractParameters if it includes an array type param inside, for example:
the contractParameters of

invokeabi 0x49cf4e5378ffcd4dec034fd98a174c5491e395e2 designateAsRole [4,[{"type":"PublicKey","value":"0244d12f3e6b8eba7d0bc0cf0c176d9df545141f4d3447f8463c1b16afb90b1ea8"}]] NgrQRsSfE6v66GpDCFDdzj1d2KeFVoPfBP NgrQRsSfE6v66GpDCFDdzj1d2KeFVoPfBP

will be:

{[{"type":"Integer","value":"4"},{"type":"Array","value":[{"type":"Map","value":[{"key":{"type":"String","value":"type"},"value":{"type":"String","value":"PublicKey"}},{"key":{"type":"String","value":"value"},"value":{"type":"String","value":"0244d12f3e6b8eba7d0bc0cf0c176d9df545141f4d3447f8463c1b16afb90b1ea8"}}]}]}]}

but it should be:

[{"type":"Integer","value":"4"},{"type":"Array","value":[{"type":"PublicKey","value":"0244d12f3e6b8eba7d0bc0cf0c176d9df545141f4d3447f8463c1b16afb90b1ea8"}]}]

This can make invokeabi fail:
1751267880345

cschuchardt88 and others added 6 commits June 30, 2025 05:09
Addresses critical issue identified by superboyiii where arrays containing
ContractParameter format objects (like {"type":"PublicKey","value":"..."})
were incorrectly parsed as Maps instead of the specified parameter type.

- Add ParseContractParameterObject method to detect ContractParameter format
- Update InferParameterFromToken to handle ContractParameter objects correctly
- Maintain backward compatibility for regular JSON objects as Maps
- Add comprehensive tests for both scenarios

This ensures that complex nested arrays with typed parameters work correctly
in the invokeabi command.
Addresses the real issue identified by superboyiii where array parameters
need to preserve the explicit type information since ABI doesn't specify
element types for arrays.

- For Array type parameters, check if elements are in ContractParameter format
- Use ContractParameter.FromJson() for explicit type objects
- Otherwise infer types for simple values
- This ensures arrays like [{"type":"PublicKey","value":"..."}] work correctly

This is the correct fix that maintains compatibility with the existing
invoke command while providing the simplified syntax for simple cases.
Similar to Arrays, Map parameters in ABI don't specify key/value types,
so we need to preserve explicit type information when provided.

- Support complete ContractParameter format maps (from invoke command)
- Support mixed maps with some values in ContractParameter format
- Maintain type inference for simple values
- Add comprehensive tests for both formats

This ensures compatibility with complex map structures while keeping
the simplified syntax for simple cases.
@superboyiii
Copy link
Member

I tried invoking deploy to deploy a contract. The byteArray works well but seems there's a problem when handling Json to String.

invokeabi 0xfffdc93764dbaddd97c48f252a53ea4643faa3fd deploy ["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","{\"name\":\"fBNBv2\",\"groups\":[],\"features\":{},\"supportedstandards\":[\"NEP-17\"],\"abi\":{\"methods\":[{\"name\":\"symbol\",\"parameters\":[],\"returntype\":\"String\",\"offset\":1570,\"safe\":true},{\"name\":\"decimals\",\"parameters\":[],\"returntype\":\"Integer\",\"offset\":1585,\"safe\":true},{\"name\":\"totalSupply\",\"parameters\":[],\"returntype\":\"Integer\",\"offset\":43,\"safe\":true},{\"name\":\"balanceOf\",\"parameters\":[{\"name\":\"owner\",\"type\":\"Hash160\"}],\"returntype\":\"Integer\",\"offset\":89,\"safe\":true},{\"name\":\"transfer\",\"parameters\":[{\"name\":\"from\",\"type\":\"Hash160\"},{\"name\":\"to\",\"type\":\"Hash160\"},{\"name\":\"amount\",\"type\":\"Integer\"},{\"name\":\"data\",\"type\":\"Any\"}],\"returntype\":\"Boolean\",\"offset\":353,\"safe\":false},{\"name\":\"factor\",\"parameters\":[],\"returntype\":\"Integer\",\"offset\":40,\"safe\":false},{\"name\":\"_deploy\",\"parameters\":[{\"name\":\"data\",\"type\":\"Any\"},{\"name\":\"update\",\"type\":\"Boolean\"}],\"returntype\":\"Void\",\"offset\":909,\"safe\":false},{\"name\":\"setOwner\",\"parameters\":[{\"name\":\"newOwner\",\"type\":\"Hash160\"}],\"returntype\":\"Void\",\"offset\":942,\"safe\":false},{\"name\":\"getOwner\",\"parameters\":[],\"returntype\":\"Hash160\",\"offset\":807,\"safe\":false},{\"name\":\"setMinter\",\"parameters\":[{\"name\":\"minter\",\"type\":\"Hash160\"}],\"returntype\":\"Void\",\"offset\":1034,\"safe\":false},{\"name\":\"getMinter\",\"parameters\":[],\"returntype\":\"Hash160\",\"offset\":852,\"safe\":false},{\"name\":\"mint\",\"parameters\":[{\"name\":\"account\",\"type\":\"Hash160\"},{\"name\":\"amount\",\"type\":\"Integer\"}],\"returntype\":\"Void\",\"offset\":1098,\"safe\":false},{\"name\":\"update\",\"parameters\":[{\"name\":\"nefFile\",\"type\":\"ByteArray\"},{\"name\":\"manifest\",\"type\":\"String\"}],\"returntype\":\"Void\",\"offset\":1390,\"safe\":false},{\"name\":\"destroy\",\"parameters\":[],\"returntype\":\"Void\",\"offset\":1428,\"safe\":false},{\"name\":\"_initialize\",\"parameters\":[],\"returntype\":\"Void\",\"offset\":1461,\"safe\":false}],\"events\":[{\"name\":\"Transfer\",\"parameters\":[{\"name\":\"from\",\"type\":\"Hash160\"},{\"name\":\"to\",\"type\":\"Hash160\"},{\"name\":\"amount\",\"type\":\"Integer\"}]},{\"name\":\"OnSetOwner\",\"parameters\":[{\"name\":\"arg1\",\"type\":\"Hash160\"},{\"name\":\"arg2\",\"type\":\"Hash160\"}]},{\"name\":\"OnSetMinter\",\"parameters\":[{\"name\":\"obj\",\"type\":\"Hash160\"}]}]},\"permissions\":[{\"contract\":\"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd\",\"methods\":[\"destroy\",\"getContract\",\"update\"]},{\"contract\":\"*\",\"methods\":[\"onNEP17Payment\"]}],\"trusts\":[],\"extra\":{\"Description\":\"Flamingo FToken v2\",\"Version\":\"2.0\"}}"] NPaoYwy79JeyqE1i23QKiv9Tb1prtXeZBb NPaoYwy79JeyqE1i23QKiv9Tb1prtXeZBb

Rpc invokefunction can handle this well:
9c5d05891fb515d1123958d0b3307eb
But this isn't a new bug from this PR, invoke has this issue as well:
1751355373178
I will open a new issue later.
So this one IGTM.

Copy link
Member

@vncoelho vncoelho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, @Jim8y

Good call.

Just check @cschuchardt88 suggestion

@Wi1l-B0t
Copy link
Contributor

Wi1l-B0t commented Jul 1, 2025

I tried invoking deploy to deploy a contract. The byteArray works well but seems there's a problem when handling Json to String.

invokeabi 0xfffdc93764dbaddd97c48f252a53ea4643faa3fd deploy ["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","{\"name\":\"fBNBv2\",\"groups\":[],\"features\":{},\"supportedstandards\":[\"NEP-17\"],\"abi\":{\"methods\":[{\"name\":\"symbol\",\"parameters\":[],\"returntype\":\"String\",\"offset\":1570,\"safe\":true},{\"name\":\"decimals\",\"parameters\":[],\"returntype\":\"Integer\",\"offset\":1585,\"safe\":true},{\"name\":\"totalSupply\",\"parameters\":[],\"returntype\":\"Integer\",\"offset\":43,\"safe\":true},{\"name\":\"balanceOf\",\"parameters\":[{\"name\":\"owner\",\"type\":\"Hash160\"}],\"returntype\":\"Integer\",\"offset\":89,\"safe\":true},{\"name\":\"transfer\",\"parameters\":[{\"name\":\"from\",\"type\":\"Hash160\"},{\"name\":\"to\",\"type\":\"Hash160\"},{\"name\":\"amount\",\"type\":\"Integer\"},{\"name\":\"data\",\"type\":\"Any\"}],\"returntype\":\"Boolean\",\"offset\":353,\"safe\":false},{\"name\":\"factor\",\"parameters\":[],\"returntype\":\"Integer\",\"offset\":40,\"safe\":false},{\"name\":\"_deploy\",\"parameters\":[{\"name\":\"data\",\"type\":\"Any\"},{\"name\":\"update\",\"type\":\"Boolean\"}],\"returntype\":\"Void\",\"offset\":909,\"safe\":false},{\"name\":\"setOwner\",\"parameters\":[{\"name\":\"newOwner\",\"type\":\"Hash160\"}],\"returntype\":\"Void\",\"offset\":942,\"safe\":false},{\"name\":\"getOwner\",\"parameters\":[],\"returntype\":\"Hash160\",\"offset\":807,\"safe\":false},{\"name\":\"setMinter\",\"parameters\":[{\"name\":\"minter\",\"type\":\"Hash160\"}],\"returntype\":\"Void\",\"offset\":1034,\"safe\":false},{\"name\":\"getMinter\",\"parameters\":[],\"returntype\":\"Hash160\",\"offset\":852,\"safe\":false},{\"name\":\"mint\",\"parameters\":[{\"name\":\"account\",\"type\":\"Hash160\"},{\"name\":\"amount\",\"type\":\"Integer\"}],\"returntype\":\"Void\",\"offset\":1098,\"safe\":false},{\"name\":\"update\",\"parameters\":[{\"name\":\"nefFile\",\"type\":\"ByteArray\"},{\"name\":\"manifest\",\"type\":\"String\"}],\"returntype\":\"Void\",\"offset\":1390,\"safe\":false},{\"name\":\"destroy\",\"parameters\":[],\"returntype\":\"Void\",\"offset\":1428,\"safe\":false},{\"name\":\"_initialize\",\"parameters\":[],\"returntype\":\"Void\",\"offset\":1461,\"safe\":false}],\"events\":[{\"name\":\"Transfer\",\"parameters\":[{\"name\":\"from\",\"type\":\"Hash160\"},{\"name\":\"to\",\"type\":\"Hash160\"},{\"name\":\"amount\",\"type\":\"Integer\"}]},{\"name\":\"OnSetOwner\",\"parameters\":[{\"name\":\"arg1\",\"type\":\"Hash160\"},{\"name\":\"arg2\",\"type\":\"Hash160\"}]},{\"name\":\"OnSetMinter\",\"parameters\":[{\"name\":\"obj\",\"type\":\"Hash160\"}]}]},\"permissions\":[{\"contract\":\"0xfffdc93764dbaddd97c48f252a53ea4643faa3fd\",\"methods\":[\"destroy\",\"getContract\",\"update\"]},{\"contract\":\"*\",\"methods\":[\"onNEP17Payment\"]}],\"trusts\":[],\"extra\":{\"Description\":\"Flamingo FToken v2\",\"Version\":\"2.0\"}}"] NPaoYwy79JeyqE1i23QKiv9Tb1prtXeZBb NPaoYwy79JeyqE1i23QKiv9Tb1prtXeZBb

Rpc invokefunction can handle this well: 9c5d05891fb515d1123958d0b3307eb But this isn't a new bug from this PR, invoke has this issue as well: 1751355373178 I will open a new issue later. So this one IGTM.

Because some format issues in this input.

{69B0D53B-D97A-4315-B205-CCEBB7289EA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69B0D53B-D97A-4315-B205-CCEBB7289EA9}.Release|Any CPU.Build.0 = Release|Any CPU
{69B0D53B-D97A-4315-B205-CCEBB7289EA9}.Release|x64.ActiveCfg = Release|Any CPU
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jim8y All of these changes are needed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, they need to be removed.

case ContractParameterType.Integer:
param.Value = BigInteger.Parse(value.AsString());
break;
case ContractParameterType.ByteArray:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @cschuchardt88

@Wi1l-B0t
Copy link
Contributor

Wi1l-B0t commented Jul 8, 2025

Need to resolve conflicts.

@Wi1l-B0t
Copy link
Contributor

Need update @Jim8y

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants