internal static (Array, int) DecodeSequence(Type elementType, int length, IEnumerable <AbiType> types, byte[] data, bool packed, int startPosition)
        {
            Array sequence        = Array.CreateInstance(elementType, length);
            int   position        = startPosition;
            int   dynamicPosition = 0;

            using IEnumerator <AbiType> typesEnumerator = types.GetEnumerator();
            object?item;

            for (int i = 0; i < length; i++)
            {
                typesEnumerator.MoveNext();
                AbiType type = typesEnumerator.Current;

                if (type.IsDynamic)
                {
                    (UInt256 offset, int nextPosition) = UInt256.DecodeUInt(data, position, packed);
                    (item, dynamicPosition)            = type.Decode(data, startPosition + (int)offset, packed);
                    position = nextPosition;
                }
                else
                {
                    (item, position) = type.Decode(data, position, packed);
                }

                sequence.SetValue(item, i);
            }

            return(sequence, Math.Max(position, dynamicPosition));
        }
示例#2
0
        public override bool Equals(object obj)
        {
            AbiType type = obj as AbiType;

            return(type != null &&
                   Name == type.Name);
        }
        protected static AbiType GetForCSharpType(Type type)
        {
            if (_typeMappings.TryGetValue(type, out AbiType? abiTYpe))
            {
                return(abiTYpe);
            }
            else if (type.IsArray)
            {
                if (type == typeof(byte[]))
                {
                    return(DynamicBytes);
                }

                Type elementType = type.GetElementType() !;
                return(new AbiArray(GetForCSharpType(elementType)));
            }
            else if (type.IsValueTuple())
            {
                Type[]    subTypes = type.GetGenericArguments();
                AbiType[] elements = new AbiType[subTypes.Length];
                for (int i = 0; i < subTypes.Length; i++)
                {
                    elements[i] = GetForCSharpType(subTypes[i]);
                }

                return(new AbiTuple(elements));
            }
            else
            {
                throw new NotSupportedException($"Type {type} doesn't have mapped {nameof(AbiType)}");
            }
        }
        static AbiType()
        {
            AbiType type = AbiAddress.Instance;

            type = AbiBool.Instance;
            type = AbiDynamicBytes.Instance;
            type = AbiInt.Int8;
            type = AbiString.Instance;
            type = AbiUInt.UInt8;
        }
示例#5
0
        public AbiFixedLengthArray(AbiType elementType, int length)
        {
            if (length <= 0)
            {
                throw new ArgumentException($"Length of {nameof(AbiFixedLengthArray)} has to be greater than 0", nameof(length));
            }

            _elementType = elementType;
            Length       = length;
            CSharpType   = _elementType.CSharpType.MakeArrayType();
        }
示例#6
0
        public byte[] Encode(AbiEncodingStyle encodingStyle, AbiSignature signature, params object[] arguments)
        {
            bool packed = (encodingStyle & AbiEncodingStyle.Packed) == AbiEncodingStyle.Packed;

            if (arguments.Length != signature.Types.Length)
            {
                throw new AbiException(
                          $"Insufficient parameters for {signature.Name}. Expected {signature.Types.Length} arguments but got {arguments.Length}");
            }

            List <byte[]> dynamicParts  = new();
            List <byte[]> headerParts   = new();
            BigInteger    currentOffset = arguments.Length * AbiType.UInt256.LengthInBytes;

            for (int i = 0; i < arguments.Length; i++)
            {
                AbiType type = signature.Types[i];
                if (type.IsDynamic)
                {
                    headerParts.Add(AbiType.UInt256.Encode(currentOffset, packed));
                    byte[] encoded = type.Encode(arguments[i], packed);
                    currentOffset += encoded.Length;
                    dynamicParts.Add(encoded);
                }
                else
                {
                    headerParts.Add(type.Encode(arguments[i], packed));
                }
            }

            bool includeSig = encodingStyle == AbiEncodingStyle.IncludeSignature;
            int  sigOffset  = includeSig ? 1 : 0;

            byte[][] encodedParts = new byte[sigOffset + headerParts.Count + dynamicParts.Count][];

            if (includeSig)
            {
                encodedParts[0] = signature.Address;
            }

            for (int i = 0; i < headerParts.Count; i++)
            {
                encodedParts[sigOffset + i] = headerParts[i];
            }

            for (int i = 0; i < dynamicParts.Count; i++)
            {
                encodedParts[sigOffset + headerParts.Count + i] = dynamicParts[i];
            }

            return(Bytes.Concat(encodedParts));
        }
示例#7
0
        public AbiFixedLengthArray(AbiType elementType, int length)
        {
            if (length <= 0)
            {
                throw new ArgumentException($"Length of {nameof(AbiFixedLengthArray)} has to be greater than 0", nameof(length));
            }

            ElementType = elementType;
            Length      = length;
            Name        = $"{ElementType}[{Length}]";
            CSharpType  = ElementType.CSharpType.MakeArrayType();
            IsDynamic   = Length != 0 && ElementType.IsDynamic;
        }
示例#8
0
        public object[] Decode(AbiEncodingStyle encodingStyle, AbiSignature signature, byte[] data)
        {
            bool packed     = (encodingStyle & AbiEncodingStyle.Packed) == AbiEncodingStyle.Packed;
            bool includeSig = encodingStyle == AbiEncodingStyle.IncludeSignature;
            int  sigOffset  = includeSig ? 4 : 0;

            string[] argTypeNames = new string[signature.Types.Length];
            for (int i = 0; i < signature.Types.Length; i++)
            {
                argTypeNames[i] = signature.Types[i].ToString();
            }

            int position = 0;

            if (encodingStyle == AbiEncodingStyle.IncludeSignature)
            {
                if (!Bytes.AreEqual(data.Slice(0, 4), ComputeAddress(signature)))
                {
                    throw new AbiException(
                              $"Signature in encoded ABI data is not consistent with {ComputeSignature(signature.Name, signature.Types)}");
                }

                position = 4;
            }

            object[] arguments       = new object[signature.Types.Length];
            int      dynamicPosition = 0;

            for (int i = 0; i < signature.Types.Length; i++)
            {
                AbiType type = signature.Types[i];
                if (type.IsDynamic)
                {
                    // TODO: do not have to decode this - can just jump 32 and check if first call and use dynamic position
                    (BigInteger offset, int nextPosition) = AbiType.UInt256.DecodeUInt(data, position, packed);
                    (arguments[i], dynamicPosition)       = type.Decode(data, sigOffset + (int)offset, packed);
                    position = nextPosition;
                }
                else
                {
                    (arguments[i], position) = type.Decode(data, position, packed);
                }
            }

            if (Math.Max(position, dynamicPosition) != data.Length)
            {
                throw new AbiException($"Unexpected data at position {position}");
            }

            return(arguments);
        }
示例#9
0
        public byte[] Encode(AbiEncodingStyle encodingStyle, AbiSignature signature, params object[] arguments)
        {
            bool packed = (encodingStyle & AbiEncodingStyle.Packed) == AbiEncodingStyle.Packed;

            List <byte[]> dynamicParts  = new List <byte[]>();
            List <byte[]> headerParts   = new List <byte[]>();
            BigInteger    currentOffset = arguments.Length * AbiType.UInt256.LengthInBytes;

            for (int i = 0; i < arguments.Length; i++)
            {
                AbiType type = signature.Types[i];
                if (type.IsDynamic)
                {
                    headerParts.Add(AbiType.UInt256.Encode(currentOffset, packed));
                    byte[] encoded = type.Encode(arguments[i], packed);
                    currentOffset += encoded.Length;
                    dynamicParts.Add(encoded);
                }
                else
                {
                    headerParts.Add(type.Encode(arguments[i], packed));
                }
            }

            bool includeSig = encodingStyle == AbiEncodingStyle.IncludeSignature;
            int  sigOffset  = includeSig ? 1 : 0;

            byte[][] encodedParts = new byte[sigOffset + headerParts.Count + dynamicParts.Count][];

            if (includeSig)
            {
                encodedParts[0] = ComputeAddress(signature);
            }

            for (int i = 0; i < headerParts.Count; i++)
            {
                encodedParts[sigOffset + i] = headerParts[i];
            }

            for (int i = 0; i < dynamicParts.Count; i++)
            {
                encodedParts[sigOffset + headerParts.Count + i] = dynamicParts[i];
            }

            return(Bytes.Concat(encodedParts));
        }
示例#10
0
        public byte[] Encode(AbiSignature signature, params object[] arguments)
        {
            List <byte[]> dynamicParts  = new List <byte[]>();
            List <byte[]> headerParts   = new List <byte[]>();
            BigInteger    currentOffset = arguments.Length * AbiType.UInt.LengthInBytes;

            for (int i = 0; i < arguments.Length; i++)
            {
                AbiType type = signature.Types[i];
                if (type.IsDynamic)
                {
                    headerParts.Add(AbiType.UInt.Encode(currentOffset));
                    byte[] encoded = type.Encode(arguments[i]);
                    currentOffset += encoded.Length;
                    dynamicParts.Add(encoded);
                }
                else
                {
                    headerParts.Add(type.Encode(arguments[i]));
                }
            }

            byte[][] encodedParts = new byte[1 + headerParts.Count + dynamicParts.Count][];
            encodedParts[0] = ComputeAddress(signature);
            for (int i = 0; i < headerParts.Count; i++)
            {
                encodedParts[1 + i] = headerParts[i];
            }

            for (int i = 0; i < dynamicParts.Count; i++)
            {
                encodedParts[1 + headerParts.Count + i] = dynamicParts[i];
            }

            return(Bytes.Concat(encodedParts));
        }
示例#11
0
 public AbiArray(AbiType elementType)
 {
     _elementType = elementType;
     CSharpType   = _elementType.CSharpType.MakeArrayType();
 }
示例#12
0
 public AbiArray(AbiType elementType)
 {
     ElementType = elementType;
     Name        = $"{ElementType}[]";
     CSharpType  = ElementType.CSharpType.MakeArrayType();
 }
        internal static byte[][] EncodeSequence(int length, IEnumerable <AbiType> types, IEnumerable <object?> sequence, bool packed, int offset = 0)
        {
            List <byte[]>  dynamicParts = new(length);
            List <byte[]?> headerParts  = new(length);

            using IEnumerator <object?> sequenceEnumerator = sequence.GetEnumerator();
            using IEnumerator <AbiType> typesEnumerator    = types.GetEnumerator();
            for (int i = 0; i < length; i++)
            {
                sequenceEnumerator.MoveNext();
                typesEnumerator.MoveNext();
                object? element = sequenceEnumerator.Current;
                AbiType type    = typesEnumerator.Current;

                byte[] encoded = type.Encode(element, packed);

                // encode each type
                if (type.IsDynamic)
                {
                    // offset placeholder, we cannot calculate offset before calculating all header parts
                    headerParts.Add(null);
                    dynamicParts.Add(encoded);
                }
                else
                {
                    headerParts.Add(encoded);
                }
            }

            // now lets calculate proper offset
            BigInteger currentOffset = 0;

            // offset of header
            for (int i = 0; i < headerParts.Count; i++)
            {
                currentOffset += headerParts[i]?.Length ?? PaddingSize;
            }

            // offset dynamic parts, calculating the actual offset of each part
            int dynamicPartsIndex = 0;

            for (int i = 0; i < headerParts.Count; i++)
            {
                if (headerParts[i] is null)
                {
                    headerParts[i] = UInt256.Encode(currentOffset, packed);
                    currentOffset += dynamicParts[dynamicPartsIndex++].Length;
                }
            }

            byte[][] encodedParts = new byte[offset + headerParts.Count + dynamicParts.Count][];

            for (int i = 0; i < headerParts.Count; i++)
            {
                encodedParts[offset + i] = headerParts[i] !;
            }

            for (int i = 0; i < dynamicParts.Count; i++)
            {
                encodedParts[offset + headerParts.Count + i] = dynamicParts[i];
            }

            return(encodedParts);
        }
 protected static void RegisterMapping <T>(AbiType abiType)
 {
     _typeMappings[typeof(T)] = abiType;
 }