Skip to content

Commit

Permalink
fix: [spearbit-94] runtime validation bypass special to only allow in…
Browse files Browse the repository at this point in the history
…stallPlugin and upgradeToAndCall
  • Loading branch information
fangting-alchemy committed Dec 18, 2023
1 parent 9d2fc29 commit c9bb5f8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,8 @@ contract UpgradeableModularAccount is
&& (
(
msg.sig != IPluginManager.installPlugin.selector
|| msg.sig != UUPSUpgradeable.upgradeToAndCall.selector
) && msg.sender != address(this)
&& msg.sig != UUPSUpgradeable.upgradeToAndCall.selector
) || msg.sender != address(this)
)
) {
// Runtime calls cannot be made against functions with no
Expand Down
30 changes: 30 additions & 0 deletions test/account/UpgradeableModularAccountPluginManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,36 @@ contract UpgradeableModularAccountPluginManagerTest is Test {
IStandardExecutor(account2).executeBatch(calls);
}

function test_uninstallAndInstallInBatch_failwithOtherCalls() external {
// Test fail case for a special use case in `installPlugin`:
// We can uninstall the `MultiOwnerPlugin`, leaving no validator on `installPlugin`, and then install a
// different plugin immediately after as part of the same batch execution. This is a special case: normally
// an execution function with no runtime validator cannot be runtime-called.
// Here we test only the above is allowed, any other self-call is blocked

vm.startPrank(owner2);

Call[] memory calls = new Call[](2);
calls[0] = Call({
target: address(account2),
value: 0,
data: abi.encodeCall(IPluginManager.uninstallPlugin, (address(multiOwnerPlugin), "", "", new bytes[](0)))
});
calls[1] = Call({
target: address(account2),
value: 0,
data: abi.encodeCall(UpgradeableModularAccount.execute, (ethRecipient, 1 wei, ""))
});

vm.expectRevert(
abi.encodeWithSelector(
UpgradeableModularAccount.RuntimeValidationFunctionMissing.selector,
UpgradeableModularAccount.execute.selector
)
);
IStandardExecutor(account2).executeBatch(calls);
}

function test_noNonSelfInstallAfterUninstall() external {
// A companion to the previous test, ensuring that `installPlugin` can't
// be called directly (e.g. not via `execute` or `executeBatch`) if it
Expand Down

0 comments on commit c9bb5f8

Please sign in to comment.