Skip to content

Commit

Permalink
✨ 4337 style aggregation
Browse files Browse the repository at this point in the history
foo
  • Loading branch information
zeroknots committed Mar 4, 2024
1 parent 88716ca commit 715ae4a
Show file tree
Hide file tree
Showing 10 changed files with 3,620 additions and 315 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"devDependencies": {
"ds-test": "github:dapphub/ds-test#e282159d5170298eb2455a6c05280ab5a73a4ef0",
"@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop",
"forge-std": "github:foundry-rs/forge-std#v1.7.6",
"solmate": "github:transmissions11/solmate#c892309933b25c03d32b1b0d674df7ae292ba925",
"solady": "github:vectorized/solady#9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e",
Expand Down
3,791 changes: 3,486 additions & 305 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@openzeppelin/=node_modules/@openzeppelin/
@ERC4337/=node_modules/@ERC4337/
solmate/=node_modules/solmate/src/
solady/=node_modules/solady/src/
solady/=node_modules/solady/
forge-std/=node_modules/forge-std/src/
ds-test/=node_modules/ds-test/src/
52 changes: 52 additions & 0 deletions src/core/Aggregator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.24;

import { IAggregator } from "@ERC4337/account-abstraction/contracts/interfaces/IAggregator.sol";
import { PackedUserOperation } from "@ERC4337/account-abstraction/contracts/interfaces/PackedUserOperation.sol";
import { ModuleType } from "../DataTypes.sol";


interface ValidatorSelection {

function getValidator(PackedUserOperation calldata userOp) external view returns (address validator);

}

abstract contract Aggregator is IAggregator {
function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) external view {
uint256 length = userOps.length;

for (uint256 i; i < length; i++) {
PackedUserOperation calldata userOp = userOps[i];
address smartAccount = userOp.sender;
address validator = _getValidator(userOp);
_check(smartAccount, validator, ModuleType.wrap(1));
}

}
function validateUserOpSignature(PackedUserOperation calldata userOp) external view returns (bytes memory sigForUserOp) { }

function _getValidator(PackedUserOperation calldata userOp) internal pure returns (address validator) {
uint256 nonce = userOp.nonce;
assembly {
validator := shr(96, nonce)
}
// address validator = ValidatorSelection(smartAccount).getValidator(userOp);
}



function aggregateSignatures(PackedUserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature) {
uint256 length = userOps.length;

for (uint256 i; i < length; i++) {
PackedUserOperation calldata userOp = userOps[i];
address validator = _getValidator(userOp);
address smartAccount = userOp.sender;
_check(smartAccount, validator, ModuleType.wrap(1));

}
}

function _check(address smartAccount, address module, ModuleType moduleType) internal view virtual;
}
1 change: 1 addition & 0 deletions src/core/Attestation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.24;

import { AttestationRecord, AttestationRequest, RevocationRequest, SchemaUID } from "../DataTypes.sol";
import { AttestationManager } from "./AttestationManager.sol";
import { Aggregator } from "./Aggregator.sol";
import { IRegistry } from "../IRegistry.sol";

/**
Expand Down
4 changes: 2 additions & 2 deletions src/core/SignedAttestation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pragma solidity ^0.8.24;
import { Attestation } from "./Attestation.sol";
import { AttestationRequest, RevocationRequest, SchemaUID } from "../DataTypes.sol";
import { AttestationLib } from "../lib/AttestationLib.sol";
import { EIP712 } from "solady/utils/EIP712.sol";
import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol";
import { EIP712 } from "solady/src/utils/EIP712.sol";
import { SignatureCheckerLib } from "solady/src/utils/SignatureCheckerLib.sol";
import { IRegistry } from "../IRegistry.sol";

/**
Expand Down
7 changes: 4 additions & 3 deletions src/core/TrustManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { ZERO_MODULE_TYPE, ZERO_ADDRESS } from "../Common.sol";
import { IRegistry, IERC7484 } from "../IRegistry.sol";
import { ModuleTypeLib } from "../lib/ModuleTypeLib.sol";
import { TrustLib } from "../lib/TrustLib.sol";
import { LibSort } from "solady/utils/LibSort.sol";
import { Aggregator } from "./Aggregator.sol";
import { LibSort } from "solady/src/utils/LibSort.sol";

/**
* Allows smart accounts to query the registry for the security status of modules.
Expand All @@ -18,7 +19,7 @@ import { LibSort } from "solady/utils/LibSort.sol";
* @dev This contract is abstract and provides utility functions to query attestations.
* @author rhinestone | zeroknots.eth, Konrad Kopp (@kopy-kat)
*/
abstract contract TrustManager is IRegistry {
abstract contract TrustManager is IRegistry, Aggregator {
using ModuleTypeLib for PackedModuleTypes;
using TrustLib for AttestationRecord;
using LibSort for address[];
Expand Down Expand Up @@ -97,7 +98,7 @@ abstract contract TrustManager is IRegistry {
* @param module address of the module to check
* @param moduleType (optional param), setting moduleType = 0, will ignore moduleTypes in attestations
*/
function _check(address smartAccount, address module, ModuleType moduleType) internal view {
function _check(address smartAccount, address module, ModuleType moduleType) internal view override {
TrustedAttesterRecord storage $trustedAttesters = $accountToAttester[smartAccount];
// SLOAD from one slot
uint256 attesterCount = $trustedAttesters.attesterCount;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/AttestationLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.24;

import { AttestationRequest, RevocationRequest, AttestationDataRef } from "../DataTypes.sol";
import { SSTORE2 } from "solady/utils/SSTORE2.sol";
import { SSTORE2 } from "solady/src/utils/SSTORE2.sol";

library AttestationLib {
// The hash of the data type used to relay calls to the attest function. It's the value of
Expand Down
68 changes: 68 additions & 0 deletions test/Aggregator.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.24;

import "./TrustDelegation.t.sol";
import { PackedUserOperation } from "@ERC4337/account-abstraction/contracts/interfaces/PackedUserOperation.sol";

contract AggregatorTest is TrustTest {
function setUp() public override {
super.setUp();

address[] memory attesters = new address[](1);
attesters[0] = address(attester1.addr);
_make_WhenUsingValidECDSA(attester1);
test_WhenSupplyingManyAttesters(1, attesters);
}

function test_aggregate() public {
PackedUserOperation[] memory userOps = new PackedUserOperation[](1);
userOps[0] = PackedUserOperation({
sender: smartAccount1.addr,
nonce: getNonce(1, address(module1)),
initCode: "",
callData: "",
accountGasLimits: bytes32(abi.encodePacked(uint128(2e6), uint128(2e6))),
preVerificationGas: 2e6,
gasFees: bytes32(abi.encodePacked(uint128(2e6), uint128(2e6))),
paymasterAndData: bytes(""),
signature: abi.encodePacked(hex"41414141")
});

// userOps[1] = PackedUserOperation({
// sender: smartAccount2.addr,
// nonce: getNonce(1, address(module1)),
// initCode: "",
// callData: "",
// accountGasLimits: bytes32(abi.encodePacked(uint128(2e6), uint128(2e6))),
// preVerificationGas: 2e6,
// gasFees: bytes32(abi.encodePacked(uint128(2e6), uint128(2e6))),
// paymasterAndData: bytes(""),
// signature: abi.encodePacked(hex"41414141")
// });
bytes memory sig = registry.aggregateSignatures(userOps);

registry.validateSignatures(userOps, sig);
}

function getNonce(uint256 _nonce, address validator) internal view returns (uint256 nonce) {
uint192 key = uint192(bytes24(bytes20(address(validator))));
nonce = _nonce | uint256(key) << 64;
}

function signatureInNonce(
address account,
uint256 nonce,
PackedUserOperation memory userOp,
address validator,
bytes memory signature
)
internal
view
returns (PackedUserOperation memory)
{
userOp.nonce = getNonce(nonce, validator);
userOp.signature = signature;

return userOp;
}
}
6 changes: 3 additions & 3 deletions test/TrustDelegation.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { LibSort } from "solady/utils/LibSort.sol";
contract TrustTest is AttestationTest {
using LibSort for address[];

function setUp() public override {
function setUp() public virtual override {
super.setUp();
// test_WhenAttestingWithNoAttestationData(address(module1));
}
Expand All @@ -17,7 +17,7 @@ contract TrustTest is AttestationTest {
_;
}

function test_WhenSupplyingOneAttester() external whenSettingAttester prankWithAccount(smartAccount1) {
function test_WhenSupplyingOneAttester() public whenSettingAttester prankWithAccount(smartAccount1) {
// It should set.
address[] memory trustedAttesters = new address[](1);
trustedAttesters[0] = address(attester1.addr);
Expand All @@ -31,7 +31,7 @@ contract TrustTest is AttestationTest {
uint8 threshold,
address[] memory attesters
)
external
public
whenSettingAttester
prankWithAccount(smartAccount1)
{
Expand Down

0 comments on commit 715ae4a

Please sign in to comment.