Aere Network public source. Everything here can be checked against the live chain (chain id 2800, https://rpc.aere.network). Scope note, stated up front rather than buried: consensus on chain 2800 is classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at the signature, precompile, account and transport layers. Nothing here makes the consensus post-quantum, and no document in it should be read as claiming so.
62 lines
2.5 KiB
Solidity
62 lines
2.5 KiB
Solidity
// SPDX-License-Identifier: LGPL-3.0-only
|
|
pragma solidity 0.8.23;
|
|
|
|
import {AereThresholdAccount} from "./AereThresholdAccount.sol";
|
|
|
|
/// @title AereThresholdAccountFactory
|
|
/// @notice Deterministic (CREATE2) factory for non-custodial post-quantum threshold accounts.
|
|
/// The account address is a pure function of (entryPoint, scheme, threshold, pubKeys,
|
|
/// salt), so it can be counterfactually funded before deployment. Permissionless; the
|
|
/// factory holds no authority over any account it deploys.
|
|
contract AereThresholdAccountFactory {
|
|
event AccountCreated(address indexed account, uint8 scheme, uint8 threshold, uint8 size, bytes32 salt);
|
|
|
|
/// @notice Deploy (or return the existing) threshold account for the given committee + salt.
|
|
function createAccount(
|
|
address entryPoint,
|
|
uint8 scheme,
|
|
uint8 threshold,
|
|
bytes[] calldata pubKeys,
|
|
bytes32 salt
|
|
) external returns (address account) {
|
|
bytes32 create2Salt = _salt(entryPoint, scheme, threshold, pubKeys, salt);
|
|
address predicted = _addressFor(create2Salt);
|
|
if (predicted.code.length > 0) {
|
|
return predicted; // idempotent
|
|
}
|
|
AereThresholdAccount acc = new AereThresholdAccount{salt: create2Salt}();
|
|
acc.initialize(entryPoint, scheme, threshold, pubKeys);
|
|
account = address(acc);
|
|
require(account == predicted, "addr mismatch");
|
|
emit AccountCreated(account, scheme, threshold, uint8(pubKeys.length), salt);
|
|
}
|
|
|
|
/// @notice The counterfactual address of the account for the given committee + salt.
|
|
function computeAddress(
|
|
address entryPoint,
|
|
uint8 scheme,
|
|
uint8 threshold,
|
|
bytes[] calldata pubKeys,
|
|
bytes32 salt
|
|
) external view returns (address) {
|
|
return _addressFor(_salt(entryPoint, scheme, threshold, pubKeys, salt));
|
|
}
|
|
|
|
function _salt(
|
|
address entryPoint,
|
|
uint8 scheme,
|
|
uint8 threshold,
|
|
bytes[] calldata pubKeys,
|
|
bytes32 salt
|
|
) internal pure returns (bytes32) {
|
|
return keccak256(abi.encode(entryPoint, scheme, threshold, keccak256(abi.encode(pubKeys)), salt));
|
|
}
|
|
|
|
function _addressFor(bytes32 create2Salt) internal view returns (address) {
|
|
bytes32 h = keccak256(
|
|
abi.encodePacked(bytes1(0xff), address(this), create2Salt, keccak256(type(AereThresholdAccount).creationCode))
|
|
);
|
|
return address(uint160(uint256(h)));
|
|
}
|
|
}
|