Розробка контрактів стейкингу
Контракт стейкингу — один із базових примітивів DeFi. Користувач депонує токени, отримує винагороди з часом та може вивести кошти. Звучить просто — і саме тому більшість реалізацій містять баги. Правильний механізм розрахунку винагород є нетривіальним, а помилки тут коштують грошей.
Розподіл винагород: алгоритм накопленої винагороди за токен
Наївна реалізація проходить через всіх стейкерів та оновлює їх баланси — це O(n) щодо газу та руйнує контракт при великій кількості користувачів.
Стандартний алгоритм: 累積된 보상당 토큰. Глобальна змінна rewardPerTokenStored накопичує винаграду на 1 токен з моменту розгортання. При кожному deposit/withdraw вона оновлюється. Індивідуальна винагорода обчислюється як (rewardPerToken - userCheckpoint) × userBalance.
uint256 public rewardPerTokenStored;
uint256 public lastUpdateTime;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
function rewardPerToken() public view returns (uint256) {
if (totalSupply == 0) return rewardPerTokenStored;
return rewardPerTokenStored +
(block.timestamp - lastUpdateTime) * rewardRate * 1e18 / totalSupply;
}
function earned(address account) public view returns (uint256) {
return balanceOf[account] *
(rewardPerToken() - userRewardPerTokenPaid[account]) / 1e18
+ rewards[account];
}
Це O(1) — газ не залежить від кількості користувачів. Саме так працює Synthetix StakingRewards, який став еталонною реалізацією.
Основні механіки стейкингу
Період блокування: токени заблоковані на N днів після депозиту. Зменшує тиск на продаж. Потребує збереження depositTime та перевірки при withdraw.
Cooldown для вивільнення: після ініціювання виводу — очікування 7-28 днів. Популярно в PoS протоколах (імітує період unbonding).
Штраф за ранній вивід: при виведенні до закінчення періоду блокування — штраф (наприклад, 10% від суми). Штраф йде до пулу винагород або спалюється.
Множник за час: чим довше стейкинг — тим вища ставка винагород. Реалізується через ярусні множники або лінійний вестинговий множник.
Безпека
Reentrancy: при виплаті винагород через transfer → зовнішній виклик → функція контракту знову. CEI паттерн (Checks-Effects-Interactions): спочатку оновити стан, потім робити transfer.
Втрата точності: поділ у Solidity округлює вниз. При малих сумах або великому totalSupply точність може бути втрачена. Використовуйте масштабуючий коефіцієнт 1e18 (або 1e27 для додаткової точності).
Токен винагород != токен стейкингу: якщо токен винагород та стейкингу однакові — totalSupply включає токени винагород у пулі, що ламає обчислення rewardPerToken. Потрібно акуратно рахувати тільки "застейковані" токени.
Адміністративні ключі: хто може змінити rewardRate? Якщо це EOA — єдина точка відмови. Timelock + multisig — стандарт для production контрактів.
Контракти стейкингу перед розгортанням обов'язково проходять аудит — вони зберігають кошти користувачів та є частими мішенями для експлойтів.







