Class: Eth::Tx::Eip7702::Authorization
- Inherits:
-
Object
- Object
- Eth::Tx::Eip7702::Authorization
- 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
-
#address ⇒ Object
readonly
The delegation target: the address whose code the authority's account runs.
-
#chain_id ⇒ Object
readonly
The EIP-155 Chain ID.
-
#nonce ⇒ Object
readonly
The authority's account nonce this authorization is valid for.
-
#signature_r ⇒ Object
readonly
The signature
rvalue. -
#signature_s ⇒ Object
readonly
The signature
svalue. -
#signature_y_parity ⇒ Object
readonly
The signature's y-parity byte (not v).
Instance Method Summary collapse
-
#==(o) ⇒ Bool
Compares two authorization data objects.
-
#initialize(fields) ⇒ Authorization
constructor
Create a type-4 (EIP-7702) authorization object that can be prepared for type-4 transactions.
-
#raw ⇒ Bytes
Gets the raw serialized authorization data.
-
#sign(key) ⇒ String
Sign the authorization with a given key.
-
#unsigned_encoded ⇒ String
Encodes the unsigned authorization payload required for signing: the MAGIC byte followed by
rlp([chain_id, address, nonce]). -
#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.
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
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.
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.
139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/eth/tx/eip7702.rb', line 139 def raw = [] .push Util.serialize_int_to_big_endian @chain_id .push Util.hex_to_bin @address .push Util.serialize_int_to_big_endian @nonce .push Util.serialize_int_to_big_endian @signature_y_parity .push Util.serialize_int_to_big_endian @signature_r .push Util.serialize_int_to_big_endian @signature_s 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.
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]).
114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/eth/tx/eip7702.rb', line 114 def unsigned_encoded = [] .push Util.serialize_int_to_big_endian @chain_id .push Util.hex_to_bin @address .push Util.serialize_int_to_big_endian @nonce = Rlp.encode # prefix the EIP-7702 magic byte to separate the signing domain magic = Util.serialize_int_to_big_endian MAGIC return "#{magic}#{}" 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.
132 133 134 |
# File 'lib/eth/tx/eip7702.rb', line 132 def unsigned_hash Util.keccak256 unsigned_encoded end |