124 lines
2.8 KiB
Solidity
124 lines
2.8 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.24;
|
|
|
|
import "hardhat/console.sol";
|
|
import "./PADToken.sol";
|
|
|
|
contract PADTokenStake {
|
|
// pool id => pool info
|
|
mapping (uint => Pool) pools;
|
|
// staker => deposits
|
|
mapping(address => Deposit[]) deposits;
|
|
uint nextPoolId = 0;
|
|
uint nextDepositId = 0;
|
|
PADToken immutable padToken;
|
|
|
|
struct Pool {
|
|
uint id;
|
|
uint lockdownDays;
|
|
uint rewardPercentage;
|
|
uint lockedAmount;
|
|
}
|
|
|
|
struct Deposit {
|
|
uint id;
|
|
address staker;
|
|
uint poolId;
|
|
uint amount;
|
|
uint lockedAt;
|
|
uint releasedAt;
|
|
}
|
|
|
|
event Staked(address indexed staker, uint indexed poolId, uint amount, uint lockedAt);
|
|
|
|
constructor(PADToken _padToken) {
|
|
padToken = _padToken;
|
|
_initPools();
|
|
}
|
|
|
|
function _initPools() internal {
|
|
pools[0] = Pool({
|
|
id: nextPoolId,
|
|
lockdownDays: 30,
|
|
rewardPercentage: 25,
|
|
lockedAmount: 0
|
|
});
|
|
nextPoolId++;
|
|
|
|
pools[1] = Pool({
|
|
id: nextPoolId,
|
|
lockdownDays: 60,
|
|
rewardPercentage: 50,
|
|
lockedAmount: 0
|
|
});
|
|
nextPoolId++;
|
|
}
|
|
|
|
function getPools() public view returns (Pool[] memory _pools) {
|
|
_pools = new Pool[](nextPoolId);
|
|
for (uint i = 0; i < nextPoolId; i++) {
|
|
_pools[i] = pools[i];
|
|
}
|
|
}
|
|
|
|
function stake(uint _poolId, uint _amount) external {
|
|
address staker = msg.sender;
|
|
uint lockedAt = block.timestamp;
|
|
Pool storage pool = pools[_poolId];
|
|
|
|
padToken.transferFrom(staker, address(this), _amount);
|
|
|
|
Deposit memory newDeposit = Deposit({
|
|
id: nextDepositId,
|
|
staker: staker,
|
|
poolId: _poolId,
|
|
amount: _amount,
|
|
lockedAt: lockedAt,
|
|
releasedAt: lockedAt + (pool.lockdownDays * 1 days)
|
|
});
|
|
deposits[staker].push(newDeposit);
|
|
|
|
console.log("hey1");
|
|
pool.lockedAmount += _amount;
|
|
console.log("hey2");
|
|
|
|
emit Staked(staker, _poolId, _amount, lockedAt);
|
|
console.log(staker, _poolId, _amount, lockedAt);
|
|
}
|
|
|
|
function getDeposit(uint _depositId) public view returns (Deposit memory) {
|
|
Deposit memory deposit;
|
|
for (uint i = 0; i < deposits[msg.sender].length; i++) {
|
|
deposit = deposits[msg.sender][i];
|
|
if (deposit.id == _depositId) {
|
|
return deposit;
|
|
}
|
|
}
|
|
revert("Deposit with the given ID not found.");
|
|
}
|
|
|
|
function getWithdrawPenalty(uint _depositId) public view returns (uint) {
|
|
Deposit memory deposit = getDeposit(_depositId);
|
|
uint remainingMs = deposit.releasedAt - block.timestamp;
|
|
|
|
if (remainingMs <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
// TODO Find a meaningful formula
|
|
return 100;
|
|
}
|
|
|
|
function withdraw(uint _depositId, bool _acceptPenaltyCut) external {
|
|
uint penalty = getWithdrawPenalty(_depositId);
|
|
if (penalty > 0) {
|
|
require(_acceptPenaltyCut, "You should accept the penalty cut.");
|
|
}
|
|
|
|
Deposit memory deposit = getDeposit(_depositId);
|
|
Pool memory pool = pools[deposit.poolId];
|
|
uint amountToTransfer = (deposit.amount * pool.rewardPercentage / 100) - penalty;
|
|
padToken.transfer(deposit.staker, amountToTransfer);
|
|
}
|
|
}
|