// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {IERC20} from "./interfaces/[Link]";
import {Ownable} from "./utils/[Link]";
interface FeeDistribution {
function claim(address) external;
}
contract Staking is Ownable {
/// @notice the balance of reward tokens
uint256 public balance = 0;
/// @notice the index of the last update
uint256 public index = 0;
/// @notice mapping of user indexes
mapping(address => uint256) public supplyIndex;
/// @notice mapping of user balances
mapping(address => uint256) public balances;
/// @notice mapping of user claimable rewards
mapping(address => uint256) public claimable;
/// @notice the staking token
IERC20 public immutable TKN;
/// @notice the reward token
IERC20 public immutable WETH;
constructor(address _token, address _weth) Ownable([Link]) {
TKN = IERC20(_token);
WETH = IERC20(_weth);
}
/// @notice deposit tokens to stake
/// @param _amount the amount to deposit
function deposit(uint _amount) external {
[Link]([Link], address(this), _amount);
updateFor([Link]);
balances[[Link]] += _amount;
}
/// @notice withdraw tokens from stake
/// @param _amount the amount to withdraw
function withdraw(uint _amount) external {
updateFor([Link]);
balances[[Link]] -= _amount;
[Link]([Link], _amount);
}
/// @notice claim rewards
function claim() external {
updateFor([Link]);
[Link]([Link], claimable[[Link]]);
claimable[[Link]] = 0;
balance = [Link](address(this));
}
/// @notice update the global index of earned rewards
function update() public {
uint256 totalSupply = [Link](address(this));
if (totalSupply > 0) {
uint256 _balance = [Link](address(this));
if (_balance > balance) {
uint256 _diff = _balance - balance;
if (_diff > 0) {
uint256 _ratio = _diff * 1e18 / totalSupply;
if (_ratio > 0) {
index = index + _ratio;
balance = _balance;
}
}
}
}
}
/// @notice update the index for a user
/// @param recipient the user to update
function updateFor(address recipient) public {
update();
uint256 _supplied = balances[recipient];
if (_supplied > 0) {
uint256 _supplyIndex = supplyIndex[recipient];
supplyIndex[recipient] = index;
uint256 _delta = index - _supplyIndex;
if (_delta > 0) {
uint256 _share = _supplied * _delta / 1e18;
claimable[recipient] += _share;
}
} else {
supplyIndex[recipient] = index;
}
}