@@ -3,7 +3,7 @@ pragma solidity ^0.8.24;
3
3
// solc: 0.8.28, optimization runs: 200, evm version: cancun.
4
4
5
5
/// @notice Relay proxy for EIP7702 delegations.
6
- /// @author Solady (https://github.com/vectorized/solady/blob/main/src/accounts/LibEIP7702 .sol)
6
+ /// @author Solady (https://github.com/vectorized/solady/blob/main/src/accounts/EIP7702Proxy .sol)
7
7
///
8
8
/// @dev Note: This relay proxy is useful for upgradeable EIP7702 accounts
9
9
/// without the need for redelegation.
@@ -17,7 +17,7 @@ contract EIP7702Proxy {
17
17
/* IMMUTABLES */
18
18
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
19
19
20
- /// @dev For allowing the differentiation of the EOA and the proxy itself.
20
+ /// @dev For differentiating calls on the EOA and calls on the proxy itself.
21
21
uint256 internal immutable __self = uint256 (uint160 (address (this )));
22
22
23
23
/// @dev The default implementation. Provided for optimization.
@@ -53,13 +53,12 @@ contract EIP7702Proxy {
53
53
uint256 defaultImplementation;
54
54
/// @solidity memory-safe-assembly
55
55
assembly {
56
- let implementation := shr (96 , shl (96 , initialImplementation))
57
- let admin := shr (96 , shl (96 , initialAdmin))
58
56
// We will store the implementation in the storage regardless,
59
57
// to aid proxy detection on block explorers.
60
- sstore (_ERC1967_IMPLEMENTATION_SLOT, implementation)
61
- sstore (_ERC1967_ADMIN_SLOT, admin)
62
- defaultImplementation := mul (lt (admin, iszero (iszero (implementation))), implementation)
58
+ sstore (_ERC1967_IMPLEMENTATION_SLOT, initialImplementation)
59
+ sstore (_ERC1967_ADMIN_SLOT, initialAdmin)
60
+ defaultImplementation :=
61
+ mul (lt (initialAdmin, iszero (iszero (initialImplementation))), initialImplementation)
63
62
}
64
63
_defaultImplementation = defaultImplementation;
65
64
}
@@ -75,13 +74,14 @@ contract EIP7702Proxy {
75
74
assembly {
76
75
mstore (0x40 , returndatasize ()) // Optimization trick to change `6040608052` into `3d604052`.
77
76
let implementationSlot := _ERC1967_IMPLEMENTATION_SLOT
77
+ let addrMask := shr (96 , not (0 ))
78
78
// Workflow for calling on the proxy itself.
79
79
// We cannot put these functions in the public ABI as this proxy must
80
80
// fully forward all the calldata from EOAs pointing to this proxy.
81
81
if iszero (xor (address (), s)) {
82
82
if iszero (gt (calldatasize (), 1 )) {
83
- mstore (calldatasize () , sload (implementationSlot))
84
- return (calldatasize () , 0x20 )
83
+ mstore (0x00 , and (addrMask , sload (implementationSlot) ))
84
+ return (0x00 , 0x20 )
85
85
}
86
86
let fnSel := shr (224 , calldataload (0x00 ))
87
87
// `implementation()`.
@@ -99,7 +99,7 @@ contract EIP7702Proxy {
99
99
}
100
100
// Admin workflow.
101
101
if eq (caller (), admin) {
102
- let addr := shr ( 96 , calldataload (0x10 ))
102
+ let addr := and (addrMask , calldataload (0x04 ))
103
103
// `changeAdmin(address)`.
104
104
if eq (0x8f283970 , fnSel) {
105
105
sstore (adminSlot, addr)
@@ -116,30 +116,28 @@ contract EIP7702Proxy {
116
116
// We don't need to forward any data to the new implementation.
117
117
// This "proxy" is actually close to an upgradeable beacon.
118
118
}
119
- revert (returndatasize () , 0x00 )
119
+ revert (0x00 , 0x00 )
120
120
}
121
121
// Workflow for the EIP7702 authority (i.e. the EOA).
122
- let impl := sload (implementationSlot) // The preferred implementation on the EOA.
122
+ let implementation := and (addrMask, sload (implementationSlot)) // On EOA's storage .
123
123
// Special workflow for retrieving the implementation directly.
124
124
if eq (1 , calldatasize ()) {
125
125
// If the preferred implementation is `address(0)`.
126
- if iszero (shl ( 96 , impl) ) {
126
+ if iszero (implementation ) {
127
127
// If `defaultImplementation` is `address(0)`
128
128
if iszero (defaultImplementation) {
129
129
// Fetch the implementation from the proxy.
130
- if iszero (staticcall (gas (), s, calldatasize (), 0x00 , 0x00 , 0x20 )) {
131
- invalid ()
132
- }
133
- return (0x00 , 0x20 )
130
+ if staticcall (gas (), s, 0x00 , 0x00 , 0x00 , 0x20 ) { return (0x00 , 0x20 ) }
131
+ revert (0x00 , 0x00 )
134
132
}
135
- impl := defaultImplementation
133
+ implementation := defaultImplementation
136
134
}
137
- mstore (0x00 , shr ( 96 , shl ( 96 , impl)) )
135
+ mstore (0x00 , implementation )
138
136
return (0x00 , 0x20 )
139
137
}
140
138
calldatacopy (0x00 , 0x00 , calldatasize ()) // Copy the calldata for the delegatecall.
141
139
// If the preferred implementation is `address(0)`.
142
- if iszero (shl ( 96 , impl) ) {
140
+ if iszero (implementation ) {
143
141
// If `defaultImplementation` is `address(0)`, perform the initialization workflow.
144
142
if iszero (defaultImplementation) {
145
143
if iszero (
@@ -148,7 +146,7 @@ contract EIP7702Proxy {
148
146
gas (), mload (calldatasize ()), 0x00 , calldatasize (), 0x00 , 0x00
149
147
),
150
148
// Fetch the implementation from the proxy.
151
- staticcall (gas (), s, calldatasize () , 0x00 , calldatasize (), 0x20 )
149
+ staticcall (gas (), s, 0x00 , 0x00 , calldatasize (), 0x20 )
152
150
)
153
151
) {
154
152
returndatacopy (0x00 , 0x00 , returndatasize ())
@@ -163,21 +161,21 @@ contract EIP7702Proxy {
163
161
let initializationRequestSlot :=
164
162
_EIP7702_PROXY_DELEGATION_INITIALIZATION_REQUEST_SLOT
165
163
if tload (initializationRequestSlot) {
166
- let implSlot := implementationSlot
167
164
// The `implementation` is still at `calldatasize()` in memory.
168
165
// Preserve the upper 96 bits when updating in case they are used for some stuff.
169
166
sstore (
170
- implSlot, or (shl (160 , shr (160 , sload (implSlot))), mload (calldatasize ()))
167
+ implementationSlot,
168
+ or (and (not (addrMask), sload (implementationSlot)), mload (calldatasize ()))
171
169
)
172
170
tstore (initializationRequestSlot, 0 ) // Clear.
173
171
}
174
172
returndatacopy (0x00 , 0x00 , returndatasize ())
175
173
return (0x00 , returndatasize ())
176
174
}
177
- impl := defaultImplementation
175
+ implementation := defaultImplementation
178
176
}
179
177
// Otherwise, just delegatecall and bubble up the results without initialization.
180
- if iszero (delegatecall (gas (), impl , 0x00 , calldatasize (), calldatasize () , 0x00 )) {
178
+ if iszero (delegatecall (gas (), implementation , 0x00 , calldatasize (), 0x00 , 0x00 )) {
181
179
returndatacopy (0x00 , 0x00 , returndatasize ())
182
180
revert (0x00 , returndatasize ())
183
181
}
0 commit comments