Пример #1
0
        private static byte[] ComputeAddress(AbiSignature signature)
        {
            string[] argTypeNames = new string[signature.Types.Length];
            for (int i = 0; i < signature.Types.Length; i++)
            {
                argTypeNames[i] = signature.Types[i].ToString();
            }

            string typeList        = string.Join(",", argTypeNames);
            string signatureString = $"{signature.Name}({typeList})";
            Keccak signatureKeccak = Keccak.Compute(signatureString);

            return(signatureKeccak.Bytes.Slice(0, 4));
        }
Пример #2
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));
        }
Пример #3
0
        public object[] Decode(AbiSignature signature, byte[] data)
        {
            string[] argTypeNames = new string[signature.Types.Length];
            for (int i = 0; i < signature.Types.Length; i++)
            {
                argTypeNames[i] = signature.Types[i].ToString();
            }

            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)}");
            }

            int 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.UInt.DecodeUInt(data, position);
                    (arguments[i], dynamicPosition)       = type.Decode(data, 4 + (int)offset);
                    position = nextPosition;
                }
                else
                {
                    (arguments[i], position) = type.Decode(data, position);
                }
            }

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

            return(arguments);
        }
Пример #4
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));
        }