Known Issues and Design Decisions

Last updated 19 Dec 2025, 15:04

Version: 1.0 Date: December 2025 Status: Pre-Audit

This document tracks known limitations, design trade-offs, and intentional decisions in the Zenpower smart contract system. These are not bugs, but acknowledged constraints that auditors and users should be aware of.


Document Purpose

This document serves to:

  1. Transparency: Clearly communicate known limitations
  2. Audit Efficiency: Help auditors focus on unknown issues
  3. Risk Management: Document accepted risks and rationale
  4. Future Planning: Track items for future improvement

Important: Items listed here are either:

  • Intentional design decisions with known trade-offs
  • Acknowledged limitations with mitigation plans
  • Low-priority issues deferred to future versions

1. Intentional Design Decisions

1.1 Non-Upgradeable Contracts

Decision: All contracts are deployed without proxy/upgrade patterns

Rationale:

  • Trust: Immutability provides stronger security guarantees
  • Simplicity: No storage collision or initialization bugs
  • Transparency: Code cannot change after deployment
  • Philosophy: Commitment to "code is law" principle

Trade-offs:

  • ❌ Cannot fix bugs post-deployment
  • ❌ Cannot add features without new deployment
  • ❌ Migration required for major updates

Mitigation:

  • Thorough testing before deployment
  • External security audit
  • Migration strategy documented
  • New contract versions can be deployed

Status: ACCEPTED - Core to trust model

Future Consideration: For v2, may consider minimal upgradeability for configuration only (not core logic)


1.2 Centralized Backend Signer

Decision: TheForge uses single backend signer for attestations

Rationale:

  • Simplicity: Easier to implement for v1
  • Speed: Single signature verification faster
  • Iteration: Allows rapid updates to off-chain verification logic

Trade-offs:

  • ❌ Single point of failure
  • ❌ Trust in backend operator
  • ❌ No redundancy if signer compromised

Mitigation:

  • Signer key stored in HSM (planned)
  • Monitoring of all signatures
  • Emergency pause capability
  • Migration to multi-sig planned for v1.1

Status: TEMPORARY - Will be upgraded to multi-sig

Roadmap:

  • v1.0: Single signer with HSM
  • v1.1: 3-of-5 multi-sig backend
  • v2.0: Fully decentralized attestation network

1.3 Off-Chain ZEN$ Currency

Decision: ZEN$ is managed off-chain (database), not on-chain token

Rationale:

  • Flexibility: Can adjust economics without gas costs
  • Privacy: User balances not public
  • Cost: No gas fees for ZEN$ transactions
  • UX: Faster transactions, better user experience

Trade-offs:

  • ❌ Requires trust in backend database
  • ❌ No on-chain proof of ZEN$ balance
  • ❌ Centralization risk

Mitigation:

  • Backend signature required to burn ZEN$
  • Regular balance audits
  • Merkle proof system planned
  • Migration path to on-chain token exists

Status: ACCEPTED - Intentional hybrid design

Future Consideration: Add Merkle tree of ZEN$ balances published on-chain for verification


1.4 Fixed Forge Path Economics

Decision: Forge paths have fixed ZEN$ costs and ZENCOIN rewards

Rationale:

  • Predictability: Users know exact returns
  • Fairness: No advantage to timing or market conditions
  • Simplicity: Easy to understand and communicate

Trade-offs:

  • ❌ No dynamic adjustment for demand
  • ❌ May become unbalanced over time
  • ❌ Governance required to update

Mitigation:

  • Paths can be updated via governance
  • Multiple paths provide diversity
  • Economic modeling before launch
  • Monitoring for gaming/exploitation

Status: ACCEPTED - Can be changed via governance

Future Consideration: Dynamic pricing based on ZENCOIN supply or demand


1.5 Low Governance Quorum (4%)

Decision: Quorum set to 4% of total ZENCOIN supply

Rationale:

  • Early Stage: Expected low participation initially
  • Activation: Ensures DAO can actually pass proposals
  • Progressive: Can be increased as participation grows

Trade-offs:

  • ❌ Small minority could control governance
  • ❌ Lower security against takeover
  • ❌ May not reflect broad consensus

Mitigation:

  • 10,000 ZENCOIN proposal threshold
  • 7-day voting period for participation
  • 48-hour timelock for community reaction
  • Quorum can be raised via governance

Status: ACCEPTED - Appropriate for launch phase

Monitoring Plan:

  • Track participation rates
  • Raise quorum when participation > 10% consistently
  • Target 10-15% quorum long-term

1.6 No Vote Locking/Staking Requirement

Decision: ZENCOIN holders can vote without locking tokens

Rationale:

  • Accessibility: Lower barrier to participation
  • Liquidity: Holders maintain token liquidity
  • Flexibility: Can change vote delegation freely

Trade-offs:

  • ❌ Vulnerable to flash loan governance attacks (mitigated by delay)
  • ❌ No commitment requirement
  • ❌ Lower skin-in-the-game

Mitigation:

  • 1-day voting delay (snapshot protection)
  • Delegation checkpoints prevent same-block attacks
  • Timelock provides exit window
  • Future staking contract can add incentives

Status: ACCEPTED - Standard OpenZeppelin Governor behavior

Future Consideration: Optional staking contract for enhanced voting power


2. Known Limitations

2.1 Unbounded Array Growth

Issue: userForges[] array grows without limit

Affected Functions:

  • getForgesForUser() - Returns full array
  • _countActiveForges() - Loops through all forges

Impact:

  • May run out of gas with many forges (>100)
  • DoS on user's future forge operations
  • View functions may fail

Likelihood: LOW - Users limited to 3 concurrent forges

Mitigation (Current):

  • maxConcurrentForges = 3 limits active forges
  • Economic cost discourages spam
  • Off-chain indexing available

Mitigation (Planned):

  • Add pagination to view functions
  • Implement forge expiration (auto-cleanup)
  • Consider mapping-based active count

Status: ACKNOWLEDGED - Low priority, has workarounds

Timeline: Fix in v1.1 if becomes issue


2.2 No Signature Expiration

Issue: Backend signatures have no expiration timestamp

Affected Functions:

  • startForge() - Accepts signatures indefinitely
  • claimForge() - Accepts completion signatures indefinitely

Impact:

  • Old signatures could be used much later
  • Potential for stale data attack
  • No time-bound on signature validity

Likelihood: LOW - forgeId includes timestamp

Mitigation (Current):

  • forgeId includes block.timestamp (uniqueness)
  • Backend can track used signatures
  • Replay protection via forgeId

Mitigation (Planned):

  • Add explicit expiration field to signature
  • Verify expiration on-chain
  • Recommended: 1-hour expiration window

Status: ACKNOWLEDGED - Should be fixed before mainnet

Priority: HIGH


2.3 No Parameter Validation in Path Configuration

Issue: setPathConfig() accepts arbitrary values

Affected Functions:

  • setPathConfig() - No bounds checking

Impact:

  • CONFIG_ROLE could set zenCost = 0
  • Could set zencoinReward = MAX_UINT256
  • Could set duration = 0
  • Breaks economic model

Likelihood: LOW - Requires malicious CONFIG_ROLE

Mitigation (Current):

  • CONFIG_ROLE assigned to trusted multisig
  • All changes emit events (monitored)
  • Community can react via governance

Mitigation (Planned):

function setPathConfig(ForgePath path, PathConfig calldata config) external {
    require(config.zenCost >= MIN_ZEN_COST, "Cost too low");
    require(config.zenCost <= MAX_ZEN_COST, "Cost too high");
    require(config.zencoinReward >= MIN_REWARD, "Reward too low");
    require(config.zencoinReward <= MAX_REWARD, "Reward too high");
    require(config.duration >= MIN_DURATION, "Duration too short");
    require(config.duration <= MAX_DURATION, "Duration too long");
    // ... rest of function
}

Status: ACKNOWLEDGED - Should be fixed before mainnet

Priority: CRITICAL


2.4 Pause Has No Time Limit

Issue: Contracts can be paused indefinitely

Affected Contracts:

  • ZENCOIN
  • TheForge

Impact:

  • Complete DoS if pauser malicious or unresponsive
  • No automatic unpause mechanism
  • DAO voting frozen during ZENCOIN pause

Likelihood: LOW - PAUSER_ROLE is trusted multisig

Mitigation (Current):

  • PAUSER_ROLE assigned to Ethics Board multisig
  • Multiple signers required
  • Community can pressure unpause

Mitigation (Planned):

uint256 public constant MAX_PAUSE_DURATION = 7 days;
uint256 public pausedAt;

function pause() external {
    pausedAt = block.timestamp;
    _pause();
}

function _requireNotPaused() internal view override {
    super._requireNotPaused();
    if (paused() && block.timestamp > pausedAt + MAX_PAUSE_DURATION) {
        // Auto-unpause after max duration
        _unpause();
    }
}

Status: ACKNOWLEDGED - Should be added before mainnet

Priority: HIGH


2.5 Single Forge ID Generation Method

Issue: ForgeId uses keccak256(forger, path, timestamp)

Potential Issues:

  • Theoretically vulnerable to collision if same user, same path, same block
  • Front-running could predict forgeId
  • No explicit nonce

Likelihood: VERY LOW - Block timestamps are unique per block

Mitigation (Current):

  • block.timestamp granularity (seconds) makes collisions unlikely
  • User can only start one forge per transaction
  • Frontend prevents concurrent submissions

Mitigation (Planned):

  • Add nonce parameter to forgeId generation
  • Use keccak256(forger, path, timestamp, nonce)
  • Track nonce per user

Status: ACKNOWLEDGED - Low risk but should be improved

Priority: MEDIUM


2.6 No Minting Rate Limit

Issue: No rate limit on ZENCOIN minting

Affected Functions:

  • ZENCOIN.forge() - Can be called unlimited times per block

Impact:

  • If backend signer compromised, unlimited minting
  • No circuit breaker for abnormal minting
  • Potential rapid supply drain

Likelihood: LOW - Requires backend compromise

Mitigation (Current):

  • Backend implements rate limiting
  • Monitoring alerts on abnormal minting
  • Pause capability exists

Mitigation (Planned):

uint256 public constant MAX_MINT_PER_HOUR = 10_000 * 10**18;
mapping(uint256 => uint256) public mintedPerHour; // hour => amount

function forge(address to, uint256 amount, bytes32 forgeId) external {
    uint256 currentHour = block.timestamp / 1 hours;
    require(
        mintedPerHour[currentHour] + amount <= MAX_MINT_PER_HOUR,
        "Hourly mint limit exceeded"
    );
    mintedPerHour[currentHour] += amount;
    // ... rest of function
}

Status: ACKNOWLEDGED - Defense in depth

Priority: MEDIUM


2.7 No Emergency Admin for Governor

Issue: If governance is broken, no emergency override

Scenario:

  • Critical bug found
  • Governance vote takes 7 days + 48 hours = 9+ days
  • May be too slow for emergency

Likelihood: LOW - Emergency pause exists

Mitigation (Current):

  • Pause capability stops damage
  • Ethics Board can cancel malicious proposals
  • Community can react during timelock

Mitigation (Considered but Rejected):

  • Emergency admin role (rejected - too centralized)
  • Shorter timelock for emergencies (rejected - security risk)
  • Guardian role (may consider for v2)

Status: ACCEPTED - Trade-off for decentralization

Philosophy: Prefer slow but secure over fast but risky


3. Deferred Features

3.1 Signature Malleability Protection

Issue: Raw ecrecover vulnerable to s-value manipulation

Description:

  • ECDSA signatures have two valid s-values
  • Attacker can flip s-value to create valid alternate signature
  • Could bypass signature tracking if implemented naively

Current Status:

  • Not exploitable in current design (forgeId prevents replay)
  • But non-ideal cryptographic practice

Recommendation:

// Use OpenZeppelin ECDSA library instead
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

function _verifySignature(bytes32 hash, bytes memory sig) internal view {
    address recovered = ECDSA.recover(hash, sig);
    require(recovered == signer, "Invalid signature");
}

Status: DEFERRED - Not critical but should fix

Priority: HIGH

Timeline: Include in pre-mainnet fixes


3.2 EIP-712 Structured Data Signing

Issue: Using EIP-191 instead of EIP-712 for signatures

Trade-offs:

  • EIP-191: Simpler, but less readable
  • EIP-712: Better UX (wallet shows readable data), but more complex

Current Status:

  • Using EIP-191 with prefix
  • Functionally secure but UX could be better

Recommendation:

bytes32 private constant FORGE_TYPEHASH = keccak256(
    "Forge(address forger,uint8 path,uint256 zenCommitted,bytes32 forgeId)"
);

function _hashTypedData(bytes32 structHash) internal view returns (bytes32) {
    return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}

Status: DEFERRED - UX improvement for v2

Priority: LOW

Timeline: Consider for v2.0


3.3 Merkle Proof for ZEN$ Balance

Issue: No on-chain proof of ZEN$ balance

Description:

  • Users must trust backend's claim of ZEN$ balance
  • No way to verify balance independently
  • Centralization risk

Proposed Solution:

  • Backend publishes Merkle root of all balances weekly
  • Users can verify their balance against Merkle root
  • On-chain verification during forge start

Status: DEFERRED - Nice to have, not critical

Priority: MEDIUM

Timeline: v1.5 or v2.0


3.4 Batch Operations

Issue: No batch operations for efficiency

Examples:

  • Batch claim multiple completed forges
  • Batch cancel multiple forges
  • Batch delegation

Trade-offs:

  • Would save gas for users
  • But adds complexity and attack surface
  • May enable new DoS vectors

Status: DEFERRED - Optimization for later

Priority: LOW

Timeline: Post-mainnet if user demand


3.5 Forge Transfer/Trading

Issue: Cannot transfer active forge to another address

Scenario:

  • User wants to sell incomplete forge
  • No mechanism to transfer ownership
  • Forge tied to original address

Design Decision:

  • Forges are non-transferable by design
  • Prevents forge market/speculation
  • Maintains "earned, not bought" philosophy

Status: INTENTIONALLY NOT IMPLEMENTED

Future Consideration: Could add transferable forges as separate contract


4. Testnet-Only Issues

4.1 Timestamp Manipulation on Testnets

Issue: Testnet validators can manipulate timestamps

Impact:

  • Could claim forges early
  • Could game voting delays
  • Not representative of mainnet

Mitigation:

  • Only affects testing
  • Mainnet timestamp manipulation limited (±15 seconds tolerance)
  • Forge durations (7-60 days) make ±15 seconds irrelevant

Status: TESTNET ONLY - Not applicable to mainnet


4.2 Low Proposal Threshold for Testing

Issue: Testing with 10,000 ZENCOIN threshold is impractical

Solution:

  • Testnet deployment may use lower threshold (e.g., 100 ZENCOIN)
  • Documented clearly in deployment scripts
  • Mainnet deployment uses documented values

Status: EXPECTED - Different config for testnet


5. Documentation Gaps

5.1 Migration Strategy Not Documented

Issue: No documented process for v1 → v2 migration

Impact:

  • Unclear how to upgrade if non-upgradeable
  • Users don't know migration process
  • Risk of confusion or loss

Planned Documentation:

  • Token migration process (snapshot + claim)
  • Forge completion process before migration
  • Treasury transfer process
  • Governance coordination

Status: ACKNOWLEDGED - Documentation needed

Priority: MEDIUM

Timeline: Before mainnet launch


5.2 Emergency Procedures Not Documented

Issue: No runbook for emergency scenarios

Needed Documentation:

  • When to pause contracts
  • How to coordinate pause across contracts
  • Emergency communication templates
  • Incident response procedures
  • Recovery processes

Status: ACKNOWLEDGED - Critical for operations

Priority: HIGH

Timeline: Before mainnet launch


5.3 Economic Model Not Fully Analyzed

Issue: No formal game theory analysis of forge paths

Questions:

  • Are paths balanced?
  • Can users game the system?
  • What's optimal strategy?
  • How does it scale?

Planned Analysis:

  • Monte Carlo simulation of user strategies
  • Nash equilibrium analysis
  • Scaling projections
  • Sensitivity analysis

Status: ACKNOWLEDGED - Should complete before launch

Priority: HIGH

Timeline: During audit period


6. External Dependencies

6.1 OpenZeppelin Contract Updates

Issue: Using OpenZeppelin Contracts v5.x

Considerations:

  • New vulnerabilities may be discovered
  • Updates may be released
  • We cannot upgrade (non-upgradeable design)

Mitigation:

  • Using stable release (not beta)
  • OpenZeppelin contracts are battle-tested
  • External audit will review OZ usage
  • Monitor OpenZeppelin security advisories

Status: ACCEPTED - Standard dependency risk

Monitoring: Subscribe to OpenZeppelin security announcements


6.2 Solidity Compiler Version

Issue: Using Solidity ^0.8.20

Considerations:

  • Newer versions may have bug fixes
  • Older versions may have known issues
  • Specific version should be pinned for deployment

Mitigation:

  • 0.8.20 is stable release
  • No known critical bugs in 0.8.20+
  • Will pin exact version for mainnet deployment

Status: ACCEPTED - Will pin to 0.8.24 for mainnet

Action: Update pragma solidity 0.8.24; (exact version) before deployment


6.3 EVM Chain Assumptions

Issue: Assumes Ethereum mainnet behavior

Considerations:

  • Other chains (L2s, sidechains) may behave differently
  • Block time variations
  • Gas cost differences
  • Opcode availability

Current Support:

  • Designed for Ethereum mainnet
  • Should work on most EVM chains
  • May need adjustments for non-EVM or special chains

Status: ACCEPTED - Ethereum mainnet primary target

Future: Test on target L2s before any multi-chain deployment


7. Trade-off Summary

Decision Benefit Cost Status
Non-upgradeable Immutability, trust Cannot fix bugs ACCEPTED
Single signer Simplicity, speed Centralization TEMPORARY
Off-chain ZEN$ Privacy, flexibility Trust required ACCEPTED
Fixed economics Predictability No dynamic adjustment ACCEPTED
Low quorum (4%) Early activation Lower security TEMPORARY
No vote locking Accessibility Flash loan risk (low) ACCEPTED
Unbounded arrays Simplicity Potential DoS ACKNOWLEDGED
No param validation Trust in admin Potential misconfiguration TO FIX
No pause limit Flexibility Potential abuse TO FIX

8. Pre-Mainnet Checklist

Must be resolved before mainnet:

  • Add parameter validation to setPathConfig()
  • Implement signature nonce-based replay protection
  • Migrate to OpenZeppelin ECDSA library
  • Add maximum pause duration
  • Document migration strategy
  • Create emergency runbook
  • Complete economic analysis
  • Implement multi-sig backend (or document single-signer HSM setup)
  • Add signature expiration checking
  • Pin exact Solidity version (0.8.24)

Should be resolved before mainnet:

  • Add pagination for unbounded arrays
  • Implement forge expiration
  • Add minting rate limits
  • Improve forgeId generation with nonce
  • Comprehensive test coverage (95%+)
  • Attack scenario testing
  • Testnet deployment and testing
  • External audit completion

9. Disclosure Policy

This document is:

  • Public: Will be published with audit
  • Living: Updated as new issues discovered
  • Transparent: Honest about limitations

Updates:

  • Major updates: Version increment (1.0 → 2.0)
  • Minor updates: Revision date
  • All changes tracked in git

Responsibility:

  • Security team maintains document
  • Community can submit issues/PRs
  • Auditors review for completeness

10. Conclusion

Summary

This document tracks 27 items across categories:

Category Count Critical High Medium Low
Design Decisions 7 0 0 0 7
Known Limitations 7 1 3 2 1
Deferred Features 5 0 1 2 2
Documentation Gaps 3 0 2 1 0
Dependencies 3 0 0 3 0

Critical/High Items Requiring Action: 7 Medium Priority Items: 8 Low Priority / Accepted Trade-offs: 12

Transparency Commitment

We believe in radical transparency about security:

  • We document what we know we don't know
  • We acknowledge trade-offs honestly
  • We communicate limitations clearly
  • We commit to continuous improvement

This document demonstrates:

  • Security-first mindset
  • Honest assessment of risks
  • Clear prioritization
  • Actionable roadmap

Auditor Notes

Dear Auditors,

This document is provided to help you focus your efforts on unknown issues. We have:

  1. Identified known limitations and design decisions
  2. Analyzed trade-offs and rationale
  3. Prioritized items for remediation
  4. Committed to pre-mainnet fixes

Please:

  • Verify our assessment of known issues
  • Identify issues we missed
  • Evaluate our prioritization
  • Recommend additional mitigations

We want your independent assessment, not validation of our assumptions.


Document Version: 1.0 Last Updated: December 2025 Next Review: After external audit Maintained By: Zenpower Security Team


"The first step in fixing a problem is acknowledging it exists."