Module: Eth::Abi::Encoder

Extended by:
Encoder
Included in:
Encoder
Defined in:
lib/eth/abi/encoder.rb

Overview

Provides a utility module to assist encoding ABIs.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.primitive_type(type, arg) ⇒ String

Encodes primitive types.

Parameters:

  • type (Eth::Abi::Type)

    type to be encoded.

  • arg (String|Number)

    value to be encoded.

Returns:

  • (String)

    the encoded primitive type.

Raises:

  • (EncodingError)

    if value does not match type.

  • (ValueOutOfBounds)

    if value is out of bounds for type.

  • (ArgumentError)

    if encoding fails for type.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/eth/abi/encoder.rb', line 87

def primitive_type(type, arg)
  case type.base_type
  when "uint"
    uint arg, type
  when "int"
    int arg, type
  when "bool"
    bool arg
  when "ureal", "ufixed"
    ufixed arg, type
  when "real", "fixed"
    fixed arg, type
  when "string", "bytes"
    bytes arg, type
  when "tuple"
    tuple arg, type
  when "hash"
    hash arg, type
  when "address"
    address arg
  else
    raise EncodingError, "Unhandled type: #{type.base_type} #{type.sub_type}"
  end
end

.type(type, arg) ⇒ String

Encodes a specific value, either static or dynamic.

Parameters:

  • type (Eth::Abi::Type)

    type to be encoded.

  • arg (String|Number)

    value to be encoded.

Returns:

  • (String)

    the encoded type.

Raises:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/eth/abi/encoder.rb', line 34

def type(type, arg)
  if %w(string bytes).include? type.base_type and type.sub_type.empty? and type.dimensions.empty?
    raise EncodingError, "Argument must be a String" unless arg.instance_of? String
    arg = handle_hex_string arg, type

    # encodes strings and bytes
    size = type Type.size_type, arg.size
    padding = Constant::BYTE_ZERO * (Util.ceil32(arg.size) - arg.size)
    "#{size}#{arg}#{padding}"
  elsif type.base_type == "tuple" && type.dimensions.size == 1 && type.dimensions[0] != 0
    result = ""
    result += struct_offsets(type.nested_sub, arg)
    result += arg.map { |x| type(type.nested_sub, x) }.join
    result
  elsif type.dynamic? && !type.dimensions.empty? && arg.is_a?(Array)

    # encodes dynamic-sized arrays
    head = type(Type.size_type, arg.size)
    nested_sub = type.nested_sub

    if nested_sub.dynamic?
      tails = arg.map { |a| type(nested_sub, a) }
      offset = arg.size * 32
      tails.each do |t|
        head += type(Type.size_type, offset)
        offset += t.size
      end
      head + tails.join
    else
      arg.each { |a| head += type(nested_sub, a) }
      head
    end
  else
    if type.dimensions.empty?

      # encode a primitive type
      primitive_type type, arg
    else

      # encode static-size arrays
      arg.map { |x| type(type.nested_sub, x) }.join
    end
  end
end

Instance Method Details

#primitive_type(type, arg) ⇒ String

Encodes primitive types.

Parameters:

  • type (Eth::Abi::Type)

    type to be encoded.

  • arg (String|Number)

    value to be encoded.

Returns:

  • (String)

    the encoded primitive type.

Raises:

  • (EncodingError)

    if value does not match type.

  • (ValueOutOfBounds)

    if value is out of bounds for type.

  • (ArgumentError)

    if encoding fails for type.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/eth/abi/encoder.rb', line 87

def primitive_type(type, arg)
  case type.base_type
  when "uint"
    uint arg, type
  when "int"
    int arg, type
  when "bool"
    bool arg
  when "ureal", "ufixed"
    ufixed arg, type
  when "real", "fixed"
    fixed arg, type
  when "string", "bytes"
    bytes arg, type
  when "tuple"
    tuple arg, type
  when "hash"
    hash arg, type
  when "address"
    address arg
  else
    raise EncodingError, "Unhandled type: #{type.base_type} #{type.sub_type}"
  end
end

#type(type, arg) ⇒ String

Encodes a specific value, either static or dynamic.

Parameters:

  • type (Eth::Abi::Type)

    type to be encoded.

  • arg (String|Number)

    value to be encoded.

Returns:

  • (String)

    the encoded type.

Raises:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/eth/abi/encoder.rb', line 34

def type(type, arg)
  if %w(string bytes).include? type.base_type and type.sub_type.empty? and type.dimensions.empty?
    raise EncodingError, "Argument must be a String" unless arg.instance_of? String
    arg = handle_hex_string arg, type

    # encodes strings and bytes
    size = type Type.size_type, arg.size
    padding = Constant::BYTE_ZERO * (Util.ceil32(arg.size) - arg.size)
    "#{size}#{arg}#{padding}"
  elsif type.base_type == "tuple" && type.dimensions.size == 1 && type.dimensions[0] != 0
    result = ""
    result += struct_offsets(type.nested_sub, arg)
    result += arg.map { |x| type(type.nested_sub, x) }.join
    result
  elsif type.dynamic? && !type.dimensions.empty? && arg.is_a?(Array)

    # encodes dynamic-sized arrays
    head = type(Type.size_type, arg.size)
    nested_sub = type.nested_sub

    if nested_sub.dynamic?
      tails = arg.map { |a| type(nested_sub, a) }
      offset = arg.size * 32
      tails.each do |t|
        head += type(Type.size_type, offset)
        offset += t.size
      end
      head + tails.join
    else
      arg.each { |a| head += type(nested_sub, a) }
      head
    end
  else
    if type.dimensions.empty?

      # encode a primitive type
      primitive_type type, arg
    else

      # encode static-size arrays
      arg.map { |x| type(type.nested_sub, x) }.join
    end
  end
end