abiparser 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77899a7da00b8be7b61c97d2f1ebad297a6d33f74bd081c59b17f8b66bca78f1
4
- data.tar.gz: 15a102dc8505eb359fcb5d117de026e9308641e714ea50096895ee15fb4d655e
3
+ metadata.gz: 9f938a2858e7da14cc5a8b42f4691a93c4721cef9e271168de78535c64f70115
4
+ data.tar.gz: 8450885be9f443548be957d0815bb31e3c56862f0368eb17f574ab176ea9e4b0
5
5
  SHA512:
6
- metadata.gz: 2bf5a3d5928df6f9d5a650f50ca05df22edb82f0d305a5ef66c552b36fee9b33d6166b63dfd4e878c8a32f7a86e042517159cc6b0155cf96734b36a0ab596817
7
- data.tar.gz: 8181ddd11ad89481204f1796ef4eebc854d10ec83fb8cd6d3fd45ce8da830cff2fd1273c726c507853843442c174c603bd66fcb735ae4aabf433141827befebb
6
+ metadata.gz: bc52799f38979a1e8b77b21d711e0ff935510ce7988bdec34e5ad0a09a5dde8db522df3038808f165dcd4178051ef49f7f832d1b76fc9fac0ef5c4f3331fd92b
7
+ data.tar.gz: 6a6d1e03041d70e7080c38ad3e534c5e57a0cd49af187c4a16dfe1f19ae7fa55d4c8a3068b12968dd64a3d23f3c08c8f4c5fd47ac96e83f9bc7da695e0dfef7b
data/Manifest.txt CHANGED
@@ -7,5 +7,7 @@ lib/abiparser/constructor.rb
7
7
  lib/abiparser/contract.rb
8
8
  lib/abiparser/export/interface.rb
9
9
  lib/abiparser/function.rb
10
+ lib/abiparser/interface.rb
10
11
  lib/abiparser/param.rb
12
+ lib/abiparser/utils.rb
11
13
  lib/abiparser/version.rb
data/README.md CHANGED
@@ -13,6 +13,133 @@ abiparser - application binary interface (abi) parser machinery / helper for Eth
13
13
  ## Usage
14
14
 
15
15
 
16
+ ### Functions Signature Hashes / Selectors & Interface (Type) Ids
17
+
18
+
19
+ You can calculate the function selectors (or "sighash",
20
+ that is, signature hash)
21
+ by hashing the function signature
22
+ e.g. `supportsInterface(bytes4)` with the Keccak 256-Bit algorithm
23
+ and than use the first 4 bytes, that is, `0x01ffc9a7` (out of 32 bytes),
24
+ that is, `0x01ffc9a7a5cef8baa21ed3c5c0d7e23accb804b619e9333b597f47a0d84076e2`. Example:
25
+
26
+
27
+ ``` ruby
28
+ require 'abiparser'
29
+
30
+ sig = 'supportsInterface(bytes4)'
31
+ pp keccak256( sig )[0,4].hexdigest
32
+ #=> "0x01ffc9a7"
33
+ ```
34
+
35
+ Note: The `String#hexdigest` (also known as `String#bin_to_hex`) helper
36
+ converts a binary string (with `BINARY`/`ASCII-8BIT` encoding)
37
+ into a hex(adecimal) string.
38
+
39
+
40
+ You can calcuate interface (type) ids
41
+ by xor-ing (`^`) together the sighashes.
42
+ If the interface only has one function than
43
+ the interface (type) id equals the function sighash (by definition).
44
+
45
+
46
+ ``` solidity
47
+ interface ERC165 {
48
+ /// @notice Query if a contract implements an interface
49
+ /// @param interfaceID The interface identifier, as specified in ERC-165
50
+ /// @dev Interface identification is specified in ERC-165.
51
+ /// @return `true` if the contract implements `interfaceID` and
52
+ /// `interfaceID` is not 0xffffffff, `false` otherwise
53
+ function supportsInterface(bytes4 interfaceID) external view returns (bool);
54
+ }
55
+ // The interface identifier for this interface is 0x01ffc9a7.
56
+ ```
57
+
58
+ If you check the sighash for `supportsInterface(bytes4)`,
59
+ that is, `0x01ffc9a7` (see above)
60
+ than - bingo! - the interface id for ERC165 matches up.
61
+
62
+
63
+ Let's try to calculate the ERC20 standard (fungible) token interface
64
+ where the official id is `0x36372b07` by xor-ing (`^`) together all function sighashes:
65
+
66
+ ``` ruby
67
+ pp (keccak256('totalSupply()')[0,4] ^
68
+ keccak256('balanceOf(address)')[0,4] ^
69
+ keccak256('allowance(address,address)')[0,4] ^
70
+ keccak256('transfer(address,uint256)')[0,4] ^
71
+ keccak256('approve(address,uint256)')[0,4] ^
72
+ keccak256('transferFrom(address,address,uint256)')[0,4]).hexdigest
73
+ #=> "0x36372b07"
74
+
75
+ # or where def sig(bin) = keccak256(bin)[0,4])
76
+
77
+ pp (sig('totalSupply()') ^
78
+ sig('balanceOf(address)') ^
79
+ sig('allowance(address,address)') ^
80
+ sig('transfer(address,uint256)') ^
81
+ sig('approve(address,uint256)') ^
82
+ sig('transferFrom(address,address,uint256)')).hexdigest
83
+ #=> "0x36372b07"
84
+ ```
85
+
86
+ Voila!
87
+ Or re(use) the builtin pre-defined interfaces. Example:
88
+
89
+ ``` ruby
90
+ pp IERC165.inteface_id #=> "0x01ffc9a7"
91
+ pp IERC20.interface_id #=> "0x36372b07"
92
+ pp IERC721.interface_id #=> "0x80ac58cd"
93
+ pp IERC721_METADATA.interface_id #=> "0x5b5e139f"
94
+ pp IERC721_ENUMERABLE.interface_id #=> "0x780e9d63"
95
+ ```
96
+
97
+ Yes, you can. Define your own interface. Let's have a looksie
98
+ at the built-ins. Example:
99
+
100
+ ``` ruby
101
+ IERC165 = ABI::Interface.new(
102
+ 'supportsInterface(bytes4)'
103
+ )
104
+
105
+ IERC20 = ABI::Interface.new(
106
+ 'totalSupply()',
107
+ 'balanceOf(address)',
108
+ 'allowance(address,address)',
109
+ 'transfer(address,uint256)',
110
+ 'approve(address,uint256)',
111
+ 'transferFrom(address,address,uint256)'
112
+ )
113
+
114
+ IERC721 = ABI::Interface.new(
115
+ 'balanceOf(address)',
116
+ 'ownerOf(uint256)',
117
+ 'approve(address,uint256)',
118
+ 'getApproved(uint256)',
119
+ 'setApprovalForAll(address,bool)',
120
+ 'isApprovedForAll(address,address)',
121
+ 'transferFrom(address,address,uint256)',
122
+ 'safeTransferFrom(address,address,uint256)',
123
+ 'safeTransferFrom(address,address,uint256,bytes)' )
124
+
125
+ IERC721_METADATA = ABI::Interface.new(
126
+ 'name()',
127
+ 'symbol()',
128
+ 'tokenURI(uint256)' )
129
+
130
+ IERC721_ENUMERABLE = ABI::Interface.new(
131
+ 'tokenOfOwnerByIndex(address,uint256)',
132
+ 'totalSupply()',
133
+ 'tokenByIndex(uint256)' )
134
+
135
+ ...
136
+ ```
137
+
138
+
139
+ To be continued...
140
+
141
+
142
+
16
143
 
17
144
 
18
145
  ## License
data/Rakefile CHANGED
@@ -22,6 +22,7 @@ Hoe.spec 'abiparser' do
22
22
  ['cocos'],
23
23
  ['bytes'],
24
24
  ['digest-lite'],
25
+ ['abicoder'],
25
26
  ]
26
27
 
27
28
  self.licenses = ['Public Domain']
@@ -47,14 +47,20 @@ class Constructor
47
47
  end
48
48
 
49
49
 
50
- attr_reader :inputs
50
+ attr_reader :inputs, :input_types
51
51
 
52
52
  def initialize( inputs: [],
53
53
  payable: false )
54
54
  @inputs = inputs
55
55
  @payable = payable
56
+
57
+ ## parse inputs into types
58
+ ## note: use "calculated" sig(nature) and NOT the type
59
+ ## (differs for tuples, that is, types with components !!!)
60
+ @input_types = @inputs.map {|param| Type.parse( param.sig ) }
56
61
  end
57
62
 
63
+
58
64
  ## add - why? why not?
59
65
  ## def constant?() false; end
60
66
  ## alias_method :readonly?, :constant?
@@ -74,7 +80,7 @@ class Constructor
74
80
  buf << "(#{buf2.join(',')})"
75
81
  end
76
82
  buf
77
- end
83
+ end
78
84
 
79
85
 
80
86
  def doc
@@ -98,9 +104,7 @@ class Constructor
98
104
  end
99
105
  buf << ";"
100
106
  buf
101
- end
102
-
103
-
107
+ end
104
108
 
105
109
 
106
110
  end # class Constructor
@@ -63,8 +63,37 @@ class Contract
63
63
  @events = events
64
64
  @has_receive = has_receive
65
65
  @has_fallback = has_fallback
66
+
67
+ @selectors = {}
68
+
69
+ ## auto-add selectors (hashed signatures)
70
+ @funcs.each do |func|
71
+ sighash = func.sighash
72
+ puts "0x#{sighash} => #{func.sig}"
73
+
74
+ ## assert - no duplicates allowed
75
+ if @selectors[sighash]
76
+ puts "!! ERROR - duplicate function signature #{func.sig}; already in use; sorry"
77
+ exit 1
78
+ end
79
+
80
+ @selectors[sighash] = func
81
+ end
66
82
  end
67
83
 
84
+
85
+ ## return hexstrings of sig(natures) - why? why not?
86
+ ## rename to sighashes - why? why not?
87
+ def selectors() @selectors.keys; end
88
+
89
+
90
+ def support?( sig )
91
+ Utils.support?( @selectors.keys, sig )
92
+ end
93
+ alias_method :supports?, :support? ## add alternate spelling - why? why not?
94
+
95
+
96
+
68
97
  def constructor() @ctor; end
69
98
  def functions() @funcs; end
70
99
 
@@ -6,11 +6,14 @@ class Contract
6
6
  buf = ''
7
7
  buf << "interface #{name} {"
8
8
 
9
- if @ctor
10
- buf << "\n"
11
- buf << "// Constructor\n"
12
- buf << "#{@ctor.decl}\n"
13
- end
9
+
10
+ # include constructor - why? why not?
11
+ #
12
+ # if @ctor
13
+ # buf << "\n"
14
+ # buf << "// Constructor\n"
15
+ # buf << "#{@ctor.decl}\n"
16
+ # end
14
17
 
15
18
  if payable_functions.size > 0
16
19
  buf << "\n"
@@ -7,9 +7,9 @@ class Function
7
7
  inputs = o['inputs'].map {|param| Param.parse( param ) }
8
8
  outputs = o['outputs'].map {|param| Param.parse( param ) }
9
9
 
10
- payable = nil
11
- contant = nil
12
- pure = nil
10
+ payable = nil
11
+ constant = nil
12
+ pure = nil
13
13
 
14
14
  ## old soliditity before v0.6
15
15
  ## newer version uses stateMutability
@@ -54,10 +54,11 @@ class Function
54
54
 
55
55
 
56
56
  attr_reader :name,
57
- :inputs, :outputs
57
+ :inputs, :outputs,
58
+ :input_types, :output_types
58
59
 
59
60
  def initialize( name,
60
- inputs: [],
61
+ inputs: [],
61
62
  outputs: [],
62
63
  payable: false,
63
64
  constant: false,
@@ -65,10 +66,21 @@ class Function
65
66
  @name = name
66
67
  @inputs = inputs
67
68
  @outputs = outputs
68
-
69
69
  @payable = payable
70
70
  @constant = constant
71
71
  @pure = pure
72
+
73
+ ## parse inputs & outputs into types
74
+ ## note: use "calculated" sig(nature) and NOT the type
75
+ ## (differs for tuples, that is, types with components !!!)
76
+ @input_types = @inputs.map do |param|
77
+ Type.parse( param.sig )
78
+ end
79
+ @output_types = @outputs.map do |param|
80
+ ## pp param
81
+ ## puts "sig: #{param.sig}"
82
+ Type.parse( param.sig )
83
+ end
72
84
  end
73
85
 
74
86
 
@@ -92,11 +104,16 @@ class Function
92
104
  buf << "(#{buf2.join(',')})"
93
105
  end
94
106
  buf
95
- end
107
+ end
108
+
109
+ def sighash
110
+ keccak256( sig )[0,4].hexdigest
111
+ end
96
112
 
97
113
 
98
114
  def doc
99
- buf = "function #{@name}"
115
+ ## note: text with markdown formatting
116
+ buf = "function **#{@name}**"
100
117
  if @inputs.empty?
101
118
  buf << "()"
102
119
  else
@@ -134,7 +151,7 @@ class Function
134
151
  end
135
152
  buf << ";"
136
153
  buf
137
- end
154
+ end
138
155
 
139
156
 
140
157
  def types
@@ -0,0 +1,59 @@
1
+
2
+ module ABI
3
+
4
+
5
+ ## rename to QueryInterface or SupportInterface
6
+ ## or InterfaceType or InterfaceId or such - why? why not?
7
+ class Interface
8
+
9
+ attr_reader :interface_id
10
+
11
+
12
+ ##
13
+ ## todo/fix: make sure full function defs get passed in (not only sigs!!!)
14
+ def initialize( *functions )
15
+ @functions = functions
16
+ @selectors = {}
17
+
18
+ @functions.each do |func|
19
+ sig = func
20
+ sighash = keccak256( sig )[0,4].hexdigest
21
+ puts "0x#{sighash} => #{sig}"
22
+
23
+ ## assert - no duplicates allowed
24
+ if @selectors[sighash]
25
+ puts "!! ERROR - duplicate function signature #{sig}; already in use; sorry"
26
+ exit 1
27
+ end
28
+
29
+ @selectors[sighash] = sig
30
+ end
31
+ @interface_id = calc_interface_id
32
+ end
33
+
34
+
35
+ def calc_interface_id
36
+ interface_id = nil
37
+ @selectors.each do |sighash,_|
38
+ sighash = sighash.hex_to_bin ## note: convert to binary string (from hexstring)!!
39
+ interface_id = if interface_id.nil?
40
+ sighash ## init with sighash
41
+ else
42
+ interface_id ^ sighash ## use xor
43
+ end
44
+ end
45
+ interface_id.hexdigest
46
+ end
47
+
48
+
49
+ ## return hexstrings of sig(natures) - why? why not?
50
+ ## rename to sighashes - why? why not?
51
+ def selectors() @selectors.keys; end
52
+
53
+ def support?( sig )
54
+ Utils.support?( @selectors.keys, sig )
55
+ end
56
+ alias_method :supports?, :support? ## add alternate spelling - why? why not?
57
+
58
+ end ## class Interface
59
+ end # module ABI
@@ -1,36 +1,78 @@
1
1
  module ABI
2
2
  class Param
3
-
4
- attr_reader :type, :name
3
+ attr_reader :type, :name,
4
+ :internal_type,
5
+ :components
5
6
 
6
7
  def self.parse( o )
7
- type = o['type']
8
- name = o['name']
9
- new( type, name )
8
+ type = o['type']
9
+ internal_type = o['internalType']
10
+ name = o['name']
11
+ components = o['components'] ? o['components'].map { |c| parse( c ) } : nil
12
+
13
+ new( type, name,
14
+ internal_type: internal_type,
15
+ components: components )
10
16
  end
11
17
 
12
- def initialize( type, name ) ## note: type goes first!!!
13
- @type = type
14
- @name = name
18
+ ### check - find a "better" name for internal_type
19
+ ## use a keyword param - why? why not?
20
+ def initialize( type, name=nil,
21
+ internal_type: nil,
22
+ components: nil ) ## note: type goes first!!!
23
+ @type = type
24
+ ## note: convert empty string "" to nil - why? why not?
25
+ @name = if name && name.empty?
26
+ nil
27
+ else
28
+ name
29
+ end
30
+ @internal_type = if internal_type && internal_type.empty?
31
+ nil
32
+ else
33
+ internal_type
34
+ end
35
+ @components = components
15
36
  end
16
37
 
38
+
17
39
  def sig
18
- buf = "#{@type}"
19
- buf
40
+ @sig ||= begin
41
+ if @components
42
+ ## replace tuple with (type,...)
43
+ ## e.g. tuple[] becomes (type,...)[] etc.
44
+ tuple = @components.map {|c| c.sig }.join(',')
45
+ @type.sub( "tuple", "(#{tuple})" )
46
+ else
47
+ "#{@type}"
48
+ end
49
+ end
50
+ @sig
20
51
  end
21
52
 
53
+
22
54
  def doc
23
55
  buf = ''
24
- buf << "#{@type} "
25
- buf << (@name.empty? ? '_' : @name)
56
+ if @internal_type && @internal_type != sig
57
+ buf << "#{@internal_type} "
58
+ else
59
+ buf << "#{sig} "
60
+ end
61
+ buf << (@name ? @name : '_')
26
62
  buf
27
63
  end
28
64
 
29
65
  def decl
30
66
  buf = ''
31
- buf << "#{@type} "
32
- buf << (@name.empty? ? '_' : @name)
67
+ buf << "#{sig} "
68
+ buf << (@name ? @name : '_')
69
+ ## use inline comment - why? why not?
70
+ if @internal_type && @internal_type != sig
71
+ buf << " /* #{@internal_type} */"
72
+ end
33
73
  buf
34
74
  end
75
+
76
+
35
77
  end ## class Param
36
78
  end ## module ABI
@@ -0,0 +1,40 @@
1
+ module ABI
2
+ module Helpers
3
+
4
+
5
+ SIGHASH_RX = /\A
6
+ (0x)?
7
+ (?<sighash>[0-9a-f]{8})
8
+ \z/ix
9
+
10
+ def support?( selectors, sig )
11
+ if sig.is_a?( Interface )
12
+ iface = sig
13
+ iface.selectors.each do |sighash|
14
+ unless selectors.include?( sighash )
15
+ puts " sighash >#{sighash}< not found in interface"
16
+ return false
17
+ end
18
+ end
19
+ true
20
+ else
21
+ sighash = if m=SIGHASH_RX.match( sig )
22
+ m[:sighash].downcase ## assume it's sighash (hexstring)
23
+ else
24
+ ## for convenience allow (white)spaces; auto-strip - why? why not?
25
+ sig = sig.gsub( /[ \r\t\n]/, '' )
26
+ keccak256( sig )[0,4].hexdigest
27
+ end
28
+
29
+ selectors.include?( sighash ) ? true : false
30
+ end
31
+ end
32
+ end # module Helpers
33
+
34
+
35
+ module Utils
36
+ extend Helpers
37
+ ## e.g. Utils.supports?( selectors, sig ) etc.
38
+ end
39
+
40
+ end # module ABI
@@ -1,8 +1,7 @@
1
1
 
2
2
  module ABIParser
3
-
4
3
  MAJOR = 0
5
- MINOR = 0
4
+ MINOR = 1
6
5
  PATCH = 1
7
6
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
7
 
data/lib/abiparser.rb CHANGED
@@ -6,9 +6,27 @@ require 'digest-lite'
6
6
  ## extend String
7
7
  class String
8
8
  alias_method :hexdigest, :bin_to_hex ## note: bin_to_hex added via Bytes!!!
9
+
10
+ # given two numeric strings,
11
+ # returns the bitwise xor string
12
+ def xor(other)
13
+ a = self.bytes
14
+ b = other.bytes
15
+ ## todo/check: cut-off on lower count (lc) - why? why not?
16
+ lc = (a.size < b.size) ? a.size : b.size
17
+ c = []
18
+ lc.times do |i|
19
+ c << (a[i] ^ b[i])
20
+ end
21
+ c = c.pack( 'C*' )
22
+ puts "#{self.bin_to_hex} ^ #{other.bin_to_hex} = #{c.bin_to_hex}<"
23
+ c
24
+ end
25
+ alias_method :^, :xor
9
26
  end # class String
10
27
 
11
28
 
29
+
12
30
  def keccak256( bin )
13
31
  Digest::KeccakLite.new( 256 ).digest( bin )
14
32
  end
@@ -18,15 +36,84 @@ def sig( bin )
18
36
  end
19
37
 
20
38
 
39
+ require 'abicoder'
40
+
21
41
 
22
42
  ## our own code
23
43
  require_relative 'abiparser/version' # note: let version always go first
44
+
24
45
  require_relative 'abiparser/param'
25
46
  require_relative 'abiparser/constructor'
26
47
  require_relative 'abiparser/function'
48
+ require_relative 'abiparser/utils'
27
49
  require_relative 'abiparser/contract'
50
+ require_relative 'abiparser/interface'
51
+
52
+ require_relative 'abiparser/export/interface'
53
+
54
+
55
+
56
+
57
+ ## note: make "global" constants - why? why not?
58
+
59
+ ## IERC165 0x01ffc9a7
60
+ IERC165 = ABI::Interface.new(
61
+ 'supportsInterface(bytes4)',
62
+ )
63
+
64
+ ## IERC20 0x36372b07
65
+ IERC20 = ABI::Interface.new(
66
+ 'totalSupply()',
67
+ 'balanceOf(address)',
68
+ 'allowance(address,address)',
69
+ 'transfer(address,uint256)',
70
+ 'approve(address,uint256)',
71
+ 'transferFrom(address,address,uint256)'
72
+ )
73
+
74
+ ## IERC20_NAME 0x06fdde03
75
+ IERC20_NAME = ABI::Interface.new(
76
+ 'name()'
77
+ )
78
+
79
+ ## IERC20_SYMBOL 0x95d89b41
80
+ IERC20_SYMBOL = ABI::Interface.new(
81
+ 'symbol()'
82
+ )
83
+
84
+ ## IERC20_DECIMALS 0x313ce567
85
+ IERC20_DECIMALS = ABI::Interface.new(
86
+ 'decimals()'
87
+ )
88
+
89
+ ## IERC721 0x80ac58cd
90
+ IERC721 = ABI::Interface.new(
91
+ 'balanceOf(address)',
92
+ 'ownerOf(uint256)',
93
+ 'approve(address,uint256)',
94
+ 'getApproved(uint256)',
95
+ 'setApprovalForAll(address,bool)',
96
+ 'isApprovedForAll(address,address)',
97
+ 'transferFrom(address,address,uint256)',
98
+ 'safeTransferFrom(address,address,uint256)',
99
+ 'safeTransferFrom(address,address,uint256,bytes)'
100
+ )
101
+
102
+ ## IERC721_METADATA 0x5b5e139f
103
+ IERC721_METADATA = ABI::Interface.new(
104
+ 'name()',
105
+ 'symbol()',
106
+ 'tokenURI(uint256)'
107
+ )
108
+
109
+ ## IERC721_ENUMERABLE 0x780e9d63
110
+ IERC721_ENUMERABLE = ABI::Interface.new(
111
+ 'tokenOfOwnerByIndex(address,uint256)',
112
+ 'totalSupply()',
113
+ 'tokenByIndex(uint256)'
114
+ )
115
+
28
116
 
29
- require_relative 'abiparser/export/interface.rb'
30
117
 
31
118
 
32
119
 
@@ -37,9 +124,6 @@ module ABI
37
124
  end # module ABI
38
125
 
39
126
 
40
- ## add convenience alternate spellings - why? why not?
41
- Abi = ABI
42
-
43
127
 
44
- puts AbiParser.banner
128
+ puts ABIParser.banner
45
129
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abiparser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-26 00:00:00.000000000 Z
11
+ date: 2023-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocos
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: abicoder
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rdoc
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -105,7 +119,9 @@ files:
105
119
  - lib/abiparser/contract.rb
106
120
  - lib/abiparser/export/interface.rb
107
121
  - lib/abiparser/function.rb
122
+ - lib/abiparser/interface.rb
108
123
  - lib/abiparser/param.rb
124
+ - lib/abiparser/utils.rb
109
125
  - lib/abiparser/version.rb
110
126
  homepage: https://github.com/rubycocos/blockchain
111
127
  licenses: