Class: Eth::Abi::Type

Inherits:
Object
  • Object
show all
Defined in:
lib/eth/abi/type.rb

Overview

Provides a class to handle and parse common ABI types.

Defined Under Namespace

Classes: ParseError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_type, sub_type, dimensions, components = nil, component_name = nil) ⇒ Eth::Abi::Type

Create a new Type object for base types, sub types, and dimensions. Should not be used; use #parse instead.

Parameters:

  • base_type (String)

    the base-type attribute.

  • sub_type (String)

    the sub-type attribute.

  • dimensions (Array)

    the dimension attribute.

  • components (Array) (defaults to: nil)

    the components attribute.

  • component_name (String) (defaults to: nil)

    the tuple component’s name.



53
54
55
56
57
58
59
60
# File 'lib/eth/abi/type.rb', line 53

def initialize(base_type, sub_type, dimensions, components = nil, component_name = nil)
  sub_type = sub_type.to_s
  @base_type = base_type
  @sub_type = sub_type
  @dimensions = dimensions
  @components = components
  @name = component_name
end

Instance Attribute Details

#base_typeObject (readonly)

The base attribute, e.g., string or bytes.



30
31
32
# File 'lib/eth/abi/type.rb', line 30

def base_type
  @base_type
end

#componentsObject (readonly)

The components of a tuple type.



39
40
41
# File 'lib/eth/abi/type.rb', line 39

def components
  @components
end

#dimensionsObject (readonly)

The dimension attribute, e.g., [10] for an array of size 10.



36
37
38
# File 'lib/eth/abi/type.rb', line 36

def dimensions
  @dimensions
end

#nameObject (readonly)

The name of tuple component.



42
43
44
# File 'lib/eth/abi/type.rb', line 42

def name
  @name
end

#sub_typeObject (readonly)

The sub-type attribute, e.g., 256 as size of an uint256.



33
34
35
# File 'lib/eth/abi/type.rb', line 33

def sub_type
  @sub_type
end

Class Method Details

.size_typeEth::Abi::Type

Creates a new uint256 type used for size.

Returns:



104
105
106
# File 'lib/eth/abi/type.rb', line 104

def self.size_type
  @size_type ||= new("uint", 256, [])
end

Instance Method Details

#==(another_type) ⇒ Boolean

Compares two types for their attributes.

Parameters:

Returns:

  • (Boolean)

    true if all attributes match.



112
113
114
115
116
# File 'lib/eth/abi/type.rb', line 112

def ==(another_type)
  base_type == another_type.base_type and
    sub_type == another_type.sub_type and
    dimensions == another_type.dimensions
end

#dynamic?Boolean

Helpes to determine whether array is of dynamic size.

Returns:

  • (Boolean)

    true if array is of dynamic size.



138
139
140
# File 'lib/eth/abi/type.rb', line 138

def dynamic?
  size.nil?
end

#nested_subEth::Abi::Type

Types can have nested sub-types in arrays.

Returns:



145
146
147
# File 'lib/eth/abi/type.rb', line 145

def nested_sub
  @nested_sub ||= self.class.new(base_type, sub_type, dimensions[0...-1], components, name)
end

#parse(type, components = nil, component_name = nil) ⇒ Eth::Abi::Type

Attempts to parse a string containing a common Solidity type. Creates a new Type upon success (using konstructor).

Parameters:

  • type (String)

    a common Solidity type.

  • components (Array) (defaults to: nil)

    the components attribute.

  • component_name (String) (defaults to: nil)

    the tuple component’s name.

Returns:

Raises:



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/eth/abi/type.rb', line 73

def parse(type, components = nil, component_name = nil)
  if type.is_a?(Type)
    @base_type = type.base_type
    @sub_type = type.sub_type
    @dimensions = type.dimensions
    @components = type.components
    @name = type.name
    return
  end

  _, base_type, sub_type, dimension = /([a-z]*)([0-9]*x?[0-9]*)((\[[0-9]*\])*)/.match(type).to_a

  # type dimension can only be numeric
  dims = dimension.scan(/\[[0-9]*\]/)
  raise ParseError, "Unknown characters found in array declaration" if dims.join != dimension

  # enforce base types
  validate_base_type base_type, sub_type

  # return a new Type (using konstructor)
  sub_type = sub_type.to_s
  @base_type = base_type
  @sub_type = sub_type
  @dimensions = dims.map { |x| x[1...-1].to_i }
  @components = components.map { |component| Abi::Type.parse(component["type"], component.dig("components"), component.dig("name")) } if components&.any?
  @name = component_name
end

#sizeInteger

Computes the size of a type if possible.

Returns:

  • (Integer)

    the size of the type; or nil if not available.



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/eth/abi/type.rb', line 121

def size
  s = nil
  if dimensions.empty?
    if !(["string", "bytes", "tuple"].include?(base_type) and sub_type.empty?)
      s = 32
    elsif base_type == "tuple" and components.none?(&:dynamic?)
      s = components.sum(&:size)
    end
  elsif dimensions.last != 0 and !nested_sub.dynamic?
    s = dimensions.last * nested_sub.size
  end
  @size ||= s
end

#to_sString

Allows exporting the type as string.

Returns:

  • (String)

    the type string.



152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/eth/abi/type.rb', line 152

def to_s
  if base_type == "tuple"
    "(" + components.map(&:to_s).join(",") + ")" + (dimensions.size > 0 ? dimensions.map { |x| "[#{x == 0 ? "" : x}]" }.join : "")
  elsif dimensions.empty?
    if %w[string bytes].include?(base_type) and sub_type.empty?
      base_type
    else
      "#{base_type}#{sub_type}"
    end
  else
    "#{base_type}#{sub_type}#{dimensions.map { |x| "[#{x == 0 ? "" : x}]" }.join}"
  end
end