Skip to content

Commit 5d85559

Browse files
committed
Add replayable applyOwnerChanges
1 parent 2582a27 commit 5d85559

3 files changed

Lines changed: 35 additions & 27 deletions

File tree

src/AccountConfiguration.sol

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ contract AccountConfiguration {
3535
// INITIALIZATION
3636
////////
3737

38-
/// @notice Designed for 7702 accounts to initialize on first use
39-
function initializeAccount() external {}
40-
4138
function createAccount(
4239
Owner[] calldata initialOwners,
4340
uint256 nonce,
@@ -82,21 +79,25 @@ contract AccountConfiguration {
8279
}
8380

8481
function removeOwner(bytes32 ownerId) external {
85-
require(isOwner(msg.sender, ownerId));
86-
delete verifiers[ownerId][msg.sender];
87-
emit OwnerRemoved(msg.sender, ownerId);
82+
_removeOwner(msg.sender, ownerId);
8883
}
8984

90-
/// @notice Apply signed, replayable owner changes
91-
function applyOwnerChanges(address account, uint64 startSequence, OwnerChange[] calldata ownerChanges) external {
92-
// // validate signature
93-
// if (startSequence != ownerChangeSequence[account]) revert InvalidOwnerChangeSequence(startSequence, ownerChangeSequence[account]);
94-
// for (uint256 i; i < ownerChanges.length; i++) {
95-
// if (ownerChangeSequence[account] != ownerChanges[i].sequence) revert InvalidOwnerChange(ownerChanges[i]);
96-
// ownerChangeSequence[account]++;
97-
// // update account owner configuration
98-
// }
99-
// emit (account, ownerChanges);
85+
/// @notice Apply replayable owner changes
86+
function applyOwnerChanges(
87+
address account,
88+
OwnerChange[] calldata ownerChanges,
89+
bytes32 ownerId,
90+
bytes calldata verifyData
91+
) external {
92+
bytes32 digest = keccak256(abi.encode(account, ownerChanges, ownerChangeSequence[account]++));
93+
require(IVerifier(verifiers[ownerId][account]).verify(account, ownerId, digest, verifyData));
94+
for (uint256 i; i < ownerChanges.length; i++) {
95+
if (ownerChanges[i].add) {
96+
_addOwner(account, ownerChanges[i].owner);
97+
} else {
98+
_removeOwner(account, ownerChanges[i].owner.id);
99+
}
100+
}
100101
}
101102

102103
////////
@@ -147,7 +148,7 @@ contract AccountConfiguration {
147148
}
148149

149150
////////
150-
// INTERNAL FUNCTIONS
151+
// INTERNALS
151152
////////
152153

153154
function _addOwner(address account, Owner calldata owner) internal {
@@ -156,4 +157,10 @@ contract AccountConfiguration {
156157
verifiers[owner.id][account] = owner.verifier;
157158
emit OwnerAdded(account, owner.id, owner.verifier);
158159
}
160+
161+
function _removeOwner(address account, bytes32 ownerId) internal {
162+
require(isOwner(account, ownerId));
163+
delete verifiers[ownerId][account];
164+
emit OwnerRemoved(account, ownerId);
165+
}
159166
}

src/verifiers/IVerifier.sol

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22
pragma solidity ^0.8.0;
33

44
interface IVerifier {
5-
function verify(address account, bytes32 ownerId, bytes32 hash, bytes calldata signature)
6-
external
7-
pure
8-
returns (bool);
5+
/// @notice Verify a signature for a given account, ownerId, hash, and data
6+
///
7+
/// @param account The account to verify the signature for
8+
/// @param ownerId The ownerId to verify the signature for
9+
/// @param hash The hash to verify the signature for
10+
/// @param data The data to verify the signature for
11+
///
12+
/// @return true if the signature is valid, false otherwise
13+
function verify(address account, bytes32 ownerId, bytes32 hash, bytes calldata data) external pure returns (bool);
914
}

src/verifiers/Secp256K1Verifier.sol

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,12 @@ pragma solidity ^0.8.0;
44
import {IVerifier} from "./IVerifier.sol";
55

66
contract Secp256K1Verifier is IVerifier {
7-
function verify(address account, bytes32 ownerId, bytes32 hash, bytes calldata signature)
8-
external
9-
pure
10-
returns (bool)
11-
{
7+
function verify(address account, bytes32 ownerId, bytes32 hash, bytes calldata data) external pure returns (bool) {
128
// Commitment must be a valid address
139
require(uint256(ownerId) < type(uint160).max && uint256(ownerId) > 0);
1410

1511
// Signature must not be malleable
16-
(uint8 v, bytes32 r, bytes32 s) = abi.decode(signature, (uint8, bytes32, bytes32));
12+
(uint8 v, bytes32 r, bytes32 s) = abi.decode(data, (uint8, bytes32, bytes32));
1713
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0); // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol#L176-L184
1814

1915
// Recover address from signature

0 commit comments

Comments
 (0)