OpenZeppelin / cairo-contracts

OpenZeppelin Contracts written in Cairo for Starknet, a decentralized ZK Rollup
https://docs.openzeppelin.com/contracts-cairo
MIT License
797 stars 321 forks source link

Enhancements and Security Concerns in OpenZeppelin Cairo Contract for StarkNet #943

Closed fruitbox12 closed 3 months ago

fruitbox12 commented 3 months ago

🧐 Motivation Improving the OpenZeppelin Cairo contract's Account component on StarkNet is crucial for enhancing security, efficiency, and developer experience. Specific code segments and patterns I have looked at or used where targeted improvements might mitigate potential vulnerabilities, optimize performance, and improve readability. IDK :P

πŸ“ Details Look into a Stricter Caller Verification: As of now ^.^ , the method to prevent unauthorized calls is based on a simple check: assert(sender.is_zero(), Errors::INVALID_CALLER);. This might not be sufficient for all security contexts. Enhancing this check to consider more scenarios can fortify the contract against unauthorized access attempts.

let sender = get_caller_address();
assert(sender.is_zero(), Errors::INVALID_CALLER);
Suggestion: Implement a more robust verification mechanism that accounts for different types of calls and contexts, enhancing the contract's security.

Robust Signature Validation: The function is_valid_signature plays a vital role in ensuring transaction integrity but might be prone to oversights in its current form. Reviewing its logic and potentially incorporating additional checks could prevent exploits.

fn is_valid_signature(
    self: @ComponentState<TContractState>, hash: felt252, signature: Array<felt252>
) -> felt252 {
    if self._is_valid_signature(hash, signature.span()) {
        starknet::VALIDATED
    } else {
        0
    }
}

Suggestion: Enhance the signature validation process with additional safeguards to protect against advanced security threats.

Efficiency and Gas Optimization Optimize Storage Access: Repeated storage operations can be costly. The set_public_key and _set_public_key functions involve multiple reads and writes that could be optimized.

fn set_public_key(ref self: ComponentState<TContractState>, new_public_key: felt252) {
    self.emit(OwnerRemoved { removed_owner_guid: self.Account_public_key.read() });
    self._set_public_key(new_public_key);
}

PLEASE Review and refactor storage access patterns to minimize gas costs, possibly by reducing the number of storage operations or caching values. Code Structure and Readability Enhanced Error Handling: Using string literals for error messages can lead to duplication and larger contract sizes. For instance, const INVALID_CALLER: felt252 = 'Account: invalid caller'; is a pattern seen across different error definitions. Suggestion: Utilize a centralized error handling system with error codes or enums to manage error messages more efficiently.

Documentation Improvements: Expanding comments and documentation within the code can significantly aid understanding and maintainability. For example, detailed explanations for the purpose and usage of functions like execute and is_valid_signature could be more comprehensive. PLEASE Add detailed docstrings and inline comments explaining the logic, parameters, and expected outcomes of functions.

Standardized Naming Conventions: The mix of camelCase and snake_case in variable and function names should be standardized. PLEASE Adopt a consistent naming convention throughout the code to improve clarity and developer experience.

### Tasks
- [ ] https://github.com/OpenZeppelin/cairo-contracts/issues/942
fruitbox12 commented 3 months ago

Enhanced Validation Strategy: To enhance this process, consider implementing the following security checks and features:

Timestamp or Nonce Validation: Incorporate a timestamp or nonce within the signature payload to prevent replay attacks. This involves modifying the signature generation and validation processes to include these additional pieces of data, ensuring that each transaction is unique and cannot be replayed by an attacker.

Class Hash and Contract Address Salt Validation: As described in the documentation for __validate_deploy__, including class hash and contract address salt in the validation process can add an additional layer of security. For is_valid_signature, adapting this approach could mean validating these parameters against expected values or policies to ensure the deployment and execution context is secure.

Constructor Arguments Validation: If the signature pertains to a contract deployment or a significant state change, validating the constructor arguments or the function call parameters as part of the signature validation can ensure the integrity of the transaction. This would involve hashing these arguments and including them in the signature verification process.

System Call for Transaction Info: Utilize get_tx_info system call to access transaction-specific details like transaction hash and max_fee, ensuring that the signature validation process also accounts for the transaction's economic aspects. This can prevent attacks aimed at manipulating transaction fees or other economic parameters.