99 lines
2.2 KiB
Solidity
99 lines
2.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.24;
|
|
|
|
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;
|
|
}
|
|
|
|
struct Deposit {
|
|
uint id;
|
|
address staker;
|
|
uint poolId;
|
|
uint amount;
|
|
uint lockedAt;
|
|
uint releasedAt;
|
|
}
|
|
|
|
constructor(PADToken _padToken) {
|
|
padToken = _padToken;
|
|
_initPools();
|
|
}
|
|
|
|
function _initPools() internal {
|
|
pools[0] = Pool({
|
|
id: nextPoolId,
|
|
lockdownDays: 30,
|
|
rewardPercentage: 25
|
|
});
|
|
nextPoolId++;
|
|
|
|
pools[1] = Pool({
|
|
id: nextPoolId,
|
|
lockdownDays: 60,
|
|
rewardPercentage: 50
|
|
});
|
|
nextPoolId++;
|
|
}
|
|
|
|
function stake(uint poolId, uint amount) external {
|
|
Pool memory pool = pools[poolId];
|
|
Deposit memory newDeposit = Deposit({
|
|
id: nextDepositId,
|
|
staker: msg.sender,
|
|
poolId: poolId,
|
|
amount: amount,
|
|
lockedAt: block.timestamp,
|
|
releasedAt: block.timestamp + (pool.lockdownDays * 1 days)
|
|
});
|
|
deposits[msg.sender].push(newDeposit);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|