Class: Eth::Tx::Eip7702::Authorization

Inherits:
Object
  • Object
show all
Defined in:
lib/eth/tx/eip7702.rb

Overview

Provides an EIP-7702 authorization that store the address to code which the signer desires to execute in the context of their EOA.

Constant Summary collapse

MAGIC =

The EIP-7702 magic byte, prefixed to the RLP-encoded authorization tuple before hashing so that authorization signatures cannot be replayed as transaction signatures. Ref: https://eips.ethereum.org/EIPS/eip-7702

0x05.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fields) ⇒ Authorization

Create a type-4 (EIP-7702) authorization object that can be prepared for type-4 transactions. Ref: https://eips.ethereum.org/EIPS/eip-7702

Parameters:

  • fields (Hash) —

    all necessary transaction fields.

Options Hash (fields):

  • :chain_id (Integer) —

    the chain ID.

  • :address (Eth::Address) —

    the delegation target address.

  • :nonce (Integer) —

    the authority's account nonce.



64
65
66
67
68
69
70
71
# File 'lib/eth/tx/eip7702.rb', line 64

def initialize(fields)
  @chain_id = fields[:chain_id].to_i
  @address = fields[:address].to_s
  @nonce = fields[:nonce].to_i
  @signature_y_parity = fields[:recovery_id]
  @signature_r = fields[:r]
  @signature_s = fields[:s]
end

Instance Attribute Details

#address ⇒ Object (readonly)

The delegation target: the address whose code the authority's account runs. The authority itself is the signer.



42
43
44
# File 'lib/eth/tx/eip7702.rb', line 42

def address
  @address
end

#chain_id ⇒ Object (readonly)

The EIP-155 Chain ID. Ref: https://eips.ethereum.org/EIPS/eip-155



38
39
40
# File 'lib/eth/tx/eip7702.rb', line 38

def chain_id
  @chain_id
end

#nonce ⇒ Object (readonly)

The authority's account nonce this authorization is valid for.



45
46
47
# File 'lib/eth/tx/eip7702.rb', line 45

def nonce
  @nonce
end

#signature_r ⇒ Object (readonly)

The signature r value.



51
52
53
# File 'lib/eth/tx/eip7702.rb', line 51

def signature_r
  @signature_r
end

#signature_s ⇒ Object (readonly)

The signature s value.



54
55
56
# File 'lib/eth/tx/eip7702.rb', line 54

def signature_s
  @signature_s
end

#signature_y_parity ⇒ Object (readonly)

The signature's y-parity byte (not v).



48
49
50
# File 'lib/eth/tx/eip7702.rb', line 48

def signature_y_parity
  @signature_y_parity
end

Instance Method Details

#==(o) ⇒ Bool

Compares two authorization data objects.

Returns:

  • (Bool) —

    true if objects are same and share same state.



154
155
156
# File 'lib/eth/tx/eip7702.rb', line 154

def ==(o)
  o.class == self.class && o.state == state
end

#raw ⇒ Bytes

Gets the raw serialized authorization data.

Returns:

  • (Bytes) —

    raw serialized authorization data.



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/eth/tx/eip7702.rb', line 139

def raw
  authorization_data = []
  authorization_data.push Util.serialize_int_to_big_endian @chain_id
  authorization_data.push Util.hex_to_bin @address
  authorization_data.push Util.serialize_int_to_big_endian @nonce

  authorization_data.push Util.serialize_int_to_big_endian @signature_y_parity
  authorization_data.push Util.serialize_int_to_big_endian @signature_r
  authorization_data.push Util.serialize_int_to_big_endian @signature_s
  authorization_data
end

#sign(key) ⇒ String

Sign the authorization with a given key. The key's account becomes the authority, delegating to the code at #address; any key may sign for any delegation target.

The signed authorization is valid on chain #chain_id, or on any chain if that is 0. Anyone holding it can submit it while the account's nonce equals #nonce; on each chain where it is included, the code at #address then acts as the account until the account delegates elsewhere. Sign only for code you trust.

Parameters:

  • key (Eth::Key) —

    the key-pair to use for signing.

Returns:

Raises:



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

def sign(key)
  if Tx.signed? self
    raise Signature::SignatureError, "Authorization is already signed!"
  end

  # reject a delegation target that is not a valid address: malformed
  # input yields a tuple clients reject, and an EIP-55 checksum
  # mismatch most likely means a typo in the target
  Address.new @address

  # sign a keccak hash of the magic-prefixed, encoded authorization;
  # the chain ID is part of that payload, so the signature carries no
  # EIP-155 v and the y-parity is the raw recovery id
  sign_hash = unsigned_hash
  signature = key.sign(sign_hash)
  r, s, v = Signature.dissect signature
  recovery_id = Chain.to_recovery_id v.to_i(16)
  @signature_y_parity = recovery_id
  @signature_r = r
  @signature_s = s
  return Util.bin_to_hex sign_hash
end

#unsigned_encoded ⇒ String

Encodes the unsigned authorization payload required for signing: the MAGIC byte followed by rlp([chain_id, address, nonce]).

Returns:

  • (String) —

    the magic-prefixed, RLP-encoded authorization tuple.



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/eth/tx/eip7702.rb', line 114

def unsigned_encoded
  authorization_data = []
  authorization_data.push Util.serialize_int_to_big_endian @chain_id
  authorization_data.push Util.hex_to_bin @address
  authorization_data.push Util.serialize_int_to_big_endian @nonce
  authorization_encoded = Rlp.encode authorization_data

  # prefix the EIP-7702 magic byte to separate the signing domain
  magic = Util.serialize_int_to_big_endian MAGIC

  return "#{magic}#{authorization_encoded}"
end

#unsigned_hash ⇒ String

Gets the sign-hash required to sign: the Keccak-256 hash of #unsigned_encoded, which an EIP-7702 client recovers the authority from.

Returns:

  • (String) —

    a Keccak-256 hash.



132
133
134
# File 'lib/eth/tx/eip7702.rb', line 132

def unsigned_hash
  Util.keccak256 unsigned_encoded
end