Smart Contracts
Contract Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ JVAULT.sol │ │ VaultManager │ │ Timelock.sol │
│ (ERC-20) │────│ .sol │────│ (Governance) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
│ │
┌─────────────────┐ ┌─────────────────┐
│ WithdrawQueue │ │ PriceOracle │
│ .sol │ │ .sol │
└─────────────────┘ └─────────────────┘
Core Contracts
JVAULT.sol (Main Token)
solidity
// Contract Address: 0x... (TODO: Deploy)
// Network: Base L2
interface IJVAULT {
function deposit(uint256 amount, uint256 lockDays) external;
function requestWithdrawal(uint256 shares) external;
function processWithdrawals() external;
function updateNAV(uint256 newNAV) external;
function getCurrentNAV() external view returns (uint256);
}
Key Functions
deposit(uint256 amount, uint256 lockDays)
- Deposits USDC and mints JVAULT tokens
- Validates lock period (7, 30, 60, 90 days)
- Applies 0.25% deposit fee
- Emits
Deposit
event
requestWithdrawal(uint256 shares)
- Queues JVAULT tokens for Sunday withdrawal
- Locks tokens until settlement
- Cannot cancel once submitted
- Emits
WithdrawalRequested
event
processWithdrawals()
- Keeper-only function
- Processes all pending withdrawals
- Burns JVAULT tokens
- Transfers USDC to users
- Called every Sunday 07:00 UTC+7
updateNAV(uint256 newNAV)
- Keeper-only function
- Updates token price based on vault performance
- Validates price within reasonable bounds
- Emits
NAVUpdated
event
Events
solidity
event Deposit(
address indexed user,
uint256 usdcAmount,
uint256 sharesIssued,
uint256 lockUntil,
uint256 pointsEarned
);
event WithdrawalRequested(
address indexed user,
uint256 sharesAmount,
uint256 requestId
);
event WithdrawalProcessed(
address indexed user,
uint256 sharesAmount,
uint256 usdcAmount,
uint256 requestId
);
event NAVUpdated(
uint256 oldNAV,
uint256 newNAV,
uint256 timestamp
);
State Variables
solidity
contract JVAULT is ERC20 {
IERC20 public usdc;
uint256 public currentNAV;
uint256 public totalDeposits;
uint256 public totalWithdrawals;
uint256 public constant FEE_BASIS_POINTS = 25; // 0.25%
mapping(address => UserInfo) public userInfo;
mapping(uint256 => WithdrawalRequest) public withdrawalQueue;
struct UserInfo {
uint256 lockedUntil;
uint256 totalPoints;
uint256 lastDeposit;
}
struct WithdrawalRequest {
address user;
uint256 shares;
uint256 timestamp;
bool processed;
}
}
Access Control
Role | Permissions | Address |
---|---|---|
Owner | Emergency pause, upgrade | 0x... (Multisig) |
Keeper | NAV updates, process withdrawals | 0x... (Bot) |
Admin | Parameter changes | 0x... (Timelock) |
Security Features
Reentrancy Protection
- OpenZeppelin
ReentrancyGuard
- All external calls protected
- CEI pattern enforced
Pausable Operations
- Emergency pause functionality
- Deposit/withdrawal can be halted
- Keeper operations protected
Time Locks
- Critical parameter changes require 48h delay
- Community notification period
- Emergency override capability
Deployed Addresses
Contract | Base L2 Address | Status |
---|---|---|
JVAULT | 0x... | TODO: Deploy |
VaultManager | 0x... | TODO: Deploy |
USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | ✅ Live |
Verification
All contracts will be:
- ✅ Open source
- ✅ Verified on Basescan
- ✅ Audited by reputable firms
- ✅ Formal verification for critical functions
Integration
Web3 Libraries
javascript
// Using wagmi + viem
import { useContract, useContractWrite } from 'wagmi';
const { write: deposit } = useContractWrite({
address: JVAULT_ADDRESS,
abi: JVAULT_ABI,
functionName: 'deposit',
});
Direct Contract Calls
javascript
// Using ethers.js
const jvault = new ethers.Contract(address, abi, signer);
await jvault.deposit(amount, lockDays);
Previous: ← Risk Factors | Next: Keeper System →