Skip to content

Commit

Permalink
Merge pull request #10 from kanna-coin/feat/pre-sale-RC
Browse files Browse the repository at this point in the history
DRAFT: Feat/pre sale rc
  • Loading branch information
psavelis authored Sep 20, 2022
2 parents 06931bb + e7c9598 commit 7975e3a
Show file tree
Hide file tree
Showing 6 changed files with 453 additions and 731 deletions.
20 changes: 16 additions & 4 deletions contracts/ERC20KannaToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import "@openzeppelin/contracts/utils/math/SafeMath.sol";

import {IKannaToken} from "./interfaces/IKannaToken.sol";

import "hardhat/console.sol";

/** @title KNN Token
@author KANNA
@notice This is a OpenZeppelin {IERC20} token contract implementation of KNN Token.
Expand All @@ -31,8 +33,8 @@ contract ERC20KannaToken is IKannaToken, ERC20, Ownable, AccessControl {

uint256 private immutable maxSupply = 19000000 * 10**decimals();

uint256 private constant transactionFeeDecimalAdjust = 1000;
uint256 private transactionFee = 1 * transactionFeeDecimalAdjust;
uint256 private constant transactionFeeDecimalAdjust = 1000 * 100;
uint256 private transactionFee = 1000;

address private kannaDeployerAddress;

Expand Down Expand Up @@ -122,10 +124,13 @@ contract ERC20KannaToken is IKannaToken, ERC20, Ownable, AccessControl {
transactionFee == 0 ||
hasRole(NO_TRANSFER_FEE, from) ||
hasRole(NO_TRANSFER_FEE, to)
) return amount;
) {
console.log("noFee", amount / 1e18, address(from), address(to));
return amount;
}

uint256 feeAmount = amount.mul(transactionFee).div(
100 * transactionFeeDecimalAdjust
transactionFeeDecimalAdjust
);
require(feeAmount > 0, "Invalid fee amount");

Expand All @@ -134,6 +139,13 @@ contract ERC20KannaToken is IKannaToken, ERC20, Ownable, AccessControl {

emit TransactionFee(from, to, amount, block.timestamp, feeAmount);

console.log(
"transactionFee",
amount / 1e18,
feeAmount / 1e18,
finalAmount / 1e18
);

return finalAmount;
}

Expand Down
139 changes: 79 additions & 60 deletions contracts/KannaYield.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,15 @@ contract KannaYield is Ownable, ReentrancyGuard {
using Address for address;

event RewardAdded(address user, uint256 reward, uint256 indexed date);
event Subscription(address user, uint256 amount, uint256 indexed date);
event Subscription(
address user,
uint256 subscriptionAmount,
uint256 fee,
uint256 finalAmount,
uint256 indexed date
);
event Withdraw(address user, uint256 amount, uint256 indexed date);
event Reward(address user, uint256 reward, uint256 indexed date);
event RewardRefreshed(address user, uint256 indexed date);
event Fee(
address user,
uint256 amount,
Expand All @@ -40,41 +45,55 @@ contract KannaYield is Ownable, ReentrancyGuard {
);

IKannaToken private immutable knnToken;
address private immutable knnDeployer;

uint64 private constant feeDecimalAdjust = 1000 * 100;
uint64 private constant reducedFee = 100;

uint256 private feeDecimalAdjust = 1000;
uint256 private reducedFee = 10;
uint256 private knnYieldPool;
uint256 private startDate = 0;
uint256 private endDate = 0;
uint256 private rewardRate = 0;
uint256 private lastUpdateTime;
uint256 private rewardPerTokenStored;

uint256[] private tier = [1 days, 7 days, 30 days, 60 days, 90 days];

mapping(address => uint256) private holderRewardPerTokenPaid;
mapping(address => uint256) private earned;
mapping(address => uint256) private rawBalances;
mapping(uint256 => uint256) private fee;
mapping(address => uint256) private subscriptionStart;
mapping(address => uint256) private started;
mapping(uint256 => uint64) private fees;

uint256 private subscriptionFee = 200;

constructor(address knnTokenAddress) {
knnToken = IKannaToken(knnTokenAddress);
initialize();
knnDeployer = msg.sender;
tiering();
}

function initialize() private {
fee[tier[0]] = 10000;
fee[tier[1]] = 5000;
fee[tier[2]] = 2500;
fee[tier[3]] = 1500;
fee[tier[4]] = reducedFee;
function tiering() private {
fees[tier[0]] = 30000;
fees[tier[1]] = 5000;
fees[tier[2]] = 2500;
fees[tier[3]] = 1500;
fees[tier[4]] = reducedFee;
}

function getFee(uint256 subscriptionDuration) public view returns (uint) {
function feeOf(uint256 subscriptionDuration)
private
view
returns (uint256)
{
if (block.timestamp >= endDate) return reducedFee;

for (uint i = 0; i < tier.length; i++) {
if (subscriptionDuration < tier[i]) return fee[tier[i]];
if (subscriptionDuration < tier[i]) {
console.log("tier applied", i);

return fees[tier[i]];
}
}

return reducedFee;
Expand Down Expand Up @@ -107,30 +126,6 @@ contract KannaYield is Ownable, ReentrancyGuard {
);
}

function applyLastInterest(address holder) private {
uint256 currentPayment = earned[holder];
earned[holder] = earned[holder].sub(currentPayment);
rawBalances[holder] = rawBalances[holder].add(currentPayment);
knnYieldPool = knnYieldPool.add(currentPayment);
}

/// @dev deprecation notice! moving to "re-stake" for gas optimization
function applyHoldersInterests(address[] calldata holders)
external
onlyOwner
updateReward(address(0))
{
for (uint i = 0; i < holders.length; i++) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastPaymentEvent();
earned[holders[i]] = calculateReward(holders[i]);

applyLastInterest(holders[i]);

holderRewardPerTokenPaid[holders[i]] = rewardPerTokenStored;
}
}

function calculateReward(address holder) public view returns (uint256) {
return
rawBalances[holder]
Expand All @@ -144,9 +139,16 @@ contract KannaYield is Ownable, ReentrancyGuard {
nonReentrant
updateReward(msg.sender)
{
require(
subscriptionAmount > 0,
"Cannot subscribe 0 KNN. Provide a valid subscription amount"
require(endDate > block.timestamp, "No reward available");
console.log("endDate", endDate, block.timestamp);
require(subscriptionAmount > 0, "Cannot subscribe 0 KNN");

if (started[msg.sender] == 0) {
started[msg.sender] = block.timestamp;
}

uint256 finalAmount = subscriptionAmount.sub(
subscriptionAmount.mul(subscriptionFee).div(feeDecimalAdjust)
);

knnToken.safeTransferFrom(
Expand All @@ -155,29 +157,40 @@ contract KannaYield is Ownable, ReentrancyGuard {
subscriptionAmount
);

knnYieldPool = knnYieldPool.add(subscriptionAmount);
knnYieldPool = knnYieldPool.add(finalAmount);

rawBalances[msg.sender] = rawBalances[msg.sender].add(
subscriptionAmount
rawBalances[msg.sender] = rawBalances[msg.sender].add(finalAmount);

emit Subscription(
msg.sender,
subscriptionAmount,
subscriptionFee,
finalAmount,
block.timestamp
);

emit Subscription(msg.sender, subscriptionAmount, block.timestamp);
console.log(
"subscriptionFee",
subscriptionAmount / 1e18,
subscriptionFee,
finalAmount / 1e18
);
}

function withdraw(uint256 amount)
public
nonReentrant
updateReward(msg.sender)
{
require(amount > 0, "Invalid amount. Provide a value above 0 KNN");
require(rawBalances[msg.sender] >= amount, "Insufficient KNN balance");
require(amount > 0, "Invalid amount");
require(rawBalances[msg.sender] >= amount, "Insufficient balance");

knnYieldPool = knnYieldPool.sub(amount);
rawBalances[msg.sender] = rawBalances[msg.sender].sub(amount);

subscriptionStart[msg.sender] = block.timestamp;
started[msg.sender] = block.timestamp;

transfer(msg.sender, rawBalances[msg.sender]);
transferFee(msg.sender, rawBalances[msg.sender]);

emit Withdraw(msg.sender, amount, block.timestamp);
}
Expand Down Expand Up @@ -213,26 +226,24 @@ contract KannaYield is Ownable, ReentrancyGuard {
return;
}

transfer(msg.sender, balance);
transferFee(msg.sender, balance);

emit Reward(msg.sender, reward, block.timestamp);
}

function transfer(address to, uint256 amount) private returns (uint) {
uint256 subscriptionLength = block.timestamp.sub(
subscriptionStart[msg.sender]
);
function transferFee(address to, uint256 amount) private returns (uint) {
require(started[msg.sender] > 0, "Not in pool");
uint256 duration = block.timestamp.sub(started[msg.sender]);

uint256 userFee = getFee(subscriptionLength);
uint256 userFee = feeOf(duration);

uint256 finalAmount = amount.sub(
amount.mul(userFee).div(feeDecimalAdjust)
);

knnToken.safeTransfer(to, finalAmount);
emit Fee(to, amount, userFee, finalAmount, block.timestamp);

console.log(userFee, amount, finalAmount);
console.log("retentionFee", amount / 1e18, userFee, finalAmount / 1e18);

return userFee;
}
Expand All @@ -244,7 +255,7 @@ contract KannaYield is Ownable, ReentrancyGuard {
{
require(
block.timestamp.add(rewardsDuration) >= endDate,
"Cannot reduce current yield contract duration. Provide a longer duration or wait for contract termination"
"Cannot reduce current yield contract duration"
);
if (block.timestamp >= endDate) {
rewardRate = reward.div(rewardsDuration);
Expand All @@ -257,7 +268,7 @@ contract KannaYield is Ownable, ReentrancyGuard {
uint256 balance = knnToken.balanceOf(address(this));
require(
rewardRate <= balance.div(rewardsDuration),
"Insufficient KNN to pay rewards. Transfer KNN first prior to initiate yield distribution"
"Insufficient balance"
);

startDate = block.timestamp;
Expand All @@ -271,6 +282,14 @@ contract KannaYield is Ownable, ReentrancyGuard {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastPaymentEvent();
if (holder != address(0)) {
uint256 subscriptionDate = started[msg.sender];

if (
subscriptionDate > 0 &&
subscriptionDate < startDate &&
rawBalances[msg.sender] > 0
) started[msg.sender] = startDate;

earned[holder] = calculateReward(holder);
holderRewardPerTokenPaid[holder] = rewardPerTokenStored;
}
Expand Down
Loading

0 comments on commit 7975e3a

Please sign in to comment.