# Smart Contracts

***

### Contract Overview

```
┌─────────────────────────────────────────────────────────────────────┐
│                    CONTRACT ARCHITECTURE                            │
└─────────────────────────────────────────────────────────────────────┘

    ┌─────────────────────────────────────────────────────────────────┐
    │                         User Wallet                             │
    └──────────────────────────────┬──────────────────────────────────┘
                                   │
                    ┌──────────────┼──────────────┐
                    │              │              │
                    ▼              ▼              ▼
           ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
           │  NOX Token  │ │  Staking    │ │  Rewards    │
           │  (ERC-20)   │ │  Contract   │ │  Contract   │
           └──────┬──────┘ └──────┬──────┘ └──────┬──────┘
                  │               │               │
                  └───────────────┼───────────────┘
                                  │
                                  ▼
                         ┌─────────────┐
                         │  Staking    │
                         │   Vault     │
                         │  (32M NOX)  │
                         └─────────────┘
```

### Contract Addresses

| Contract             | Address                                      | Verified |
| -------------------- | -------------------------------------------- | -------- |
| **NOX Token**        | `0x0a26c80Be4E060e688d7C23aDdB92cBb5D2C9eCA` | ✓        |
| **Staking Vault**    | `0xD548558A7e2666D5580125448B446358F5990423` | ✓        |
| **Staking Contract** | TBD (deployment pending)                     | -        |

***

### NOX Token Contract

#### Overview

* **Standard**: ERC-20 with EIP-2612 Permit
* **Upgradeability**: UUPS Proxy Pattern
* **Access Control**: Role-based (OpenZeppelin)

#### Interface

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface INOX {
    // ═══════════════════════════════════════════════════════════════
    //                         ERC-20 STANDARD
    // ═══════════════════════════════════════════════════════════════

    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    // ═══════════════════════════════════════════════════════════════
    //                         EIP-2612 PERMIT
    // ═══════════════════════════════════════════════════════════════

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function nonces(address owner) external view returns (uint256);
    function DOMAIN_SEPARATOR() external view returns (bytes32);

    // ═══════════════════════════════════════════════════════════════
    //                         EVENTS
    // ═══════════════════════════════════════════════════════════════

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}
```

#### Usage Examples

```javascript
// Using ethers.js

// Transfer tokens
const tx = await noxToken.transfer(recipientAddress, amount);

// Approve staking contract
const tx = await noxToken.approve(stakingContractAddress, amount);

// Gasless approval with permit
const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour
const nonce = await noxToken.nonces(userAddress);

const signature = await signer._signTypedData(
    {
        name: 'NOX',
        version: '1',
        chainId: 1,
        verifyingContract: noxTokenAddress
    },
    {
        Permit: [
            { name: 'owner', type: 'address' },
            { name: 'spender', type: 'address' },
            { name: 'value', type: 'uint256' },
            { name: 'nonce', type: 'uint256' },
            { name: 'deadline', type: 'uint256' }
        ]
    },
    {
        owner: userAddress,
        spender: stakingContractAddress,
        value: amount,
        nonce: nonce,
        deadline: deadline
    }
);

const { v, r, s } = ethers.utils.splitSignature(signature);
await noxToken.permit(userAddress, stakingContractAddress, amount, deadline, v, r, s);
```

***

### Staking Contract

#### Overview

The staking contract manages:

* Stake deposits and withdrawals
* Tier management
* Reward distribution
* Quality metrics reporting

#### Interface

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface INONOSStaking {
    // ═══════════════════════════════════════════════════════════════
    //                         STAKING
    // ═══════════════════════════════════════════════════════════════

    /// @notice Deposit NOX tokens to stake
    /// @param amount Amount of NOX to stake
    function stake(uint256 amount) external;

    /// @notice Deposit with permit (gasless approval)
    /// @param amount Amount to stake
    /// @param deadline Permit deadline
    /// @param v Signature v
    /// @param r Signature r
    /// @param s Signature s
    function stakeWithPermit(
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /// @notice Request withdrawal (starts cooldown)
    /// @param amount Amount to withdraw
    function requestWithdrawal(uint256 amount) external;

    /// @notice Complete withdrawal after cooldown
    function completeWithdrawal() external;

    /// @notice Cancel pending withdrawal
    function cancelWithdrawal() external;

    // ═══════════════════════════════════════════════════════════════
    //                         TIERS
    // ═══════════════════════════════════════════════════════════════

    enum Tier { None, Bronze, Silver, Gold, Platinum, Diamond }

    /// @notice Get current tier for an address
    function getTier(address staker) external view returns (Tier);

    /// @notice Get tier multiplier (in basis points, 10000 = 1.0x)
    function getTierMultiplier(Tier tier) external pure returns (uint256);

    /// @notice Get minimum stake for a tier
    function getTierMinimum(Tier tier) external pure returns (uint256);

    // ═══════════════════════════════════════════════════════════════
    //                         REWARDS
    // ═══════════════════════════════════════════════════════════════

    /// @notice Claim pending rewards
    function claimRewards() external;

    /// @notice Get pending rewards for an address
    function pendingRewards(address staker) external view returns (uint256);

    /// @notice Get reward history
    function getRewardHistory(address staker, uint256 limit)
        external view returns (RewardRecord[] memory);

    // ═══════════════════════════════════════════════════════════════
    //                         QUALITY
    // ═══════════════════════════════════════════════════════════════

    /// @notice Report quality metrics for a node (oracle only)
    /// @param node Node address
    /// @param quality Quality score (0-10000 basis points)
    function reportQuality(address node, uint256 quality) external;

    /// @notice Get quality score for a node
    function getQuality(address node) external view returns (uint256);

    // ═══════════════════════════════════════════════════════════════
    //                         VIEW FUNCTIONS
    // ═══════════════════════════════════════════════════════════════

    /// @notice Get stake info for an address
    function getStakeInfo(address staker) external view returns (
        uint256 stakedAmount,
        Tier tier,
        uint256 pendingWithdrawal,
        uint256 withdrawalReadyAt,
        uint256 quality,
        uint256 streak
    );

    /// @notice Get current epoch number
    function currentEpoch() external view returns (uint256);

    /// @notice Get daily emission rate
    function dailyEmission() external view returns (uint256);

    /// @notice Get total staked across all nodes
    function totalStaked() external view returns (uint256);

    // ═══════════════════════════════════════════════════════════════
    //                         EVENTS
    // ═══════════════════════════════════════════════════════════════

    event Staked(address indexed staker, uint256 amount, Tier tier);
    event WithdrawalRequested(address indexed staker, uint256 amount, uint256 readyAt);
    event WithdrawalCompleted(address indexed staker, uint256 amount);
    event WithdrawalCancelled(address indexed staker, uint256 amount);
    event RewardsClaimed(address indexed staker, uint256 amount, uint256 epoch);
    event QualityReported(address indexed node, uint256 quality, uint256 epoch);
    event TierChanged(address indexed staker, Tier oldTier, Tier newTier);
}

struct RewardRecord {
    uint256 epoch;
    uint256 amount;
    uint256 quality;
    uint256 timestamp;
    bool claimed;
}
```

#### State Variables

```solidity
// Tier configuration
mapping(Tier => uint256) public tierMinimums;
// Bronze: 1,000 NOX, Silver: 10,000 NOX, Gold: 50,000 NOX
// Platinum: 200,000 NOX, Diamond: 1,000,000 NOX

mapping(Tier => uint256) public tierMultipliers;
// Bronze: 10000 (1.0x), Silver: 12000 (1.2x), Gold: 15000 (1.5x)
// Platinum: 20000 (2.0x), Diamond: 25000 (2.5x)

// Emission configuration
uint256 public baseEmission = 50_000 * 10**18; // 50,000 NOX/day initial
uint256 public decayRate = 9993; // 0.9993 daily (basis points)
uint256 public floorEmission = 5_000 * 10**18; // 5,000 NOX/day minimum

// Withdrawal configuration
uint256 public withdrawalCooldown = 7 days;

// Staker state
mapping(address => StakerInfo) public stakers;

struct StakerInfo {
    uint256 stakedAmount;
    uint256 pendingWithdrawal;
    uint256 withdrawalReadyAt;
    uint256 lastClaimedEpoch;
    uint256 quality;
    uint256 streak;
}
```

#### Usage Examples

```javascript
// Stake tokens
const tx = await stakingContract.stake(ethers.utils.parseEther("10000"));

// Stake with permit (no separate approval needed)
const deadline = Math.floor(Date.now() / 1000) + 3600;
const signature = await signPermit(amount, deadline); // Helper function
const { v, r, s } = ethers.utils.splitSignature(signature);
await stakingContract.stakeWithPermit(amount, deadline, v, r, s);

// Check stake info
const info = await stakingContract.getStakeInfo(userAddress);
console.log(`Staked: ${ethers.utils.formatEther(info.stakedAmount)} NOX`);
console.log(`Tier: ${['None', 'Bronze', 'Silver', 'Gold', 'Platinum', 'Diamond'][info.tier]}`);

// Claim rewards
const pending = await stakingContract.pendingRewards(userAddress);
if (pending.gt(0)) {
    await stakingContract.claimRewards();
}

// Request withdrawal
await stakingContract.requestWithdrawal(ethers.utils.parseEther("5000"));

// After cooldown period
await stakingContract.completeWithdrawal();
```

***

### Staking Vault

#### Overview

The vault holds the 32M NOX allocated for staking rewards.

* **Purpose**: Secure storage of reward tokens
* **Access**: Only staking contract can withdraw
* **Balance**: 32,000,000 NOX initial

***

#### Security

```
┌─────────────────────────────────────────────────────────────────────┐
│                    VAULT SECURITY                                    │
└─────────────────────────────────────────────────────────────────────┘

    Access Controls:
    ┌─────────────────────────────────────────────────────────────────┐
    │  Role            │ Permissions                                  │
    ├───────────────────┼─────────────────────────────────────────────┤
    │  ADMIN           │ Upgrade contracts, emergency pause           │
    │  STAKING_CONTRACT│ Withdraw rewards for distribution            │
    │  PUBLIC          │ View balance only                            │
    └───────────────────┴─────────────────────────────────────────────┘

    Withdrawal Flow:
    1. User claims rewards via staking contract
    2. Staking contract calculates reward
    3. Staking contract requests from vault
    4. Vault verifies caller is staking contract
    5. Vault transfers NOX to user
```

***

### Deployment Information

#### Network Details

| Parameter      | Value            |
| -------------- | ---------------- |
| Network        | Ethereum Mainnet |
| Chain ID       | 1                |
| Block Explorer | etherscan.io     |

#### Deployment Transactions

| Contract         | Deploy Tx | Block |
| ---------------- | --------- | ----- |
| Staking Contract | TBD       | TBD   |

***

### Security Considerations

#### Audit Status

| Auditor    | Scope          | Date | Status  |
| ---------- | -------------- | ---- | ------- |
| \[Auditor] | Full contracts | TBD  | Pending |

#### Known Risks

**Upgradeability Risk**: UUPS proxy allows upgrades; Mitigation: Multi-sig + timelock on upgrades

**Oracle Risk**: Quality reporting depends on oracle; Mitigation: Decentralized oracle network (planned)

**Smart Contract Risk**: Bugs could affect funds; Mitigation: Audits, bug bounty, gradual rollout

#### Emergency Functions

```solidity
// Emergency pause (admin only)
function pause() external onlyRole(ADMIN_ROLE);
function unpause() external onlyRole(ADMIN_ROLE);

// Emergency withdrawal (governance only, with timelock)
function emergencyWithdraw(address token, uint256 amount)
    external onlyRole(GOVERNANCE_ROLE);
```

***

### Integration Guide

#### For Wallets

```javascript
// Add NOX token
const NOX_TOKEN = {
    address: "0x0a26c80Be4E060e688d7C23aDdB92cBb5D2C9eCA",
    symbol: "NOX",
    decimals: 18,
    chainId: 1
};
```

#### For DApps

```javascript
// Contract ABIs (import from npm package)
import { NOX_ABI, STAKING_ABI } from '@nonos/contracts';

// Connect to contracts
const noxToken = new ethers.Contract(NOX_ADDRESS, NOX_ABI, provider);
const staking = new ethers.Contract(STAKING_ADDRESS, STAKING_ABI, provider);

// Read stake info
const info = await staking.getStakeInfo(userAddress);

// Listen for events
staking.on('Staked', (staker, amount, tier) => {
    console.log(`${staker} staked ${amount} at tier ${tier}`);
});
```

#### For Block Explorers

Contract verification available on Etherscan with full source code and ABI.

***

### Contract Upgrades

#### Upgrade Process

1. **Proposal**: Submit upgrade proposal with new implementation
2. **Review**: 7-day review period
3. **Vote**: Governance vote (requires quorum)
4. **Timelock**: 48-hour timelock after approval
5. **Execute**: Upgrade executed

***

#### Upgrade History

| Version | Date       | Changes            |
| ------- | ---------- | ------------------ |
| 1.0.0   | 01.09.2025 | Initial deployment |

***
