@@ -33,63 +33,93 @@ impl Cheatcode for broadcast_2Call {
33
33
}
34
34
}
35
35
36
- impl Cheatcode for attachDelegationCall {
36
+ impl Cheatcode for attachDelegation_0Call {
37
37
fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
38
38
let Self { signedDelegation } = self ;
39
- let SignedDelegation { v, r, s, nonce, implementation } = signedDelegation;
39
+ attach_delegation ( ccx, signedDelegation, false )
40
+ }
41
+ }
40
42
41
- let auth = Authorization {
42
- address : * implementation,
43
- nonce : * nonce,
44
- chain_id : U256 :: from ( ccx. ecx . env . cfg . chain_id ) ,
45
- } ;
46
- let signed_auth = SignedAuthorization :: new_unchecked (
47
- auth,
48
- * v,
49
- U256 :: from_be_bytes ( r. 0 ) ,
50
- U256 :: from_be_bytes ( s. 0 ) ,
51
- ) ;
52
- write_delegation ( ccx, signed_auth. clone ( ) ) ?;
53
- ccx. state . active_delegation = Some ( signed_auth) ;
54
- Ok ( Default :: default ( ) )
43
+ impl Cheatcode for attachDelegation_1Call {
44
+ fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
45
+ let Self { signedDelegation, crossChain } = self ;
46
+ attach_delegation ( ccx, signedDelegation, * crossChain)
55
47
}
56
48
}
57
49
58
50
impl Cheatcode for signDelegation_0Call {
59
51
fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
60
52
let Self { implementation, privateKey } = * self ;
61
- sign_delegation ( ccx, privateKey, implementation, None , false )
53
+ sign_delegation ( ccx, privateKey, implementation, None , false , false )
62
54
}
63
55
}
64
56
65
57
impl Cheatcode for signDelegation_1Call {
66
58
fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
67
59
let Self { implementation, privateKey, nonce } = * self ;
68
- sign_delegation ( ccx, privateKey, implementation, Some ( nonce) , false )
60
+ sign_delegation ( ccx, privateKey, implementation, Some ( nonce) , false , false )
61
+ }
62
+ }
63
+
64
+ impl Cheatcode for signDelegation_2Call {
65
+ fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
66
+ let Self { implementation, privateKey, crossChain } = * self ;
67
+ sign_delegation ( ccx, privateKey, implementation, None , crossChain, false )
69
68
}
70
69
}
71
70
72
71
impl Cheatcode for signAndAttachDelegation_0Call {
73
72
fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
74
73
let Self { implementation, privateKey } = * self ;
75
- sign_delegation ( ccx, privateKey, implementation, None , true )
74
+ sign_delegation ( ccx, privateKey, implementation, None , false , true )
76
75
}
77
76
}
78
77
79
78
impl Cheatcode for signAndAttachDelegation_1Call {
80
79
fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
81
80
let Self { implementation, privateKey, nonce } = * self ;
82
- sign_delegation ( ccx, privateKey, implementation, Some ( nonce) , true )
81
+ sign_delegation ( ccx, privateKey, implementation, Some ( nonce) , false , true )
83
82
}
84
83
}
85
84
85
+ impl Cheatcode for signAndAttachDelegation_2Call {
86
+ fn apply_stateful ( & self , ccx : & mut CheatsCtxt ) -> Result {
87
+ let Self { implementation, privateKey, crossChain } = * self ;
88
+ sign_delegation ( ccx, privateKey, implementation, None , crossChain, true )
89
+ }
90
+ }
91
+
92
+ /// Helper function to attach an EIP-7702 delegation.
93
+ fn attach_delegation (
94
+ ccx : & mut CheatsCtxt ,
95
+ delegation : & SignedDelegation ,
96
+ cross_chain : bool ,
97
+ ) -> Result {
98
+ let SignedDelegation { v, r, s, nonce, implementation } = delegation;
99
+ // Set chain id to 0 if universal deployment is preferred.
100
+ // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7702.md#protection-from-malleability-cross-chain
101
+ let chain_id = if cross_chain { U256 :: from ( 0 ) } else { U256 :: from ( ccx. ecx . env . cfg . chain_id ) } ;
102
+
103
+ let auth = Authorization { address : * implementation, nonce : * nonce, chain_id } ;
104
+ let signed_auth = SignedAuthorization :: new_unchecked (
105
+ auth,
106
+ * v,
107
+ U256 :: from_be_bytes ( r. 0 ) ,
108
+ U256 :: from_be_bytes ( s. 0 ) ,
109
+ ) ;
110
+ write_delegation ( ccx, signed_auth. clone ( ) ) ?;
111
+ ccx. state . active_delegation = Some ( signed_auth) ;
112
+ Ok ( Default :: default ( ) )
113
+ }
114
+
86
115
/// Helper function to sign and attach (if needed) an EIP-7702 delegation.
87
116
/// Uses the provided nonce, otherwise retrieves and increments the nonce of the EOA.
88
117
fn sign_delegation (
89
118
ccx : & mut CheatsCtxt ,
90
119
private_key : Uint < 256 , 4 > ,
91
120
implementation : Address ,
92
121
nonce : Option < u64 > ,
122
+ cross_chain : bool ,
93
123
attach : bool ,
94
124
) -> Result < Vec < u8 > > {
95
125
let signer = PrivateKeySigner :: from_bytes ( & B256 :: from ( private_key) ) ?;
@@ -101,11 +131,9 @@ fn sign_delegation(
101
131
// If we don't have a nonce then use next auth account nonce.
102
132
authority_acc. data . info . nonce + 1
103
133
} ;
104
- let auth = Authorization {
105
- address : implementation,
106
- nonce,
107
- chain_id : U256 :: from ( ccx. ecx . env . cfg . chain_id ) ,
108
- } ;
134
+ let chain_id = if cross_chain { U256 :: from ( 0 ) } else { U256 :: from ( ccx. ecx . env . cfg . chain_id ) } ;
135
+
136
+ let auth = Authorization { address : implementation, nonce, chain_id } ;
109
137
let sig = signer. sign_hash_sync ( & auth. signature_hash ( ) ) ?;
110
138
// Attach delegation.
111
139
if attach {
@@ -133,6 +161,7 @@ fn write_delegation(ccx: &mut CheatsCtxt, auth: SignedAuthorization) -> Result<(
133
161
134
162
if auth. address . is_zero ( ) {
135
163
// Set empty code if the delegation address of authority is 0x.
164
+ // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7702.md#behavior.
136
165
ccx. ecx . journaled_state . set_code_with_hash ( authority, Bytecode :: default ( ) , KECCAK_EMPTY ) ;
137
166
} else {
138
167
let bytecode = Bytecode :: new_eip7702 ( * auth. address ( ) ) ;
0 commit comments