You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/adr/ADR-0003-typed-transactions-sponsorship.md
+8-11Lines changed: 8 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ DRAFT — Not Implemented
8
8
9
9
## Abstract
10
10
11
-
This ADR proposes a new EIP-2718 typed transaction (0x76) for the EvNode protocol. The transaction natively supports **gas sponsorship** and **batch calls**. Sponsorship separates the `executor` (identity/nonce provider) from the `fee_payer` (gas provider). Batch calls allow multiple operations to execute **atomically** within a single transaction. This removes the need for off-chain relayers or batching contracts while remaining compatible with Reth's modular architecture.
11
+
This ADR proposes a new EIP-2718 typed transaction (0x76) for the EvNode protocol. The transaction natively supports **gas sponsorship** and **batch calls**. Sponsorship separates the `executor` (identity/nonce provider) from the sponsor (gas provider, recovered from the sponsor signature). Batch calls allow multiple operations to execute **atomically** within a single transaction. This removes the need for off-chain relayers or batching contracts while remaining compatible with Reth's modular architecture.
12
12
13
13
## Context
14
14
@@ -18,7 +18,7 @@ Gas sponsorship is a recurring requirement for onboarding users and for product
18
18
19
19
EvNode aims to support sponsorship and batch calls natively. We require a mechanism where a transaction can carry two signatures (authorization + payment) and multiple calls, with deterministic encoding and atomic execution.
20
20
21
-
Terminology: the **executor** is the signer of domain `0x76`; it provides the `nonce`, is the transaction `from`, and maps to `tx.origin`. The **sponsor**(aka `fee_payer`) is the signer of domain `0x78` and pays gas when sponsorship is present; `fee_payer` is the sponsor address field. **Sponsorship** means `fee_payer` is present and pays gas; it does not change the `from`.
21
+
Terminology: the **executor** is the signer of domain `0x76`; it provides the `nonce`, is the transaction `from`, and maps to `tx.origin`. The **sponsor** is the signer of domain `0x78` and pays gas when sponsorship is present. **Sponsorship** means `fee_payer_signature` is present and pays gas; it does not change the `from`.
22
22
23
23
## Decision
24
24
@@ -51,7 +51,6 @@ pub struct EvNodeTransaction {
51
51
pubcalls:Vec<Call>,
52
52
pubaccess_list:AccessList,
53
53
// Sponsorship Extensions (Optional)
54
-
pubfee_payer:Option<Address>,
55
54
pubfee_payer_signature:Option<Signature>,
56
55
}
57
56
@@ -72,7 +71,6 @@ pub type EvNodeSignedTx = Signed<EvNodeTransaction>;
72
71
73
72
Optional fields MUST be encoded deterministically:
74
73
75
-
*`fee_payer`: encode `0x80` (nil) when `None`.
76
74
*`fee_payer_signature`: encode `0x80` (nil) when `None`.
77
75
78
76
The `calls` field is an RLP list of `Call` structs, each encoded as:
@@ -91,24 +89,23 @@ This transaction uses two signature domains to prevent collisions and enable the
91
89
92
90
1.**Executor Signature** (Domain `0x76`)
93
91
* Preimage: `0x76 || rlp(payload_fields...)` (no `v,r,s` in the RLP).
94
-
* Constraint: `fee_payer` and `fee_payer_signature` MUST be set to `0x80` (empty) in the RLP stream for this hash.
92
+
* Constraint: `fee_payer_signature` MUST be set to `0x80` (empty) in the RLP stream for this hash.
95
93
**Effect:* The executor authorizes the intent regardless of who pays.
96
94
97
95
2.**Sponsor Signature** (Domain `0x78`)
98
-
* Preimage: `0x78 || rlp(payload_fields...)`
99
-
* Constraint: `fee_payer` MUST be the sponsor's address. `fee_payer_signature` remains `0x80`.
100
-
**Effect:* The sponsor binds their address to the specific executor intent.
101
-
**Note:* In the final encoded transaction, `fee_payer_signature` is populated with the sponsor signature; it is set to `0x80` only for signing preimages. The "both present or both absent" rule applies to the final encoded payload.
96
+
* Preimage: `0x78 || rlp(payload_fields...)` with `fee_payer_signature` set to `0x80`, and the executor `sender` address encoded in its place for the hash.
97
+
**Effect:* The sponsor binds to a specific executor intent and can be recovered from the signature.
98
+
**Note:* In the final encoded transaction, `fee_payer_signature` is populated with the sponsor signature; it is set to `0x80` only for signing preimages.
102
99
103
100
3.**Transaction Hash** (TxHash)
104
101
*`keccak256(0x76 || rlp([payload_fields..., v, r, s]))` using the final encoded transaction (including the sponsor signature if present).
105
102
106
103
### Validity Rules
107
104
108
-
***State:**`fee_payer` and `fee_payer_signature` MUST be both present or both absent.
105
+
***State:**`fee_payer_signature` is optional; if absent, the transaction is not sponsored.
109
106
***Behavior:**
110
107
* If sponsorship is absent: Executor pays gas (standard EIP-1559 behavior).
111
-
* If sponsorship is present: Sponsor pays gas; executor remains `from` (tx.origin).
108
+
* If sponsorship is present: Sponsor pays gas (sponsor recovered from signature); executor remains `from` (tx.origin).
112
109
113
110
***Validation:**
114
111
* Executor signature MUST be valid for domain `0x76`.
0 commit comments