Skip to content

Commit b09e6f4

Browse files
authored
♻️ Tidy EIP7702Proxy (#1386)
1 parent 5954693 commit b09e6f4

File tree

3 files changed

+29
-31
lines changed

3 files changed

+29
-31
lines changed

docs/accounts/libeip7702.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ and the delegation, so we shall just use bytes32 in case we want to standardize
7272

7373
```solidity
7474
bytes internal constant EIP7702_PROXY_CREATION_CODE =
75-
hex"60c060408190523060805261031138819003908190833981016040819052610026916100a3565b6001600160a01b039182167f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905591167fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103819055811515110260a0526100d4565b80516001600160a01b038116811461009e575f5ffd5b919050565b5f5f604083850312156100b4575f5ffd5b6100bd83610088565b91506100cb60208401610088565b90509250929050565b60805160a05161021e6100f35f395f602601525f6005015261021e5ff3fe3d6040527f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc308318610119576001361161007e5780543652602036f35b5f3560e01c80635c60da1b0361009f5760205f5f36305afa1561009f573d5ff35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610380548263f851a440036100d557805f5260205ff35b8033036101125760103560601c83638f283970036100f95780835560015f5260205ff35b83630900f010036101105780855560015f5260205ff35b505b5050505f3dfd5b805436600103610154578060601b61014657826101435760205f5f36875afa61013e57fe5b60205ff35b50815b8060601b60601c5f5260205ff35b365f5f378060601b6101cb57826101c8576020365f36875afa5f5f365f36515af416610182573d5f5f3e3d5ffd5b7f94e11c6e41e7fb92cb8bb65e13fdfbd4eba8b831292a1a220f7915c78c7c078f805c156101bf57365183546001600160a01b0319161783555f815d5b503d5f5f3e3d5ff35b50815b5f36365f845af46101de573d5f5f3e3d5ffd5b50503d5f5f3e3d5ff3fea2646970667358221220ad810cb1d8296ebd4649785ecb093c978531e8ae483468cdb56d4856d522f99464736f6c634300081c0033"
75+
hex"60c06040819052306080526102f93881900390819083398101604081905261002691610096565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8290557fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103819055811515110260a0526100c7565b80516001600160a01b0381168114610091575f5ffd5b919050565b5f5f604083850312156100a7575f5ffd5b6100b08361007b565b91506100be6020840161007b565b90509250929050565b60805160a0516102136100e65f395f602601525f600501526102135ff3fe3d6040527f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6001600160a01b0330841861011f576001361161008857815481165f5260205ff35b5f3560e01c80635c60da1b036100a95760205f5f36305afa156100a9573d5ff35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610380548263f851a440036100df57805f5260205ff35b80330361011b57600435841683638f283970036101025780835560015f5260205ff35b83630900f010036101195780865560015f5260205ff35b505b5f5ffd5b8154811636600103610152578061014a57836101475760205f5f5f885afa1561011b5760205ff35b50825b805f5260205ff35b365f5f37806101bf57836101bc576020365f5f885afa5f5f365f36515af41661017d573d5f5f3e3d5ffd5b7f94e11c6e41e7fb92cb8bb65e13fdfbd4eba8b831292a1a220f7915c78c7c078f805c156101b357365184548419161784555f815d5b503d5f5f3e3d5ff35b50825b5f5f365f845af46101d2573d5f5f3e3d5ffd5b5050503d5f5f3e3d5ff3fea26469706673582212206f32ef601c4ecbe6bf6bd140c202d924909bf63b82b41534da1a01bd9620334064736f6c634300081c0033"
7676
```
7777

7878
The creation code for the EIP7702Proxy.
@@ -82,7 +82,7 @@ This is generated from [`EIP7702Proxy.sol`](accounts/eip7702proxy.md) with exact
8282

8383
```solidity
8484
bytes32 internal constant EIP7702_PROXY_MINIMAL_CODE_HASH =
85-
0x7386c2810632fa8ea702ec3b7b0ad8fe514f063d42915830c6dd30abd543082e
85+
0xcabd060d42833a05e9887a2398c1b9c5886dbf4aaa134d91e86d7384bd6f3c93
8686
```
8787

8888
The keccak256 of runtime code for [`EIP7702Proxy.sol`](accounts/eip7702proxy.md) with exact compilation settings,

src/accounts/EIP7702Proxy.sol

+23-25
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.24;
33
// solc: 0.8.28, optimization runs: 200, evm version: cancun.
44

55
/// @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)
77
///
88
/// @dev Note: This relay proxy is useful for upgradeable EIP7702 accounts
99
/// without the need for redelegation.
@@ -17,7 +17,7 @@ contract EIP7702Proxy {
1717
/* IMMUTABLES */
1818
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
1919

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.
2121
uint256 internal immutable __self = uint256(uint160(address(this)));
2222

2323
/// @dev The default implementation. Provided for optimization.
@@ -53,13 +53,12 @@ contract EIP7702Proxy {
5353
uint256 defaultImplementation;
5454
/// @solidity memory-safe-assembly
5555
assembly {
56-
let implementation := shr(96, shl(96, initialImplementation))
57-
let admin := shr(96, shl(96, initialAdmin))
5856
// We will store the implementation in the storage regardless,
5957
// 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)
6362
}
6463
_defaultImplementation = defaultImplementation;
6564
}
@@ -75,13 +74,14 @@ contract EIP7702Proxy {
7574
assembly {
7675
mstore(0x40, returndatasize()) // Optimization trick to change `6040608052` into `3d604052`.
7776
let implementationSlot := _ERC1967_IMPLEMENTATION_SLOT
77+
let addrMask := shr(96, not(0))
7878
// Workflow for calling on the proxy itself.
7979
// We cannot put these functions in the public ABI as this proxy must
8080
// fully forward all the calldata from EOAs pointing to this proxy.
8181
if iszero(xor(address(), s)) {
8282
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)
8585
}
8686
let fnSel := shr(224, calldataload(0x00))
8787
// `implementation()`.
@@ -99,7 +99,7 @@ contract EIP7702Proxy {
9999
}
100100
// Admin workflow.
101101
if eq(caller(), admin) {
102-
let addr := shr(96, calldataload(0x10))
102+
let addr := and(addrMask, calldataload(0x04))
103103
// `changeAdmin(address)`.
104104
if eq(0x8f283970, fnSel) {
105105
sstore(adminSlot, addr)
@@ -116,30 +116,28 @@ contract EIP7702Proxy {
116116
// We don't need to forward any data to the new implementation.
117117
// This "proxy" is actually close to an upgradeable beacon.
118118
}
119-
revert(returndatasize(), 0x00)
119+
revert(0x00, 0x00)
120120
}
121121
// 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.
123123
// Special workflow for retrieving the implementation directly.
124124
if eq(1, calldatasize()) {
125125
// If the preferred implementation is `address(0)`.
126-
if iszero(shl(96, impl)) {
126+
if iszero(implementation) {
127127
// If `defaultImplementation` is `address(0)`
128128
if iszero(defaultImplementation) {
129129
// 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)
134132
}
135-
impl := defaultImplementation
133+
implementation := defaultImplementation
136134
}
137-
mstore(0x00, shr(96, shl(96, impl)))
135+
mstore(0x00, implementation)
138136
return(0x00, 0x20)
139137
}
140138
calldatacopy(0x00, 0x00, calldatasize()) // Copy the calldata for the delegatecall.
141139
// If the preferred implementation is `address(0)`.
142-
if iszero(shl(96, impl)) {
140+
if iszero(implementation) {
143141
// If `defaultImplementation` is `address(0)`, perform the initialization workflow.
144142
if iszero(defaultImplementation) {
145143
if iszero(
@@ -148,7 +146,7 @@ contract EIP7702Proxy {
148146
gas(), mload(calldatasize()), 0x00, calldatasize(), 0x00, 0x00
149147
),
150148
// Fetch the implementation from the proxy.
151-
staticcall(gas(), s, calldatasize(), 0x00, calldatasize(), 0x20)
149+
staticcall(gas(), s, 0x00, 0x00, calldatasize(), 0x20)
152150
)
153151
) {
154152
returndatacopy(0x00, 0x00, returndatasize())
@@ -163,21 +161,21 @@ contract EIP7702Proxy {
163161
let initializationRequestSlot :=
164162
_EIP7702_PROXY_DELEGATION_INITIALIZATION_REQUEST_SLOT
165163
if tload(initializationRequestSlot) {
166-
let implSlot := implementationSlot
167164
// The `implementation` is still at `calldatasize()` in memory.
168165
// Preserve the upper 96 bits when updating in case they are used for some stuff.
169166
sstore(
170-
implSlot, or(shl(160, shr(160, sload(implSlot))), mload(calldatasize()))
167+
implementationSlot,
168+
or(and(not(addrMask), sload(implementationSlot)), mload(calldatasize()))
171169
)
172170
tstore(initializationRequestSlot, 0) // Clear.
173171
}
174172
returndatacopy(0x00, 0x00, returndatasize())
175173
return(0x00, returndatasize())
176174
}
177-
impl := defaultImplementation
175+
implementation := defaultImplementation
178176
}
179177
// 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)) {
181179
returndatacopy(0x00, 0x00, returndatasize())
182180
revert(0x00, returndatasize())
183181
}

src/accounts/LibEIP7702.sol

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ library LibEIP7702 {
3939
/// @dev The creation code for the EIP7702Proxy.
4040
/// This is generated from `EIP7702Proxy.sol` with exact compilation settings.
4141
bytes internal constant EIP7702_PROXY_CREATION_CODE =
42-
hex"60c060408190523060805261031138819003908190833981016040819052610026916100a3565b6001600160a01b039182167f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905591167fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103819055811515110260a0526100d4565b80516001600160a01b038116811461009e575f5ffd5b919050565b5f5f604083850312156100b4575f5ffd5b6100bd83610088565b91506100cb60208401610088565b90509250929050565b60805160a05161021e6100f35f395f602601525f6005015261021e5ff3fe3d6040527f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc308318610119576001361161007e5780543652602036f35b5f3560e01c80635c60da1b0361009f5760205f5f36305afa1561009f573d5ff35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610380548263f851a440036100d557805f5260205ff35b8033036101125760103560601c83638f283970036100f95780835560015f5260205ff35b83630900f010036101105780855560015f5260205ff35b505b5050505f3dfd5b805436600103610154578060601b61014657826101435760205f5f36875afa61013e57fe5b60205ff35b50815b8060601b60601c5f5260205ff35b365f5f378060601b6101cb57826101c8576020365f36875afa5f5f365f36515af416610182573d5f5f3e3d5ffd5b7f94e11c6e41e7fb92cb8bb65e13fdfbd4eba8b831292a1a220f7915c78c7c078f805c156101bf57365183546001600160a01b0319161783555f815d5b503d5f5f3e3d5ff35b50815b5f36365f845af46101de573d5f5f3e3d5ffd5b50503d5f5f3e3d5ff3fea2646970667358221220ad810cb1d8296ebd4649785ecb093c978531e8ae483468cdb56d4856d522f99464736f6c634300081c0033";
42+
hex"60c06040819052306080526102f93881900390819083398101604081905261002691610096565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8290557fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103819055811515110260a0526100c7565b80516001600160a01b0381168114610091575f5ffd5b919050565b5f5f604083850312156100a7575f5ffd5b6100b08361007b565b91506100be6020840161007b565b90509250929050565b60805160a0516102136100e65f395f602601525f600501526102135ff3fe3d6040527f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6001600160a01b0330841861011f576001361161008857815481165f5260205ff35b5f3560e01c80635c60da1b036100a95760205f5f36305afa156100a9573d5ff35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610380548263f851a440036100df57805f5260205ff35b80330361011b57600435841683638f283970036101025780835560015f5260205ff35b83630900f010036101195780865560015f5260205ff35b505b5f5ffd5b8154811636600103610152578061014a57836101475760205f5f5f885afa1561011b5760205ff35b50825b805f5260205ff35b365f5f37806101bf57836101bc576020365f5f885afa5f5f365f36515af41661017d573d5f5f3e3d5ffd5b7f94e11c6e41e7fb92cb8bb65e13fdfbd4eba8b831292a1a220f7915c78c7c078f805c156101b357365184548419161784555f815d5b503d5f5f3e3d5ff35b50825b5f5f365f845af46101d2573d5f5f3e3d5ffd5b5050503d5f5f3e3d5ff3fea264697066735822122094bb23ea8991ed3ef0f69ec672e5622d7e7167d81f37b21ee01d9fe33acb081964736f6c634300081c0033";
4343

4444
/// @dev The keccak256 of runtime code for `EIP7702Proxy.sol` with exact compilation settings,
4545
/// with immutables zeroized and without the CBOR metadata.
4646
bytes32 internal constant EIP7702_PROXY_MINIMAL_CODE_HASH =
47-
0x7386c2810632fa8ea702ec3b7b0ad8fe514f063d42915830c6dd30abd543082e;
47+
0xcabd060d42833a05e9887a2398c1b9c5886dbf4aaa134d91e86d7384bd6f3c93;
4848

4949
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
5050
/* AUTHORITY AND PROXY OPERATIONS */
@@ -98,11 +98,11 @@ library LibEIP7702 {
9898
assembly {
9999
let m := mload(0x40)
100100
// Copy the runtime bytecode without the CBOR metadata.
101-
extcodecopy(target, m, 0x00, 0x1e8)
101+
extcodecopy(target, m, 0x00, 0x1dd)
102102
// Zeroize the immutables.
103103
mstore(add(m, 0x05), 0)
104104
mstore(add(m, 0x26), 0)
105-
result := eq(keccak256(m, 0x1e8), EIP7702_PROXY_MINIMAL_CODE_HASH)
105+
result := eq(keccak256(m, 0x1dd), EIP7702_PROXY_MINIMAL_CODE_HASH)
106106
}
107107
}
108108

0 commit comments

Comments
 (0)