Giter Site home page Giter Site logo

Comments (18)

foued1979 avatar foued1979 commented on June 18, 2024

Error is coming from the ArrayTypeDecoder.DecodeStaticElement (for static elements), line 117, where var decodedListOutput = (IList) Activator.CreateInstance(type) is used; system cannot create an array without size being specified. Then, if using Activator.CreateInstance(type, size) we are facing the issue where the size is fixed and we cannot add elements in DecodeAndAddElement.

The code should be changed into
var elementType = GetIListElementType(type);
if (elementType == null)
throw new Exception("Only types that implement IList<T> are supported to decoded Array Types");

var decodedListOutput = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType));

if (decodedListOutput == null)
throw new Exception("Only types that implement IList<T> are supported to decoded Array Types");

var currentIndex = 0;
while (currentIndex < size)
{
var encodedElement = encoded.Skip(currentIndex * ElementType.FixedSize).Take(ElementType.FixedSize).ToArray();
DecodeAndAddElement(elementType, decodedListOutput, encodedElement);
currentIndex++;
}
return ToArray(decodedListOutput, elementType, size);

Where
private object ToArray(IList list, Type elementType, int size)
{
var array = Array.CreateInstance(elementType, size);
for (int i = 0; i < size; i++) array.SetValue(list[i], i);
return array;
}

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

How are you declaring the DTO / Struct in Nethereum?

from nethereum.

foued1979 avatar foued1979 commented on June 18, 2024

The output parameters were declared as arrays in the function DTO (address[] and uint256[]).

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

The output parameters were declared as arrays in the function DTO (address[] and uint256[]).

No I mean can you copy and paste your csharp code

from nethereum.

foued1979 avatar foued1979 commented on June 18, 2024

The function DTOs are created dynamically (so nothing easily readable) at runtime based on the specifications of the function definitions. The function definition looks like:

<Function>
<Reference>1</Reference>
<Name>getPoolTokens</Name>
<FunctionType>GetPoolTokens</FunctionType>
<Constant>true</Constant>
<InputParameters>
<Parameter Alias="PoolId" Name="poolId" Type="bytes32" Order="1"></Parameter>
</InputParameters>
<OutputParameters>
<Parameter Alias="Tokens" Name="tokens" Type="address[]" Order="1"></Parameter>
<Parameter Alias="Balances" Name="balances" Type="uint256[]" Order="2"></Parameter>
<Parameter Alias="LastChangeBlock" Name="lastChangeBlock" Type="uint256" Order="3"></Parameter>
</OutputParameters>
</Function>

The parameters are used to declare the properties of the function output DTO, with the corresponding ParameterAttribute (where type of parameter attribute is equal to the Type of the spec). The property of the C# class will be converted such as (for example): uint256 -> BigInteger, address -> string

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

Why don't just use the code generator, that is why is there, instead of using your own custom.. just use the abi to generate your code instead of xml, you might be doing something wrong with your custom generator.

So make sure what you do generate is right ...

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

demo-etherscan-codegen-balancer

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

Invalid issue, closing

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

@foued1979 Can you let me know if this some tool or third party service, and which one it is if so?

from nethereum.

foued1979 avatar foued1979 commented on June 18, 2024

Why don't just use the code generator, that is why is there, instead of using your own custom.. just use the abi to generate your code instead of xml, you might be doing something wrong with your custom generator.

So make sure what you do generate is right ...

My code is 100% correct; it is not a third party, it is all developed by me for high frequency trading. I use my own ABI conventions to have my own contract ABIs, more flexible and able to read / write all type of contracts (whether EVM or not).
I was expecting the Nethereum code to be more flexible (i.e. not being too strongly typed when declaring parameters) => the modification I brought to the Nethereum code is (I believe) more flexible and is now working (enables to create fully custom ABIs).

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

You might have missed something

image

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

You don't need to be strongly typed either https://playground.nethereum.com/csharp/id/1070

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

But really cool regardless !! I hope is helping you

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

I got you know, so you are creating FunctionABIs etc from Xml instead the json ABI, or human readable http://playground.nethereum.com/csharp/id/1068
image
There are extensions to deserialise to default to dynamic, json etc.. just have a look, all arrays are supported.

from nethereum.

foued1979 avatar foued1979 commented on June 18, 2024

In fact, I have created my own mapping with my own function names so that different contracts with same functionalities are interpreted in the same way by my code <=> for example, a swap, regardless of the signature or contract format, is understood as a swap by my code. Same as for any smart contract functionality (getBalance, allowance, getReserves, etc.).

I have exchange / blockchain managers acting in parallel and managing pairs / tokens across different blockchains and exchanges, simultaneously, to detect DEX vs DEX arbitrage opportunities (within less than 1s for 2000 paths, approximately - and my ABI typology helps avoiding data collision when using RPC requests) => as you can imagine, I needed to have the lightest code as possible to have the code being straight to the point (and also flexible enough to onboard any future format - including digital assets).

Btw, your Nethereum code has been exceptionally helping for my implementation; that's a really great library.

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

In fact, I have created my own mapping with my own function names so that different contracts with same functionalities are interpreted in the same way by my code <=> for example, a swap, regardless of the signature or contract format, is understood as a swap by my code. Same as for any smart contract functionality (getBalance, allowance, getReserves, etc.).

Ah excellent that was mainly the idea of the typed objects, that they can be reused across a Swap is a swap across many standards and GetBalance etc, now i see your point of using the custom xml as it is easier to onboard, ie does this system have x and y functionality.

I have TODO to use generators that will speed up the encoding / decoing, so that might help you in the future even if typed.

I have exchange / blockchain managers acting in parallel and managing pairs / tokens across different blockchains and exchanges, simultaneously, to detect DEX vs DEX arbitrage opportunities (within less than 1s for 2000 paths, approximately - and my ABI typology helps avoiding data collision when using RPC requests) => as you can imagine, I needed to have the lightest code as possible to have the code being straight to the point (and also flexible enough to onboard any future format - including digital assets).

Awesome, that is great. I would never have thought that will be still arbing opportunities.

from nethereum.

juanfranblanco avatar juanfranblanco commented on June 18, 2024

Well if it helps on the dynamic

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Threading.Tasks;
using Nethereum.ABI.FunctionEncoding.Attributes;
using Nethereum.ABI.FunctionEncoding;
using Nethereum.ABI.Model;
using Nethereum.Contracts;
using Nethereum.Web3.Accounts;
using Nethereum.Web3;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.Hex.HexTypes;
using System.Linq;


public class DynamicRebalancer
{

	public static async Task Main()
	{
		
		var web3 = new Web3("https://mainnet.infura.io/v3/ddd5ed15e8d443e295b696c0d07c8b02");

		var contract = web3.Eth.GetContract(@"
		[{'inputs':[{'internalType':'bytes32','name':'poolId','type':'bytes32'}],'name':'getPoolTokens','outputs':[{'internalType':'contract IERC20[]','name':'tokens','type':'address[]'},{'internalType':'uint256[]','name':'balances','type':'uint256[]'},{'internalType':'uint256','name':'lastChangeBlock','type':'uint256'}],'stateMutability':'view','type':'function'}]", "0xba12222222228d8ba445958a75a0704d566bf2c8");
	
		var getPoolTokensFunction = contract.GetFunction("getPoolTokens");
		var output = await getPoolTokensFunction.CallDecodingToDefaultAsync("0xa6f548df93de924d73be7d25dc02554c6bd66db500020000000000000000000e".HexToByteArray());
		var jobject = output.ConvertToJObject();

		Console.WriteLine(jobject.ToString());
	}	
}

from nethereum.

foued1979 avatar foued1979 commented on June 18, 2024

Thanks - I will have a look. I assume that a conversion occurs when parameters are created using GetContract; conversion doesn't occur when I dynamically create the parameters and attach "my" ABI to the Nethereum contract.ABI class. The initial error i was getting (in the decoder) was "cannot dynamically create instance of System.String[]"; which is due to the fact that size of array must be specified with the Activator.CreateInstance (or the Array.CreateInstance). But then, when using the size of the parameter to create the array, I was confronted to the fixed size and therefore the impossibility to use Add => I changed the code to create instance of List and then convert the list to Array.

This is how I create the contractABI; abi that I attach to the new Contract(new RPC.EthApiService(web3.Client), typeof(AbiModel.ContractABI), contractId).ContractBuilder.ContractABI:

var abiContract = new ContractABI();
var abiFunctions = new List();

foreach (var function in listOfFunctions)
{
var functionAbi = new FunctionABI(function.Name, function.Constant);
var newAliases = new SortedDictionary<string, string>();
var inputParameters = new List<EthAbi.Parameter>();
var outputParameters = new List<EthAbi.Parameter>();

if (function.InputParameters != null)
    foreach (var parameter in function.InputParameters)
    {
		var inputParam = new EthAbi.Parameter(parameter.Type, parameter.Name, parameter.Order);

		if (parameter.Type == "tuple")
        {
			var component = StructuresDef.Structures.First(c => c.Name == parameter.ComponentName);
			var tupleParameters = new List<EthAbi.Parameter>();

			foreach (var componentParameter in component.Parameters)
			{
				tupleParameters.Add(new EthAbi.Parameter(componentParameter.Type, componentParameter.Name, componentParameter.Order));
			}

            (inputParam.ABIType as TupleType)!.SetComponents(tupleParameters.ToArray()); 
		}

		inputParameters.Add(inputParam);
	}  


if (function.OutputParameters != null)
    foreach (var parameter in function.OutputParameters)
    {
        outputParameters.Add(new EthAbi.Parameter(parameter.Type, parameter.Name, parameter.Order));
        if (!functionOutputAliases.ContainsKey(parameter.Name)) newAliases.Add(parameter.Name, parameter.Alias);
    }

functionAbi.InputParameters = inputParameters.ToArray();
functionAbi.OutputParameters = outputParameters.ToArray();

abiFunctions.Add(functionAbi);

if (function.FunctionType == "Other") functionNameMapping.Add(function.Name, function.Name);
else functionNameMapping.Add(function.FunctionType, function.Name);

functionOutputAliases.Add(function.Name, newAliases);

}

abiContract.Events = listOfEvents.ToArray();
abiContract.Functions = abiFunctions.ToArray();

from nethereum.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.