IndividualPool Contract
Complete reference for IndividualPool smart contract - methods, events, and integration examples.
IndividualPool Contract
IndividualPool is a personal savings contract where users deposit MUSD tokens and earn yields from Mezo protocol integration.
Contract Details
Address (Mezo Testnet): 0xdfBEd2D3efBD2071fD407bF169b5e5533eA90393
Chain ID: 31611 (Mezo Testnet)
Solidity Version: 0.8.26
Inheritance: BasePoolV3 → UUPSUpgradeable → OwnableUpgradeable → ReentrancyGuardUpgradeable
Key Features
- Personal savings pool (1 user = 1 pool)
- Flexible deposits and withdrawals
- Automatic yield calculation from Mezo protocol
- Optional auto-compounding
- Upgradeable via UUPS proxy
- Reentrancy protected
State Variables
contract IndividualPoolV3 {
IERC20 public musdToken; // MUSD token address
address public owner; // Pool owner
uint256 public balance; // User's balance
uint256 public totalYield; // Accumulated yield
uint256 public lastYieldUpdate; // Last yield calculation
bool public autoCompound; // Auto-compound flag
uint256 public minimumDeposit; // Min deposit (10 MUSD)
uint256 public createdAt; // Creation timestamp
}Read Functions
balanceOf
Get user's current balance.
function balanceOf(address account) external view returns (uint256)Parameters:
account(address): User address
Returns:
balance(uint256): User's balance in wei
Wagmi Example:
import { useReadContract } from 'wagmi'
const { data: balance } = useReadContract({
address: '0xdfBEd2D3efBD2071fD407bF169b5e5533eA90393',
abi: INDIVIDUAL_POOL_ABI,
functionName: 'balanceOf',
args: [userAddress]
})
console.log(`Balance: ${formatUnits(balance, 18)} MUSD`)calculateYield
Calculate pending yield for a user.
function calculateYield(address account) external view returns (uint256)Returns:
- Claimable yield in wei
Example:
const { data: yield } = useReadContract({
address: INDIVIDUAL_POOL_ADDRESS,
abi: INDIVIDUAL_POOL_ABI,
functionName: 'calculateYield',
args: [userAddress]
})totalDeposits
Get total deposits in pool.
function totalDeposits() external view returns (uint256)Example:
const { data: total } = useReadContract({
address: INDIVIDUAL_POOL_ADDRESS,
abi: INDIVIDUAL_POOL_ABI,
functionName: 'totalDeposits'
})getCurrentAPR
Get current Annual Percentage Rate.
function getCurrentAPR() external view returns (uint256)Returns:
- APR in basis points (e.g., 1850 = 18.5%)
Write Functions
deposit
Deposit MUSD tokens into the pool.
function deposit(uint256 amount) external nonReentrantParameters:
amount(uint256): Amount to deposit in wei
Requirements:
- Amount more than 0
- Amount at least minimumDeposit (for first deposit)
- User has approved MUSD spending
- User has sufficient MUSD balance
Events Emitted:
Deposit(address indexed user, uint256 amount, uint256 newBalance, uint256 timestamp)
Wagmi Example:
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { parseUnits } from 'viem'
function DepositButton() {
const { writeContract, data: hash } = useWriteContract()
const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash })
const handleDeposit = async () => {
// First, approve MUSD
await writeContract({
address: MUSD_ADDRESS,
abi: MUSD_ABI,
functionName: 'approve',
args: [INDIVIDUAL_POOL_ADDRESS, parseUnits('100', 18)]
})
// Then deposit
writeContract({
address: INDIVIDUAL_POOL_ADDRESS,
abi: INDIVIDUAL_POOL_ABI,
functionName: 'deposit',
args: [parseUnits('100', 18)]
})
}
return <button onClick={handleDeposit}>Deposit 100 MUSD</button>
}withdraw
Withdraw MUSD tokens from the pool.
function withdraw(uint256 amount) external nonReentrantParameters:
amount(uint256): Amount to withdraw in wei
Requirements:
- Amount more than 0
- Amount at most user balance
- Pool has sufficient liquidity
Events Emitted:
Withdrawal(address indexed user, uint256 amount, uint256 newBalance, uint256 timestamp)
Example:
const { writeContract } = useWriteContract()
const withdraw = () => {
writeContract({
address: INDIVIDUAL_POOL_ADDRESS,
abi: INDIVIDUAL_POOL_ABI,
functionName: 'withdraw',
args: [parseUnits('50', 18)]
})
}claimYield
Claim accumulated yield.
function claimYield() external nonReentrant returns (uint256)Returns:
- Amount of yield claimed
Events Emitted:
YieldClaimed(address indexed user, uint256 amount, uint256 timestamp)
Example:
const { writeContract } = useWriteContract()
const claimYield = () => {
writeContract({
address: INDIVIDUAL_POOL_ADDRESS,
abi: INDIVIDUAL_POOL_ABI,
functionName: 'claimYield'
})
}setAutoCompound
Enable or disable automatic yield compounding.
function setAutoCompound(bool enabled) externalParameters:
enabled(bool): True to enable, false to disable
Example:
const { writeContract } = useWriteContract()
const toggleAutoCompound = (enabled: boolean) => {
writeContract({
address: INDIVIDUAL_POOL_ADDRESS,
abi: INDIVIDUAL_POOL_ABI,
functionName: 'setAutoCompound',
args: [enabled]
})
}Events
Deposit
event Deposit(
address indexed user,
uint256 amount,
uint256 newBalance,
uint256 timestamp
)Listening to Events:
import { useWatchContractEvent } from 'wagmi'
useWatchContractEvent({
address: INDIVIDUAL_POOL_ADDRESS,
abi: INDIVIDUAL_POOL_ABI,
eventName: 'Deposit',
onLogs(logs) {
logs.forEach(log => {
console.log('Deposit:', {
user: log.args.user,
amount: formatUnits(log.args.amount, 18),
newBalance: formatUnits(log.args.newBalance, 18)
})
})
}
})Withdrawal
event Withdrawal(
address indexed user,
uint256 amount,
uint256 newBalance,
uint256 timestamp
)YieldClaimed
event YieldClaimed(
address indexed user,
uint256 amount,
uint256 timestamp
)Complete ABI
export const INDIVIDUAL_POOL_ABI = [
// Read functions
{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: '', type: 'uint256' }]
},
{
name: 'calculateYield',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: '', type: 'uint256' }]
},
{
name: 'totalDeposits',
type: 'function',
stateMutability: 'view',
inputs: [],
outputs: [{ name: '', type: 'uint256' }]
},
{
name: 'getCurrentAPR',
type: 'function',
stateMutability: 'view',
inputs: [],
outputs: [{ name: '', type: 'uint256' }]
},
// Write functions
{
name: 'deposit',
type: 'function',
stateMutability: 'nonpayable',
inputs: [{ name: 'amount', type: 'uint256' }],
outputs: []
},
{
name: 'withdraw',
type: 'function',
stateMutability: 'nonpayable',
inputs: [{ name: 'amount', type: 'uint256' }],
outputs: []
},
{
name: 'claimYield',
type: 'function',
stateMutability: 'nonpayable',
inputs: [],
outputs: [{ name: '', type: 'uint256' }]
},
{
name: 'setAutoCompound',
type: 'function',
stateMutability: 'nonpayable',
inputs: [{ name: 'enabled', type: 'bool' }],
outputs: []
},
// Events
{
name: 'Deposit',
type: 'event',
inputs: [
{ name: 'user', type: 'address', indexed: true },
{ name: 'amount', type: 'uint256', indexed: false },
{ name: 'newBalance', type: 'uint256', indexed: false },
{ name: 'timestamp', type: 'uint256', indexed: false }
]
},
{
name: 'Withdrawal',
type: 'event',
inputs: [
{ name: 'user', type: 'address', indexed: true },
{ name: 'amount', type: 'uint256', indexed: false },
{ name: 'newBalance', type: 'uint256', indexed: false },
{ name: 'timestamp', type: 'uint256', indexed: false }
]
},
{
name: 'YieldClaimed',
type: 'event',
inputs: [
{ name: 'user', type: 'address', indexed: true },
{ name: 'amount', type: 'uint256', indexed: false },
{ name: 'timestamp', type: 'uint256', indexed: false }
]
}
] as constGas Estimates
| Function | Gas (avg) | Gas (max) |
|---|---|---|
| deposit | 65,000 | 85,000 |
| withdraw | 55,000 | 75,000 |
| claimYield | 45,000 | 60,000 |
| setAutoCompound | 35,000 | 45,000 |
Security Features
- ✅ Reentrancy guard on all state-changing functions
- ✅ SafeERC20 for token transfers
- ✅ Checks-Effects-Interactions pattern
- ✅ Upgradeable (UUPS) with access control
- ✅ Audited by [Auditor Name]