@@ -6,6 +6,10 @@ import {EIP7702Proxy} from "../../src/EIP7702Proxy.sol";
66import {CoinbaseSmartWallet} from "../../lib/smart-wallet/src/CoinbaseSmartWallet.sol " ;
77import {ECDSA} from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol " ;
88
9+ /**
10+ * @title CoinbaseImplementationTest
11+ * @dev Tests specific to the CoinbaseSmartWallet implementation
12+ */
913contract CoinbaseImplementationTest is Test {
1014 uint256 constant _EOA_PRIVATE_KEY = 0xA11CE ;
1115 address payable _eoa;
@@ -44,6 +48,11 @@ contract CoinbaseImplementationTest is Test {
4448 }
4549
4650 // ======== Utility Functions ========
51+ /**
52+ * @dev Creates initialization arguments for CoinbaseSmartWallet
53+ * @param owner Address to set as the initial owner
54+ * @return Encoded initialization arguments for CoinbaseSmartWallet
55+ */
4756 function _createInitArgs (
4857 address owner
4958 ) internal pure returns (bytes memory ) {
@@ -52,16 +61,72 @@ contract CoinbaseImplementationTest is Test {
5261 return abi.encode (owners);
5362 }
5463
64+ /**
65+ * @dev Signs initialization data for CoinbaseSmartWallet that will be verified by the proxy
66+ * @param signerPk Private key of the signer
67+ * @param initArgs Initialization arguments to sign
68+ * @return Signature bytes
69+ */
5570 function _signInitData (
5671 uint256 signerPk ,
5772 bytes memory initArgs
5873 ) internal view returns (bytes memory ) {
59- // Use the EOA address in the hash since that's where our proxy lives
6074 bytes32 initHash = keccak256 (abi.encode (proxy, initArgs));
6175 (uint8 v , bytes32 r , bytes32 s ) = vm.sign (signerPk, initHash);
6276 return abi.encodePacked (r, s, v);
6377 }
6478
79+ /**
80+ * @dev Helper to create ECDSA signatures
81+ * @param pk Private key to sign with
82+ * @param hash Message hash to sign
83+ * @return signature Encoded signature bytes
84+ */
85+ function _sign (
86+ uint256 pk ,
87+ bytes32 hash
88+ ) internal pure returns (bytes memory signature ) {
89+ (uint8 v , bytes32 r , bytes32 s ) = vm.sign (pk, hash);
90+ return abi.encodePacked (r, s, v);
91+ }
92+
93+ /**
94+ * @dev Creates a signature from a wallet owner for CoinbaseSmartWallet validation
95+ * @param message Message to sign
96+ * @param smartWallet Address of the wallet contract
97+ * @param ownerPk Private key of the owner
98+ * @param ownerIndex Index of the owner in the wallet's owner list
99+ * @return Wrapped signature bytes
100+ */
101+ function _createOwnerSignature (
102+ bytes32 message ,
103+ address smartWallet ,
104+ uint256 ownerPk ,
105+ uint256 ownerIndex
106+ ) internal view returns (bytes memory ) {
107+ bytes32 replaySafeHash = CoinbaseSmartWallet (payable (smartWallet))
108+ .replaySafeHash (message);
109+ bytes memory signature = _sign (ownerPk, replaySafeHash);
110+ return _applySignatureWrapper (ownerIndex, signature);
111+ }
112+
113+ /**
114+ * @dev Wraps a signature with owner index for CoinbaseSmartWallet validation
115+ * @param ownerIndex Index of the owner in the wallet's owner list
116+ * @param signatureData Raw signature bytes to wrap
117+ * @return Encoded signature wrapper
118+ */
119+ function _applySignatureWrapper (
120+ uint256 ownerIndex ,
121+ bytes memory signatureData
122+ ) internal pure returns (bytes memory ) {
123+ return
124+ abi.encode (
125+ CoinbaseSmartWallet.SignatureWrapper (ownerIndex, signatureData)
126+ );
127+ }
128+
129+ // ======== Tests ========
65130 function testCoinbaseInitializeSetsOwner () public {
66131 assertTrue (
67132 wallet.isOwnerAddress (_newOwner),
@@ -132,36 +197,4 @@ contract CoinbaseImplementationTest is Test {
132197 vm.expectRevert (CoinbaseSmartWallet.Initialized.selector );
133198 EIP7702Proxy (_eoa).initialize (initArgs, signature);
134199 }
135-
136- // ======== Utility Functions ========
137-
138- function _sign (
139- uint256 pk ,
140- bytes32 hash
141- ) internal pure returns (bytes memory signature ) {
142- (uint8 v , bytes32 r , bytes32 s ) = vm.sign (pk, hash);
143- return abi.encodePacked (r, s, v);
144- }
145-
146- function _createOwnerSignature (
147- bytes32 message ,
148- address smartWallet ,
149- uint256 ownerPk ,
150- uint256 ownerIndex
151- ) internal view returns (bytes memory ) {
152- bytes32 replaySafeHash = CoinbaseSmartWallet (payable (smartWallet))
153- .replaySafeHash (message);
154- bytes memory signature = _sign (ownerPk, replaySafeHash);
155- return _applySignatureWrapper (ownerIndex, signature);
156- }
157-
158- function _applySignatureWrapper (
159- uint256 ownerIndex ,
160- bytes memory signatureData
161- ) internal pure returns (bytes memory ) {
162- return
163- abi.encode (
164- CoinbaseSmartWallet.SignatureWrapper (ownerIndex, signatureData)
165- );
166- }
167200}
0 commit comments