def encode_type(type, arg)
      if %w(string bytes).include?(type.base) && type.sub.empty?
        raise ArgumentError, "arg must be a string" unless arg.instance_of?(String)

        size = encode_type Type.size_type, arg.size
        padding = BYTE_ZERO * (Utils.ceil32(arg.size) - arg.size)

        "#{size}#{arg}#{padding}"
      elsif type.dynamic?
        raise ArgumentError, "arg must be an array" unless arg.instance_of?(Array)

        head, tail = '', ''
        if type.dims.last == 0
          head += encode_type(Type.size_type, arg.size)
        else
          raise ArgumentError, "Wrong array size: found #{arg.size}, expecting #{type.dims.last}" unless arg.size == type.dims.last
        end

        sub_type = type.subtype
        sub_size = type.subtype.size
        arg.size.times do |i|
          if sub_size.nil?
            head += encode_type(Type.size_type, 32*arg.size + tail.size)
            tail += encode_type(sub_type, arg[i])
          else
            head += encode_type(sub_type, arg[i])
          end
        end

        "#{head}#{tail}"
      else # static type
        if type.dims.empty?
          encode_primitive_type type, arg
        else
          arg.map {|x| encode_type(type.subtype, x) }.join
        end
      end
    end
def encode_type(type, arg)
      if %w(string bytes).include?(type.base) && type.sub.empty?
        raise ArgumentError, "arg must be a string" unless arg.instance_of?(String)

        size = encode_type Type.size_type, arg.size
        padding = BYTE_ZERO * (Utils.ceil32(arg.size) - arg.size)

        "#{size}#{arg}#{padding}"
      elsif type.dynamic?
        raise ArgumentError, "arg must be an array" unless arg.instance_of?(Array)

        head, tail = '', ''
        if type.dims.last == 0
          head += encode_type(Type.size_type, arg.size)
        else
          raise ArgumentError, "Wrong array size: found #{arg.size}, expecting #{type.dims.last}" unless arg.size == type.dims.last
        end

        sub_type = type.subtype
        sub_size = type.subtype.size
        arg.size.times do |i|
          if sub_size.nil?
            head += encode_type(Type.size_type, 32*arg.size + tail.size)
            tail += encode_type(sub_type, arg[i])
          else
            head += encode_type(sub_type, arg[i])
          end
        end

        "#{head}#{tail}"
      else # static type
        if type.dims.empty?
          encode_primitive_type type, arg
        else
          arg.map {|x| encode_type(type.subtype, x) }.join
        end
      end
    end
Encodes a single value (static or dynamic).

 @param type [Ethereum::ABI::Type] value type
 @param arg [Object] value

 @return [String] encoded bytes