Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename Execution to Call, and update IStandardExecutor #12

Merged
merged 2 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 12 additions & 26 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import {BaseAccount} from "@eth-infinitism/account-abstraction/core/BaseAccount.
import {BaseModularAccount} from "./BaseModularAccount.sol";
import {BaseModularAccountLoupe} from "./BaseModularAccountLoupe.sol";
import {IPlugin, PluginManifest} from "../interfaces/IPlugin.sol";
import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol";
import {IStandardExecutor, Call} from "../interfaces/IStandardExecutor.sol";
import {IPluginExecutor} from "../interfaces/IPluginExecutor.sol";
import {AccountStorage, getAccountStorage, getPermittedCallKey} from "../libraries/AccountStorage.sol";
import {Execution} from "../libraries/ERC6900TypeUtils.sol";
import {FunctionReference, FunctionReferenceLib} from "../libraries/FunctionReferenceLib.sol";
import {AccountStorageInitializable} from "./AccountStorageInitializable.sol";
import {IPluginManager} from "../interfaces/IPluginManager.sol";
Expand Down Expand Up @@ -137,46 +136,38 @@ contract UpgradeableModularAccount is
return execReturnData;
}

/// @notice Executes a transaction from the account
/// @param execution The execution to perform
/// @return result The result of the execution
function execute(Execution calldata execution)
/// @inheritdoc IStandardExecutor
function execute(address target, uint256 value, bytes calldata data)
external
payable
override
wrapNativeFunction
returns (bytes memory result)
{
result = _exec(execution.target, execution.value, execution.data);
result = _exec(target, value, data);
}

/// @notice Executes a batch of transactions from the account
/// @dev If any of the transactions revert, the entire batch reverts
/// @param executions The executions to perform
/// @return results The results of the executions
function executeBatch(Execution[] calldata executions)
/// @inheritdoc IStandardExecutor
adam-alchemy marked this conversation as resolved.
Show resolved Hide resolved
function executeBatch(Call[] calldata calls)
external
payable
override
wrapNativeFunction
returns (bytes[] memory results)
{
uint256 executionsLength = executions.length;
results = new bytes[](executionsLength);
uint256 callsLength = calls.length;
results = new bytes[](callsLength);

for (uint256 i = 0; i < executionsLength;) {
results[i] = _exec(executions[i].target, executions[i].value, executions[i].data);
for (uint256 i = 0; i < callsLength;) {
results[i] = _exec(calls[i].target, calls[i].value, calls[i].data);

unchecked {
++i;
}
}
}

/// @notice Executes a call from a plugin to another plugin
/// @dev Permissions must be granted to the calling plugin for the call to go through
/// @param data calldata to send to the plugin
/// @return The result of the call
/// @inheritdoc IPluginExecutor
function executeFromPlugin(bytes calldata data) external payable override returns (bytes memory) {
bytes4 selector = bytes4(data[:4]);
address callingPlugin = msg.sender;
Expand Down Expand Up @@ -213,12 +204,7 @@ contract UpgradeableModularAccount is
return returnData;
}

/// @notice Executes a call from a plugin to a non-plugin address
/// @dev Permissions must be granted to the calling plugin for the call to go through
/// @param target address of the target to call
/// @param value value to send with the call
/// @param data calldata to send to the target
/// @return The result of the call
/// @inheritdoc IPluginExecutor
function executeFromPluginExternal(address target, uint256 value, bytes calldata data)
external
payable
Expand Down
18 changes: 10 additions & 8 deletions src/interfaces/IPluginExecutor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
pragma solidity ^0.8.19;

interface IPluginExecutor {
/// @notice Method from calls made from plugins.
/// @param data The call data for the call.
/// @return The return data from the call.
/// @notice Executes a call from a plugin to another plugin.
/// @dev Permissions must be granted to the calling plugin for the call to go through.
/// @param data calldata to send to the plugin
/// @return The result of the call
function executeFromPlugin(bytes calldata data) external payable returns (bytes memory);

/// @notice Method from calls made from plugins.
/// @dev If the target is a plugin, the call SHOULD revert.
/// @param target The target of the external contract to be called.
/// @param value The value to pass.
/// @param data The data to pass.
/// @notice Executes a call from a plugin to a non-plugin address.
/// @dev Permissions must be granted to the calling plugin for the call to go through.
/// @param target address of the target to call
/// @param value value to send with the call
/// @param data calldata to send to the target
/// @return The result of the call
function executeFromPluginExternal(address target, uint256 value, bytes calldata data)
external
payable
Expand Down
23 changes: 17 additions & 6 deletions src/interfaces/IStandardExecutor.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.19;

import {Execution} from "../libraries/ERC6900TypeUtils.sol";
struct Call {
// The target address for account to call.
address target;
// The value sent with the call.
uint256 value;
// The call data for the call.
bytes data;
}

/// @title Standard Executor Interface
interface IStandardExecutor {
/// @notice Standard execute method.
/// @dev If the target is a plugin, the call SHOULD revert.
/// @param execution The execution information.
/// @param target The target address for account to call.
/// @param value The value sent with the call.
/// @param data The call data for the call.
/// @return The return data from the call.
function execute(Execution calldata execution) external payable returns (bytes memory);
function execute(address target, uint256 value, bytes calldata data) external payable returns (bytes memory);

/// @notice Standard executeBatch method.
/// @dev If the target is a plugin, the call SHOULD revert.
/// @param executions The array of executions.
/// @dev If the target is a plugin, the call SHOULD revert. If any of the transactions revert, the entire batch
/// reverts.
/// @param calls The array of calls.
/// @return An array containing the return data from the calls.
function executeBatch(Execution[] calldata executions) external payable returns (bytes[] memory);
function executeBatch(Call[] calldata calls) external payable returns (bytes[] memory);
}
11 changes: 0 additions & 11 deletions src/libraries/ERC6900TypeUtils.sol

This file was deleted.

13 changes: 6 additions & 7 deletions test/account/AccountReturnData.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {IPluginManager} from "../../src/interfaces/IPluginManager.sol";
import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol";
import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol";
import {FunctionReference} from "../../src/libraries/FunctionReferenceLib.sol";
import {Execution} from "../../src/libraries/ERC6900TypeUtils.sol";
import {Call} from "../../src/interfaces/IStandardExecutor.sol";

import {
RegularResultContract,
Expand Down Expand Up @@ -72,9 +72,8 @@ contract AccountReturnDataTest is Test {

// Tests the ability to read the results of contracts called via IStandardExecutor.execute
function test_returnData_singular_execute() public {
bytes memory returnData = account.execute(
Execution(address(regularResultContract), 0, abi.encodeCall(RegularResultContract.foo, ()))
);
bytes memory returnData =
account.execute(address(regularResultContract), 0, abi.encodeCall(RegularResultContract.foo, ()));

bytes32 result = abi.decode(returnData, (bytes32));

Expand All @@ -83,13 +82,13 @@ contract AccountReturnDataTest is Test {

// Tests the ability to read the results of multiple contract calls via IStandardExecutor.executeBatch
function test_returnData_executeBatch() public {
Execution[] memory calls = new Execution[](2);
calls[0] = Execution({
Call[] memory calls = new Call[](2);
calls[0] = Call({
target: address(regularResultContract),
value: 0,
data: abi.encodeCall(RegularResultContract.foo, ())
});
calls[1] = Execution({
calls[1] = Call({
target: address(regularResultContract),
value: 0,
data: abi.encodeCall(RegularResultContract.bar, ())
Expand Down
26 changes: 9 additions & 17 deletions test/account/UpgradeableModularAccount.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {PluginManifest} from "../../src/interfaces/IPlugin.sol";
import {IPluginLoupe} from "../../src/interfaces/IPluginLoupe.sol";
import {IPluginManager} from "../../src/interfaces/IPluginManager.sol";
import {IPluginExecutor} from "../../src/interfaces/IPluginExecutor.sol";
import {Execution} from "../../src/libraries/ERC6900TypeUtils.sol";
import {Call} from "../../src/interfaces/IStandardExecutor.sol";
import {FunctionReference} from "../../src/libraries/FunctionReferenceLib.sol";
import {IPlugin, PluginManifest} from "../../src/interfaces/IPlugin.sol";

Expand Down Expand Up @@ -122,9 +122,7 @@ contract UpgradeableModularAccountTest is Test {
sender: address(account1),
nonce: 0,
initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner1, 0))),
callData: abi.encodeCall(
UpgradeableModularAccount(payable(account1)).execute, Execution(recipient, 1 wei, "")
),
callData: abi.encodeCall(UpgradeableModularAccount.execute, (recipient, 1 wei, "")),
callGasLimit: CALL_GAS_LIMIT,
verificationGasLimit: VERIFICATION_GAS_LIMIT,
preVerificationGas: 0,
Expand Down Expand Up @@ -152,9 +150,7 @@ contract UpgradeableModularAccountTest is Test {
sender: address(account2),
nonce: 0,
initCode: "",
callData: abi.encodeCall(
UpgradeableModularAccount(payable(account2)).execute, Execution(ethRecipient, 1 wei, "")
),
callData: abi.encodeCall(UpgradeableModularAccount.execute, (ethRecipient, 1 wei, "")),
callGasLimit: CALL_GAS_LIMIT,
verificationGasLimit: VERIFICATION_GAS_LIMIT,
preVerificationGas: 0,
Expand Down Expand Up @@ -182,9 +178,7 @@ contract UpgradeableModularAccountTest is Test {
sender: address(account2),
nonce: 0,
initCode: "",
callData: abi.encodeCall(
UpgradeableModularAccount(payable(account2)).execute, Execution(ethRecipient, 1 wei, "")
),
callData: abi.encodeCall(UpgradeableModularAccount.execute, (ethRecipient, 1 wei, "")),
callGasLimit: CALL_GAS_LIMIT,
verificationGasLimit: VERIFICATION_GAS_LIMIT,
preVerificationGas: 0,
Expand Down Expand Up @@ -213,8 +207,7 @@ contract UpgradeableModularAccountTest is Test {
nonce: 0,
initCode: "",
callData: abi.encodeCall(
UpgradeableModularAccount(payable(account2)).execute,
Execution(address(counter), 0, abi.encodeCall(counter.increment, ()))
UpgradeableModularAccount.execute, (address(counter), 0, abi.encodeCall(counter.increment, ()))
),
callGasLimit: CALL_GAS_LIMIT,
verificationGasLimit: VERIFICATION_GAS_LIMIT,
Expand All @@ -240,16 +233,15 @@ contract UpgradeableModularAccountTest is Test {

function test_batchExecute() public {
// Performs both an eth send and a contract interaction with counter
Execution[] memory executions = new Execution[](2);
executions[0] = Execution({target: ethRecipient, value: 1 wei, data: ""});
executions[1] =
Execution({target: address(counter), value: 0, data: abi.encodeCall(counter.increment, ())});
Call[] memory calls = new Call[](2);
calls[0] = Call({target: ethRecipient, value: 1 wei, data: ""});
calls[1] = Call({target: address(counter), value: 0, data: abi.encodeCall(counter.increment, ())});

UserOperation memory userOp = UserOperation({
sender: address(account2),
nonce: 0,
initCode: "",
callData: abi.encodeCall(UpgradeableModularAccount(payable(account2)).executeBatch, (executions)),
callData: abi.encodeCall(UpgradeableModularAccount.executeBatch, (calls)),
callGasLimit: CALL_GAS_LIMIT,
verificationGasLimit: VERIFICATION_GAS_LIMIT,
preVerificationGas: 0,
Expand Down