Skip to content

Commit 14f4c8c

Browse files
authored
Merge pull request #8 from base-org/amie/test-upgrades
Test `upgradeToAndCall` for ERC-1967 upgrades
2 parents b2da844 + 88ac5e7 commit 14f4c8c

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77
[submodule "lib/smart-wallet"]
88
path = lib/smart-wallet
99
url = https://github.com/coinbase/smart-wallet
10+
[submodule "lib/solady"]
11+
path = lib/solady
12+
url = https://github.com/vectorized/solady

lib/solady

Submodule solady added at 5ea5d9f

remappings.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
smart-wallet/=lib/smart-wallet/src/
22
forge-std/=lib/forge-std/src/
3-
openzeppelin-contracts/=lib/openzeppelin-contracts/
3+
openzeppelin-contracts/=lib/openzeppelin-contracts/
4+
solady/=lib/solady/src/
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.23;
3+
4+
import {EIP7702ProxyBase} from "../base/EIP7702ProxyBase.sol";
5+
import {EIP7702Proxy} from "../../src/EIP7702Proxy.sol";
6+
import {CoinbaseSmartWallet} from "../../lib/smart-wallet/src/CoinbaseSmartWallet.sol";
7+
import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol";
8+
9+
contract UpgradeToAndCallTest is EIP7702ProxyBase {
10+
DummyImplementation newImplementation;
11+
12+
function setUp() public override {
13+
super.setUp();
14+
15+
// Initialize the proxy first
16+
bytes memory initArgs = _createInitArgs(_newOwner);
17+
bytes memory signature = _signInitData(_EOA_PRIVATE_KEY, initArgs);
18+
EIP7702Proxy(_eoa).initialize(initArgs, signature);
19+
20+
// Deploy new implementation
21+
newImplementation = new DummyImplementation();
22+
}
23+
24+
function testUpgradeToAndCall_succeedsForOwner() public {
25+
// Wallet owner should be able to upgrade
26+
vm.prank(_newOwner);
27+
28+
CoinbaseSmartWallet(payable(_eoa)).upgradeToAndCall(
29+
address(newImplementation),
30+
abi.encodeWithSignature("dummy()")
31+
);
32+
33+
// Verify upgrade worked by calling new function
34+
vm.expectEmit(true, true, true, true, _eoa);
35+
emit DummyImplementation.DummyCalled();
36+
DummyImplementation(payable(_eoa)).dummy();
37+
}
38+
39+
function testUpgradeToAndCall_succeedsForEOA() public {
40+
// EOA should be able to upgrade
41+
vm.prank(_eoa);
42+
43+
CoinbaseSmartWallet(payable(_eoa)).upgradeToAndCall(
44+
address(newImplementation),
45+
abi.encodeWithSignature("dummy()")
46+
);
47+
48+
// Verify upgrade worked by calling new function
49+
vm.expectEmit(true, true, true, true, _eoa);
50+
emit DummyImplementation.DummyCalled();
51+
DummyImplementation(payable(_eoa)).dummy();
52+
}
53+
54+
function testUpgradeToAndCall_revertsForNonOwner() public {
55+
vm.prank(address(0xBAD));
56+
vm.expectRevert(); // CoinbaseSmartWallet will revert for non-owner
57+
CoinbaseSmartWallet(payable(_eoa)).upgradeToAndCall(
58+
address(newImplementation),
59+
""
60+
);
61+
}
62+
}
63+
64+
contract DummyImplementation is UUPSUpgradeable {
65+
event DummyCalled();
66+
67+
function dummy() external {
68+
emit DummyCalled();
69+
}
70+
71+
function _authorizeUpgrade(address) internal override {}
72+
}

0 commit comments

Comments
 (0)