public override void Decode(ref AbiDecodeBuffer buff, out bool val) { // Input data validity check: last byte should be either 0 or 1. switch (buff.HeadCursor[31]) { case 0: val = false; break; case 1: val = true; break; default: throw Error(buff.HeadCursor); } #if ZERO_BYTE_CHECKS // Input data validity check: all but the last byte should be zero. // Span<byte>.SequenceEquals should use the fast native memory slab comparer. if (!buff.HeadCursor.Slice(0, UInt256.SIZE - 1).SequenceEqual(ZEROx31)) { throw Error(buff.HeadCursor.Slice(0, UInt256.SIZE - 1)); } #endif buff.IncrementHeadCursor(UInt256.SIZE); Exception Error(ReadOnlySpan <byte> payload) { return(new ArgumentException("Invalid boolean input data; should be 31 zeros followed by a 1 or 0; received: " + payload.Slice(0, UInt256.SIZE).ToHexString())); } }
public override void Decode(ref AbiDecodeBuffer buff, out string val) { var uintEncoder = UInt256Encoder.UncheckedEncoders.Get(); try { // Read the next header int which is the offset to the start of the data // in the data payload area. uintEncoder.Decode(buff.HeadCursor, out int startingPosition); // The first int in our offset of data area is the length of the rest of the payload. var encodedLength = buff.Buffer.Slice(startingPosition, UInt256.SIZE); uintEncoder.Decode(encodedLength, out int byteLen); // Read the actual payload from the data area var encodedString = buff.Buffer.Slice(startingPosition + UInt256.SIZE, byteLen); var bytes = new byte[byteLen]; encodedString.CopyTo(bytes); val = UTF8.GetString(bytes); int bodyLen = PadLength(bytes.Length, UInt256.SIZE); buff.IncrementHeadCursor(UInt256.SIZE); } finally { UInt256Encoder.UncheckedEncoders.Put(uintEncoder); } }
public void Decode(ref AbiDecodeBuffer buff, out TItem[] val) { var uintEncoder = UInt256Encoder.UncheckedEncoders.Get(); try { // Read the next header int which is the offset to the start of the data // in the data payload area. uintEncoder.Decode(buff.HeadCursor, out int startingPosition); // The first int in our offset of data area is the length of the rest of the payload. var encodedLength = buff.Buffer.Slice(startingPosition, UInt256.SIZE); uintEncoder.Decode(encodedLength, out int itemCount); var payloadOffset = startingPosition + UInt256.SIZE; var payload = buff.Buffer.Slice(payloadOffset, buff.Buffer.Length - payloadOffset); var payloadBuffer = new AbiDecodeBuffer(payload, Enumerable.Repeat(_info.ArrayItemInfo, itemCount).ToArray()); var items = new TItem[itemCount]; for (var i = 0; i < itemCount; i++) { _itemEncoder.Decode(ref payloadBuffer, out var item); items[i] = item; } val = items; buff.IncrementHeadCursor(UInt256.SIZE); } finally { UInt256Encoder.UncheckedEncoders.Put(uintEncoder); } }
public void Int24_2() { var encodedNum = "0000000000000000000000000000000000000000000000000000000000fed260"; var buff = new AbiDecodeBuffer(encodedNum, "int24"); DecoderFactory.Decode("int24", ref buff, out int result); Assert.Equal(0, buff.HeadCursor.Length); Assert.Equal(-77216, result); }
public void StringUnicode() { var encodedStr = "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000028757466383b20342062797465733a20f0a0beb43b20332062797465733a20e28fb020776f726b7321000000000000000000000000000000000000000000000000"; var buff = new AbiDecodeBuffer(encodedStr, "string"); DecoderFactory.Decode("string", ref buff, out string result); Assert.Equal(0, buff.HeadCursor.Length); Assert.Equal("utf8; 4 bytes: 𠾴; 3 bytes: ⏰ works!", result); }
public void String() { var encodedStr = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000"; var buff = new AbiDecodeBuffer(encodedStr, "bool"); DecoderFactory.Decode("string", ref buff, out string result); Assert.Equal(0, buff.HeadCursor.Length); Assert.Equal("Hello, world!", result); }
public void Address() { var encodedAddr = "00000000000000000000000011f4d0a3c12e86b4b5f39b213f7e19d048276dae"; var buff = new AbiDecodeBuffer(encodedAddr, "address"); DecoderFactory.Decode("address", ref buff, out Address address); Assert.Equal(0, buff.HeadCursor.Length); Assert.Equal("0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe".ToLowerInvariant(), address.ToString()); }
public void Boolean_False() { var encodedFalse = "0000000000000000000000000000000000000000000000000000000000000000"; var buff = new AbiDecodeBuffer(encodedFalse, "bool"); DecoderFactory.Decode("bool", ref buff, out bool decodedFalse); Assert.Equal(0, buff.HeadCursor.Length); Assert.False(decodedFalse); }
public void Int64FixedArray() { var encodedArr = "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000011c20000000000000000000000000000000000000000000000007fffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffff"; var buff = new AbiDecodeBuffer(encodedArr, "int64[5]"); DecoderFactory.Decode("int64[5]", ref buff, out long[] result, EncoderFactory.LoadEncoder("int64", default(long))); Assert.Equal(0, buff.HeadCursor.Length); long[] expected = new long[] { 1, 4546, long.MaxValue, 0, long.MaxValue }; Assert.Equal(expected, result); }
public void UInt8FixedArray() { var encodedArr = "00000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000e70000000000000000000000000000000000000000000000000000000000000046"; var buff = new AbiDecodeBuffer(encodedArr, "uint8[5]"); DecoderFactory.Decode("uint8[5]", ref buff, out byte[] result, EncoderFactory.LoadEncoder("uint8", default(byte))); Assert.Equal(0, buff.HeadCursor.Length); byte[] expected = HexUtil.HexToBytes("072696e746"); Assert.Equal(expected, result); }
public void UInt32() { var encodedNum = "00000000000000000000000000000000000000000000000000000000ffff5544"; var buff = new AbiDecodeBuffer(encodedNum, "uint32"); DecoderFactory.Decode("uint32", ref buff, out uint result); Assert.Equal(0, buff.HeadCursor.Length); uint expected = 4294923588; Assert.Equal(expected, result); }
public void UInt24() { var encodedNum = "0000000000000000000000000000000000000000000000000000000000005ba0"; var buff = new AbiDecodeBuffer(encodedNum, "uint24"); DecoderFactory.Decode("uint24", ref buff, out uint result); Assert.Equal(0, buff.HeadCursor.Length); uint expected = 23456; Assert.Equal(expected, result); }
public void Int56() { var encodedNum = "00000000000000000000000000000000000000000000000000ffffffffffd492"; var buff = new AbiDecodeBuffer(encodedNum, "int56"); DecoderFactory.Decode("int56", ref buff, out long result); Assert.Equal(0, buff.HeadCursor.Length); var expected = (long)-11118; Assert.Equal(expected, result); }
public void Bytes_M() { var encodedBytes22 = "072696e74657220746f6f6b20612067616c6c657920600000000000000000000"; var buff = new AbiDecodeBuffer(encodedBytes22, "bytes22"); DecoderFactory.Decode("bytes22", ref buff, out byte[] result); Assert.Equal(0, buff.HeadCursor.Length); byte[] expected = HexUtil.HexToBytes("072696e74657220746f6f6b20612067616c6c6579206"); Assert.Equal(expected, result); }
public void Bytes() { var encodedBytes = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003d207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970000000"; var buff = new AbiDecodeBuffer(encodedBytes, "bytes"); DecoderFactory.Decode("bytes", ref buff, out byte[] result); Assert.Equal(0, buff.HeadCursor.Length); byte[] expected = "207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970".HexToBytes(); Assert.Equal(expected, result); }
public override void Decode(ref AbiDecodeBuffer buff, out Address val) { #if ZERO_BYTE_CHECKS // data validity check: 20 address bytes should be left-padded with 12 zero-bytes if (!buff.HeadCursor.Slice(0, 12).SequenceEqual(ZEROx12)) { throw new ArgumentException("Invalid address input data; should be 20 address bytes, left-padded with 12 zero-bytes; received: " + buff.HeadCursor.Slice(0, UInt256.SIZE).ToHexString()); } #endif val = MemoryMarshal.Read <Address>(buff.HeadCursor.Slice(12)); buff.IncrementHeadCursor(UInt256.SIZE); }
public void DecodeObject(ref AbiDecodeBuffer buff, out object val) { var items = new object[TypeInfo.ArrayLength]; for (var i = 0; i < items.Length; i++) { _itemEncoder.DecodeObject(ref buff, out var item); items[i] = item; } val = items; }
public override void Decode(ref AbiDecodeBuffer buff, out IEnumerable <TItem> val) { var items = new TItem[_info.ArrayLength]; for (var i = 0; i < items.Length; i++) { _itemEncoder.Decode(ref buff, out var item); items[i] = item; } val = items; }
public void Boolean_BadInput_2() { var encodedTrue = "0000000000000000000000000000000000000000000000000000000000000002"; var buff = new AbiDecodeBuffer(encodedTrue, "bool"); try { DecoderFactory.Decode("bool", ref buff, out bool val); throw null; } catch (ArgumentException) { } }
public void Bytes_BadInput_BadLengthPrefix() { var encodedBytes = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000010000000000000000000003d207072696e74657220746f6f6b20612067616c6c6579206f66207479706520616e6420736372616d626c656420697420746f206d616b65206120747970000000"; var buff = new AbiDecodeBuffer(encodedBytes, "bytes"); try { DecoderFactory.Decode("bytes", ref buff, out byte[] result); throw null; } catch (ArgumentException) { } catch (OverflowException) { } }
public void String_BadInput_BadLengthPrefix() { var encodedBytes = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000060000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000"; var buff = new AbiDecodeBuffer(encodedBytes, "bytes"); try { DecoderFactory.Decode("bytes", ref buff, out byte[] result); throw null; } catch (ArgumentException) { } catch (OverflowException) { } }
public void Decode(ref AbiDecodeBuffer buff, out TItem[] val) { if (_info.ArrayDimensionSizes.Length != 1) { throw new NotImplementedException(); } var items = new TItem[_info.ArrayDimensionSizes[0]]; for (var i = 0; i < items.Length; i++) { _itemEncoder.Decode(ref buff, out var item); items[i] = item; } val = items; }
public HelloEvent(Meadow.JsonRpc.Types.FilterLogObject log) : base(log) { // Decode the log topic args. Span <byte> topicBytes = MemoryMarshal.AsBytes(new Span <Meadow.Core.EthTypes.Data>(log.Topics).Slice(1)); AbiTypeInfo[] topicTypes = Array.Empty <AbiTypeInfo>(); var topicBuff = new AbiDecodeBuffer(topicBytes, topicTypes); // Decode the log data args. Span <byte> dataBytes = log.Data; AbiTypeInfo[] dataTypes = new AbiTypeInfo[] { "string", "address" }; var dataBuff = new AbiDecodeBuffer(dataBytes, dataTypes); DecoderFactory.Decode(dataTypes[0], ref dataBuff, out _message); DecoderFactory.Decode(dataTypes[1], ref dataBuff, out _sender); // Add all the log args and their metadata to a collection that can be checked at runtime. LogArgs = new(string Name, string Type, bool Indexed, object Value)[] { ("_message", "string", false, _message), ("_sender", "address", false, _sender) };
public Transfer(Meadow.JsonRpc.Types.FilterLogObject log) : base(log) { // Decode the log topic args. Span <byte> topicBytes = MemoryMarshal.AsBytes(new Span <Meadow.Core.EthTypes.Data>(log.Topics).Slice(1)); AbiTypeInfo[] topicTypes = new AbiTypeInfo[] { "address", "address" }; var topicBuff = new AbiDecodeBuffer(topicBytes, topicTypes); DecoderFactory.Decode(topicTypes[0], ref topicBuff, out from); DecoderFactory.Decode(topicTypes[1], ref topicBuff, out to); // Decode the log data args. Span <byte> dataBytes = log.Data; AbiTypeInfo[] dataTypes = new AbiTypeInfo[] { "uint256" }; var dataBuff = new AbiDecodeBuffer(dataBytes, dataTypes); DecoderFactory.Decode(dataTypes[0], ref dataBuff, out tokens); // Add all the log args and their metadata to a collection that can be checked at runtime. LogArgs = new(string Name, string Type, bool Indexed, object Value)[] { ("from", "address", true, from), ("to", "address", true, to), ("tokens", "uint256", false, tokens) };
public void FunctionData_MultipleStringParams() { var strP1 = "first string"; var strP2 = "asdf"; var strP3 = "utf8; 4 bytes: 𠾴; 3 bytes: ⏰ works!"; var encoded = "000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000c666972737420737472696e670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000461736466000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028757466383b20342062797465733a20f0a0beb43b20332062797465733a20e28fb020776f726b7321000000000000000000000000000000000000000000000000"; AbiDecodeBuffer buff = new AbiDecodeBuffer(encoded, "string", "string", "string"); DecoderFactory.Decode("string", ref buff, out string ru1); Assert.Equal(strP1, ru1); DecoderFactory.Decode("string", ref buff, out string ru2); Assert.Equal(strP2, ru2); DecoderFactory.Decode("string", ref buff, out string ru3); Assert.Equal(strP3, ru3); }
public LogAccess(Meadow.JsonRpc.Types.FilterLogObject log) : base(log) { // Decode the log topic args. Span <byte> topicBytes = MemoryMarshal.AsBytes(new Span <Meadow.Core.EthTypes.Data>(log.Topics).Slice(1)); AbiTypeInfo[] topicTypes = new AbiTypeInfo[] { "address", "uint256" }; var topicBuff = new AbiDecodeBuffer(topicBytes, topicTypes); DecoderFactory.Decode(topicTypes[0], ref topicBuff, out by); DecoderFactory.Decode(topicTypes[1], ref topicBuff, out accessTime); // Decode the log data args. Span <byte> dataBytes = log.Data; AbiTypeInfo[] dataTypes = new AbiTypeInfo[] { "string", "string" }; var dataBuff = new AbiDecodeBuffer(dataBytes, dataTypes); DecoderFactory.Decode(dataTypes[0], ref dataBuff, out method); DecoderFactory.Decode(dataTypes[1], ref dataBuff, out desc); // Add all the log args and their metadata to a collection that can be checked at runtime. LogArgs = new(string Name, string Type, bool Indexed, object Value)[] { ("by", "address", true, by), ("accessTime", "uint256", true, accessTime), ("method", "string", false, method), ("desc", "string", false, desc) };
public override void Decode(ref AbiDecodeBuffer buff, out IEnumerable <byte> val) { var uintEncoder = UInt256Encoder.UncheckedEncoders.Get(); try { // Read the next header int which is the offset to the start of the data // in the data payload area. uintEncoder.Decode(buff.HeadCursor, out int startingPosition); // The first int in our offset of data area is the length of the rest of the payload. var encodedLength = buff.Buffer.Slice(startingPosition, UInt256.SIZE); uintEncoder.Decode(encodedLength, out int byteLen); // Read the actual payload from the data area var payloadOffset = startingPosition + UInt256.SIZE; var payload = buff.Buffer.Slice(payloadOffset, byteLen); var bytes = payload.ToArray(); int bodyLen = PadLength(bytes.Length, UInt256.SIZE); val = bytes; #if ZERO_BYTE_CHECKS // data validity check: should be right-padded with zero bytes for (var i = payloadOffset + byteLen; i < payloadOffset + bodyLen; i++) { if (buff.Buffer[i] != 0) { throw new ArgumentException($"Invalid bytes input data; should be {bytes.Length} bytes of data followed by {bodyLen - bytes.Length} zero-bytes"); } } #endif buff.IncrementHeadCursor(UInt256.SIZE); } finally { UInt256Encoder.UncheckedEncoders.Put(uintEncoder); } }
public override void Decode(ref AbiDecodeBuffer buff, out IEnumerable <byte> val) { var bytes = new byte[_info.ArrayLength]; for (var i = 0; i < bytes.Length; i++) { bytes[i] = buff.HeadCursor[i]; } #if ZERO_BYTE_CHECKS // data validity check: all bytes after the fixed M amount should be zero for (var i = bytes.Length; i < UInt256.SIZE; i++) { if (buff.HeadCursor[i] != 0) { throw new ArgumentException($"Invalid {_info.SolidityName} input data; should be {_info.ArrayLength} bytes padded {UInt256.SIZE - _info.ArrayLength} zero-bytes; received: " + buff.HeadCursor.Slice(0, 32).ToHexString()); } } #endif val = bytes; buff.IncrementHeadCursor(UInt256.SIZE); }
public void Int56Random() { var rand = new Random(); var int56Encoder = EncoderFactory.LoadEncoder("int56", default(long)); for (var i = 0; i < 50_000; i++) { byte[] num = new byte[32]; Span <byte> bytes = num; Span <long> view = MemoryMarshal.Cast <byte, long>(bytes); byte[] tmp = new byte[7]; rand.NextBytes(tmp); tmp.CopyTo(num, 25); var buff = new AbiDecodeBuffer(bytes, "int56"); int56Encoder.Decode(ref buff, out var result); Span <byte> resultBuff = new byte[32]; var abiEncodeBuff = new AbiEncodeBuffer(resultBuff, "int56"); int56Encoder.SetValue(result); int56Encoder.Encode(ref abiEncodeBuff); Assert.Equal(bytes.Slice(25).ToHexString(), resultBuff.Slice(25).ToHexString()); } }
public void DecodeObject(ref AbiDecodeBuffer buffer, out object result) { // If we have no elements, no work needs to be done. if (TypeInfo.ArrayDimensionSizes.Length == 0) { result = Array.CreateInstance(TypeInfo.ArrayItemInfo.ClrType, 0); return; } // Create our initial array. var items = (Array)ArrayExtensions.CreateJaggedArray(TypeInfo.ArrayItemInfo.ClrType, TypeInfo.ArrayDimensionSizes); // Create a variable to track our position. int[] decodingPosition = new int[TypeInfo.ArrayDimensionSizes.Length]; // Loop for each element to index. bool reachedEnd = false; while (!reachedEnd) { // Define the parent array to resolve for this element. Array innerMostArray = items; // Increment our decoding position. bool incrementing = true; for (int x = 0; x < decodingPosition.Length; x++) { // If this isn't the final index (inner most array index), then it's an index to another array. if (x < decodingPosition.Length - 1) { innerMostArray = (Array)innerMostArray.GetValue(decodingPosition[x]); } else { // We've resolved the element to index. _itemEncoder.DecodeObject(ref buffer, out var item); innerMostArray.SetValue(item, decodingPosition[x]); } // Increment the index for this dimension if (incrementing) { // Increment our position. decodingPosition[x]++; // Determine if we need to carry a digit. if (decodingPosition[x] >= TypeInfo.ArrayDimensionSizes[x]) { // Reset the digit, we will carry over to the next. decodingPosition[x] = 0; } else { incrementing = false; } } } // If we incremented all digits and still have increment flag set, we overflowed our last element, so we reached the end reachedEnd = incrementing; } // Set our result result = items; }