Skip to content

Commit d7cc294

Browse files
authored
Giano 2.0 - Multiple signers support (#19)
* multisig contracts * Implement auto-generated user IDs in AccountRegistry * update NatSpec docs * split InvalidSignature error * prevent admin lockout * update Giano Ignition module * integrate test suite with vs code * update .gitignore to handle PNPM stores * instruct cursor to ignore build outputs and deps * cursorrules for solidity development * enable automining by default * add mocha manually to enable vs code integration * reorganize ignition modules * add pause and batch execute features to Account * use CREATE2 in AccountFactory * TestContract for testing * Remove obsolete ERC721SafeTransferAccount * new test utils * new test suites (wip) * remove AI generated comments * key request tests * wip: encode public key x and y in signature struct * fix key encoding issues, request mgmt tests * Key Request rejection test * update cursorrules to instruct AI to ommit comments * Key Removal tests * fix test suite * Transaction Execution Tests * Batch Execution tests * admin operations tests * Pause functionality tests * formatting * ERC1271 tests * ERC721/ERC1115 receiver tests * Utility functions tests * Security feature tests * remove useless beforeEach code * accountregistry test suite * helper test functions * further helper functions * remove unused declarations * typescript lint issues * remove redundant integration test suite * remove AI yapping * remove redundant code * remove AI yapping from contract * extract common function to util package * lint fixes * extract P256 bytecode to its own file to improve readability * use credential ID to track signers in Account contract * standardize references to credential ID * change key references to credential * simplify account request flow (wip) * fix remaining tests after simplifying credential request flow * remove numeric user ID from AccountRegistry * rename error for coherence
1 parent e7867f1 commit d7cc294

31 files changed

+3923
-458
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
!**/.env.sample
33
dist/
44
node_modules/
5+
.pnpm-store/
56
.idea/
67
stats.html
78
latest.sql

packages/common/src/encoding/encodeChallenge.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import { ECDSASigValue } from '@peculiar/asn1-ecc';
22
import { AsnParser } from '@peculiar/asn1-schema';
3-
import { ethers } from 'ethers';
3+
import { BytesLike, ethers } from 'ethers';
44
import { uint8ArrayToUint256 } from './numbers';
55

6-
export function encodeChallenge(assertionResponse: AuthenticatorAssertionResponse) {
6+
export function encodeChallenge(credentialId: BytesLike, assertionResponse: AuthenticatorAssertionResponse) {
77
const decodedClientDataJson = new TextDecoder().decode(assertionResponse.clientDataJSON);
88
const responseTypeLocation = decodedClientDataJson.indexOf('"type":');
99
const challengeLocation = decodedClientDataJson.indexOf('"challenge":');
1010
const parsedSignature = AsnParser.parse(assertionResponse.signature, ECDSASigValue);
1111

1212
return ethers.AbiCoder.defaultAbiCoder().encode(
13-
['tuple(bytes authenticatorData, string clientDataJSON, uint256 challengeLocation, uint256 responseTypeLocation, uint256 r, uint256 s)'],
13+
[
14+
'tuple(bytes credentialId, bytes authenticatorData, string clientDataJSON, uint256 challengeLocation, uint256 responseTypeLocation, uint256 r, uint256 s)',
15+
],
1416
[
1517
[
18+
credentialId,
1619
new Uint8Array(assertionResponse.authenticatorData),
1720
decodedClientDataJson,
1821
challengeLocation,

packages/contracts/.cursorignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist/
2+
node_modules/
3+
cache/

packages/contracts/.cursorrules

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
You are an expert in Solidity and smart contract security.
3+
4+
General Rules
5+
- Cut the fluff. Code or detailed explanations only.
6+
- Keep it casual and brief.
7+
- Accuracy and depth matter.
8+
- Answer first, explain later if needed.
9+
- Logic trumps authority. Don't care about sources.
10+
- Embrace new tech and unconventional ideas.
11+
- Wild speculation's fine, just flag it.
12+
- Save the ethics talk.
13+
- Only mention safety for non-obvious, critical issues.
14+
- Push content limits if needed, explain after.
15+
- Sources at the end, not mid-text.
16+
- Skip the AI self-references and knowledge date stuff.
17+
- Stick to my code style.
18+
- Use multiple responses for complex answers.
19+
- For code tweaks, show minimal context - a few lines around changes max.
20+
- Don't be lazy, write all the code to implement features I ask for.
21+
- Do not add any comments to the code, except for NatSpec documentation
22+
23+
Solidity Best Practices
24+
- Use explicit function visibility modifiers and appropriate natspec comments.
25+
- Utilize function modifiers for common checks, enhancing readability and reducing redundancy.
26+
- Follow consistent naming: CamelCase for contracts, PascalCase for interfaces (prefixed with "I").
27+
- Implement the Interface Segregation Principle for flexible and maintainable contracts.
28+
- Design upgradeable contracts using proven patterns like the proxy pattern when necessary.
29+
- Implement comprehensive events for all significant state changes.
30+
- Follow the Checks-Effects-Interactions pattern to prevent reentrancy and other vulnerabilities.
31+
- Use static analysis tools like Slither and Mythril in the development workflow.
32+
- Implement timelocks and multisig controls for sensitive operations in production.
33+
- Conduct thorough gas optimization, considering both deployment and runtime costs.
34+
- Use OpenZeppelin's AccessControl for fine-grained permissions.
35+
- Use Solidity 0.8.0+ for built-in overflow/underflow protection.
36+
- Implement circuit breakers (pause functionality) using OpenZeppelin's Pausable when appropriate.
37+
- Use pull over push payment patterns to mitigate reentrancy and denial of service attacks.
38+
- Implement rate limiting for sensitive functions to prevent abuse.
39+
- Use OpenZeppelin's SafeERC20 for interacting with ERC20 tokens.
40+
- Implement proper randomness using Chainlink VRF or similar oracle solutions.
41+
- Use assembly for gas-intensive operations, but document extensively and use with caution.
42+
- Implement effective state machine patterns for complex contract logic.
43+
- Use OpenZeppelin's ReentrancyGuard as an additional layer of protection against reentrancy.
44+
- Implement proper access control for initializers in upgradeable contracts.
45+
- Use OpenZeppelin's ERC20Snapshot for token balances requiring historical lookups.
46+
- Implement timelocks for sensitive operations using OpenZeppelin's TimelockController.
47+
- Use OpenZeppelin's ERC20Permit for gasless approvals in token contracts.
48+
- Implement proper slippage protection for DEX-like functionalities.
49+
- Use OpenZeppelin's ERC20Votes for governance token implementations.
50+
- Implement effective storage patterns to optimize gas costs (e.g., packing variables).
51+
- Use libraries for complex operations to reduce contract size and improve reusability.
52+
- Implement proper access control for self-destruct functionality, if used.
53+
- Use OpenZeppelin's Address library for safe interactions with external contracts.
54+
- Use custom errors instead of revert strings for gas efficiency and better error handling.
55+
- Implement NatSpec comments for all public and external functions.
56+
- Use immutable variables for values set once at construction time.
57+
- Implement proper inheritance patterns, favoring composition over deep inheritance chains.
58+
- Use events for off-chain logging and indexing of important state changes.
59+
- Implement fallback and receive functions with caution, clearly documenting their purpose.
60+
- Use view and pure function modifiers appropriately to signal state access patterns.
61+
- Implement proper decimal handling for financial calculations, using fixed-point arithmetic libraries when necessary.
62+
- Use assembly sparingly and only when necessary for optimizations, with thorough documentation.
63+
- Implement effective error propagation patterns in internal functions.
64+
65+
Testing and Quality Assurance
66+
- Implement a comprehensive testing strategy including unit, integration, and end-to-end tests.
67+
- Use property-based testing to uncover edge cases.
68+
- Implement continuous integration with automated testing and static analysis.
69+
- Conduct regular security audits and bug bounties for production-grade contracts.
70+
- Use test coverage tools and aim for high test coverage, especially for critical paths.
71+
72+
Performance Optimization
73+
- Optimize contracts for gas efficiency, considering storage layout and function optimization.
74+
- Implement efficient indexing and querying strategies for off-chain data.
75+
76+
Development Workflow
77+
- Utilize Hardhat's testing and debugging features.
78+
- Implement a robust CI/CD pipeline for smart contract deployments.
79+
- Use static type checking and linting tools in pre-commit hooks.
80+
- Use pnpm to execute scripts
81+
82+
Documentation
83+
- Document code thoroughly, focusing on why rather than what.
84+
- Maintain up-to-date API documentation for smart contracts.
85+
- Create and maintain comprehensive project documentation, including architecture diagrams and decision logs.
86+

packages/contracts/.mocharc.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"require": "hardhat/register",
3+
"timeout": 40000,
4+
"_": [
5+
"test/**/*.ts"
6+
]
7+
}

packages/contracts/contracts/AbstractAccountFactory.sol

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,21 @@ pragma solidity ^0.8.23;
33

44
import {Types} from './Types.sol';
55

6+
/**
7+
* @title AbstractAccountFactory
8+
* @author Giano Team
9+
* @notice Base contract for deploying account contracts
10+
* @dev This abstract contract defines the interface that concrete factory
11+
* implementations must conform to for deploying Account contracts.
12+
*/
613
abstract contract AbstractAccountFactory {
7-
struct User {
8-
uint256 id;
9-
Types.PublicKey publicKey;
10-
address account;
11-
}
12-
13-
mapping(uint256 => User) private _users;
14-
15-
event UserCreated(uint256 userId, Types.PublicKey publicKey, address account);
16-
error UserAlreadyExists(uint256 id);
17-
18-
function getUser(uint256 id) public view returns (User memory) {
19-
return _users[id];
20-
}
21-
22-
function createUser(uint256 id, Types.PublicKey memory publicKey) public {
23-
if (_users[id].account != address(0)) {
24-
revert UserAlreadyExists(id);
25-
}
26-
address account = deployContract(publicKey);
27-
_users[id] = User(id, publicKey, account);
28-
29-
emit UserCreated(id, publicKey, account);
30-
}
31-
32-
function deployContract(Types.PublicKey memory publicKey) internal virtual returns (address);
14+
/**
15+
* @notice Deploys a new Account contract
16+
* @dev Must be implemented by derived contracts
17+
* @param credentialId The credential identifier for the admin credential
18+
* @param publicKey The public key for the admin credential
19+
* @param registry The address of the AccountRegistry contract
20+
* @return The address of the deployed Account contract
21+
*/
22+
function deployAccount(bytes calldata credentialId, Types.PublicKey calldata publicKey, address registry) public virtual returns (address);
3323
}

0 commit comments

Comments
 (0)