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

Implemented EIP interface changes #23

Merged
merged 6 commits into from
Aug 1, 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
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/openzeppelin/openzeppelin-contracts
[submodule "lib/reference"]
path = lib/reference
url = https://github.com/erc6551/reference
[submodule "lib/account-abstraction"]
path = lib/account-abstraction
url = https://github.com/eth-infinitism/account-abstraction
[submodule "lib/erc6551"]
path = lib/erc6551
url = https://github.com/erc6551/reference
1 change: 1 addition & 0 deletions lib/erc6551
Submodule erc6551 added at df75cd
1 change: 0 additions & 1 deletion lib/reference
Submodule reference deleted from 1a5b00
3 changes: 1 addition & 2 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
account-abstraction/=lib/account-abstraction/contracts/
erc6551/=lib/reference/src/
erc6551/=lib/erc6551/src/
ds-test/=lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
forge-std/=lib/forge-std/src/
openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/
@openzeppelin/=lib/openzeppelin-contracts/
73 changes: 40 additions & 33 deletions src/Account.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
pragma solidity ^0.8.13;

import "erc6551/interfaces/IERC6551Account.sol";
import "erc6551/interfaces/IERC6551Executable.sol";
import "erc6551/lib/ERC6551AccountLib.sol";

import "openzeppelin-contracts/utils/cryptography/ECDSA.sol";
import "openzeppelin-contracts/utils/introspection/IERC165.sol";
import "openzeppelin-contracts/token/ERC721/IERC721.sol";
import "openzeppelin-contracts/token/ERC721/IERC721Receiver.sol";
import "openzeppelin-contracts/token/ERC1155/IERC1155Receiver.sol";
import "openzeppelin-contracts/interfaces/IERC1271.sol";
import "openzeppelin-contracts/utils/cryptography/SignatureChecker.sol";
import "openzeppelin-contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";

import {BaseAccount as BaseERC4337Account, IEntryPoint, UserOperation} from "account-abstraction/core/BaseAccount.sol";

Expand All @@ -31,6 +32,7 @@ contract Account is
IERC165,
IERC1271,
IERC6551Account,
IERC6551Executable,
IERC721Receiver,
IERC1155Receiver,
UUPSUpgradeable,
Expand Down Expand Up @@ -100,12 +102,13 @@ contract Account is
}

/// @dev executes a low-level call against an account if the caller is authorized to make calls
function executeCall(
function execute(
address to,
uint256 value,
bytes calldata data
bytes calldata data,
uint256 operation
) external payable onlyAuthorized onlyUnlocked returns (bytes memory) {
emit TransactionExecuted(to, value, data);
require(operation == 0, "Only calls are allowed");

_incrementNonce();

Expand Down Expand Up @@ -191,10 +194,30 @@ contract Account is
return "";
}

/// @dev Returns a magic value if a given signer is valid
function isValidSigner(address signer, bytes calldata)
external
view
returns (bytes4 magicValue)
{
_handleOverrideStatic();

if (signer == owner()) {
return IERC6551Account.isValidSigner.selector;
}

return bytes4(0);
}

/// @dev Returns the current account nonce
function state() external view override returns (uint256) {
return IEntryPoint(_entryPoint).getNonce(address(this), 0);
}

/// @dev Returns the EIP-155 chain ID, token contract address, and token ID for the token that
/// owns this account.
function token()
external
public
view
returns (
uint256 chainId,
Expand All @@ -205,11 +228,6 @@ contract Account is
return ERC6551AccountLib.token();
}

/// @dev Returns the current account nonce
function nonce() public view override returns (uint256) {
return IEntryPoint(_entryPoint).getNonce(address(this), 0);
}

/// @dev Increments the account nonce if the caller is not the ERC-4337 entry point
function _incrementNonce() internal {
if (msg.sender != _entryPoint)
Expand All @@ -224,11 +242,7 @@ contract Account is
/// @dev Returns the owner of the ERC-721 token which owns this account. By default, the owner
/// of the token has full permissions on the account.
function owner() public view returns (address) {
(
uint256 chainId,
address tokenContract,
uint256 tokenId
) = ERC6551AccountLib.token();
(uint256 chainId, address tokenContract, uint256 tokenId) = token();

if (chainId != block.chainid) return address(0);

Expand All @@ -240,11 +254,7 @@ contract Account is
// authorize entrypoint for 4337 transactions
if (caller == _entryPoint) return true;

(
uint256 chainId,
address tokenContract,
uint256 tokenId
) = ERC6551AccountLib.token();
(uint256 chainId, address tokenContract, uint256 tokenId) = token();
address _owner = IERC721(tokenContract).ownerOf(tokenId);

// authorize token owner
Expand Down Expand Up @@ -272,7 +282,8 @@ contract Account is
{
bool defaultSupport = interfaceId == type(IERC165).interfaceId ||
interfaceId == type(IERC1155Receiver).interfaceId ||
interfaceId == type(IERC6551Account).interfaceId;
interfaceId == type(IERC6551Account).interfaceId ||
interfaceId == type(IERC6551Executable).interfaceId;

if (defaultSupport) return true;

Expand All @@ -292,11 +303,7 @@ contract Account is
) public view override returns (bytes4) {
_handleOverrideStatic();

(
uint256 chainId,
address tokenContract,
uint256 tokenId
) = ERC6551AccountLib.token();
(uint256 chainId, address tokenContract, uint256 tokenId) = token();

if (
chainId == block.chainid &&
Expand Down
2 changes: 1 addition & 1 deletion src/AccountGuardian.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "openzeppelin-contracts/access/Ownable2Step.sol";
import "@openzeppelin/contracts/access/Ownable2Step.sol";

// @dev manages upgrade and cross-chain execution settings for accounts
contract AccountGuardian is Ownable2Step {
Expand Down
4 changes: 2 additions & 2 deletions src/AccountProxy.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "openzeppelin-contracts/proxy/ERC1967/ERC1967Upgrade.sol";
import "openzeppelin-contracts/proxy/Proxy.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
import "@openzeppelin/contracts/proxy/Proxy.sol";

error InvalidImplementation();

Expand Down
33 changes: 15 additions & 18 deletions test/Account.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ pragma solidity ^0.8.13;

import "forge-std/Test.sol";

import "openzeppelin-contracts/token/ERC20/ERC20.sol";
import "openzeppelin-contracts/proxy/Clones.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/proxy/Clones.sol";

import "account-abstraction/core/EntryPoint.sol";

Expand Down Expand Up @@ -63,7 +63,7 @@ contract AccountTest is Test {
// should fail if user2 tries to use account
vm.prank(user2);
vm.expectRevert(NotAuthorized.selector);
account.executeCall(payable(user2), 0.1 ether, "");
account.execute(payable(user2), 0.1 ether, "", 0);

// should fail if user2 tries to set override
address[] memory callers = new address[](1);
Expand Down Expand Up @@ -103,14 +103,14 @@ contract AccountTest is Test {
// should fail if user2 tries to use account
vm.prank(user2);
vm.expectRevert(NotAuthorized.selector);
account.executeCall(payable(user2), 0.1 ether, "");
account.execute(payable(user2), 0.1 ether, "", 0);

vm.prank(user1);
tokenCollection.safeTransferFrom(user1, user2, tokenId);

// should succeed now that user2 is owner
vm.prank(user2);
account.executeCall(payable(user2), 0.1 ether, "");
account.execute(payable(user2), 0.1 ether, "", 0);

assertEq(user2.balance, 0.1 ether);
}
Expand Down Expand Up @@ -205,7 +205,7 @@ contract AccountTest is Test {
// transaction should revert if account is locked
vm.prank(user1);
vm.expectRevert(AccountLocked.selector);
account.executeCall(payable(user1), 1 ether, "");
account.execute(payable(user1), 1 ether, "", 0);

// fallback calls should revert if account is locked
vm.prank(user1);
Expand All @@ -221,7 +221,7 @@ contract AccountTest is Test {
// setOverrides calls should revert if account is locked
{
bytes4[] memory selectors = new bytes4[](1);
selectors[0] = Account.executeCall.selector;
selectors[0] = Account.execute.selector;
address[] memory implementations = new address[](1);
implementations[0] = vm.addr(1337);
vm.prank(user1);
Expand All @@ -246,7 +246,7 @@ contract AccountTest is Test {

// transaction succeed now that account lock has expired
vm.prank(user1);
account.executeCall(payable(user1), 1 ether, "");
account.execute(payable(user1), 1 ether, "", 0);
assertEq(user1.balance, 1 ether);

// signing should now that account lock has expired
Expand Down Expand Up @@ -390,7 +390,7 @@ contract AccountTest is Test {
assertEq(account.isAuthorized(user2), true);

vm.prank(user2);
account.executeCall(user2, 0.1 ether, "");
account.execute(user2, 0.1 ether, "", 0);

assertEq(user2.balance, 0.1 ether);
}
Expand Down Expand Up @@ -425,14 +425,14 @@ contract AccountTest is Test {
assertEq(account.isAuthorized(crossChainExecutor), true);

vm.prank(crossChainExecutor);
account.executeCall(user1, 0.1 ether, "");
account.execute(user1, 0.1 ether, "", 0);

assertEq(user1.balance, 0.1 ether);

address notCrossChainExecutor = vm.addr(3);
vm.prank(notCrossChainExecutor);
vm.expectRevert(NotAuthorized.selector);
Account(payable(account)).executeCall(user1, 0.1 ether, "");
Account(payable(account)).execute(user1, 0.1 ether, "", 0);

assertEq(user1.balance, 0.1 ether);

Expand All @@ -447,11 +447,7 @@ contract AccountTest is Test {

vm.prank(crossChainExecutor);
vm.expectRevert(NotAuthorized.selector);
Account(payable(nativeAccountAddress)).executeCall(
user1,
0.1 ether,
""
);
Account(payable(nativeAccountAddress)).execute(user1, 0.1 ether, "", 0);

assertEq(user1.balance, 0.1 ether);
}
Expand Down Expand Up @@ -479,10 +475,11 @@ contract AccountTest is Test {

vm.prank(user1);
vm.expectRevert(MockReverter.MockError.selector);
account.executeCall(
account.execute(
payable(address(mockReverter)),
0,
abi.encodeWithSignature("fail()")
abi.encodeWithSignature("fail()"),
0
);
}

Expand Down
14 changes: 8 additions & 6 deletions test/AccountERC1155.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ pragma solidity ^0.8.13;

import "forge-std/Test.sol";

import "openzeppelin-contracts/token/ERC20/ERC20.sol";
import "openzeppelin-contracts/proxy/Clones.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/proxy/Clones.sol";

import "account-abstraction/core/EntryPoint.sol";

Expand Down Expand Up @@ -77,10 +77,11 @@ contract AccountERC1155Test is Test {
""
);
vm.prank(user1);
account.executeCall(
account.execute(
payable(address(dummyERC1155)),
0,
erc1155TransferCall
erc1155TransferCall,
0
);

assertEq(dummyERC1155.balanceOf(accountAddress, 1), 0);
Expand Down Expand Up @@ -117,10 +118,11 @@ contract AccountERC1155Test is Test {
""
);
vm.prank(user1);
account.executeCall(
account.execute(
payable(address(dummyERC1155)),
0,
erc1155TransferCall
erc1155TransferCall,
0
);

assertEq(dummyERC1155.balanceOf(accountAddress, 1), 0);
Expand Down
8 changes: 4 additions & 4 deletions test/AccountERC20.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ pragma solidity ^0.8.13;

import "forge-std/Test.sol";

import "openzeppelin-contracts/token/ERC20/ERC20.sol";
import "openzeppelin-contracts/proxy/Clones.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/proxy/Clones.sol";

import "account-abstraction/core/EntryPoint.sol";

Expand Down Expand Up @@ -73,7 +73,7 @@ contract AccountERC20Test is Test {
1 ether
);
vm.prank(user1);
account.executeCall(payable(address(dummyERC20)), 0, erc20TransferCall);
account.execute(payable(address(dummyERC20)), 0, erc20TransferCall, 0);

assertEq(dummyERC20.balanceOf(accountAddress), 0);
assertEq(dummyERC20.balanceOf(user1), 1 ether);
Expand Down Expand Up @@ -106,7 +106,7 @@ contract AccountERC20Test is Test {
1 ether
);
vm.prank(user1);
account.executeCall(payable(address(dummyERC20)), 0, erc20TransferCall);
account.execute(payable(address(dummyERC20)), 0, erc20TransferCall, 0);

assertEq(dummyERC20.balanceOf(accountAddress), 0);
assertEq(dummyERC20.balanceOf(user1), 1 ether);
Expand Down
Loading
Loading