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)); }
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; }
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(); }
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)); }
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; }
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); }
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)); }
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)); }
public AbiArray(AbiType elementType) { _elementType = elementType; CSharpType = _elementType.CSharpType.MakeArrayType(); }
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; }