Closed shivasai780 closed 1 year ago
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./Iint.sol";
contract TimechainProtocol is ReentrancyGuard {
// Define the structure for the protocol's Burning pool
struct BurningPool {
uint256 totalInputs;
uint256 timeChainsLeft;
mapping(uint => mapping(uint => uint)) slashingPercentage; // slashingpercent[number of investment][Amount]=slashpercent
mapping(uint => uint) amountStaked;
uint256 noOfinvestments;
address usdUsed;
uint256 startingBlock;
uint256 totalslashedAmount;
}
// Mapping to store the protocol's Burning pool data
mapping(address => BurningPool) public BurningPools;
// GLIPs vault to hold the slashed INT
mapping(address => uint256) public glipsVaultAmount;
address public stableCoin1;
address public stableCoin2;
address public stableCoin3;
address public stableCoin4;
address public glipsVault;
Iint public intToken;
address public owner;
constructor(address _stableCoin1, address _stableCoin2, address _stableCoin3, address _stableCoin4, address _intToken) {
stableCoin1 = _stableCoin1;
stableCoin2 = _stableCoin2;
stableCoin3 = _stableCoin3;
stableCoin4 = _stableCoin4;
intToken = Iint(_intToken);
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only the owner can perform this action");
_;
}
modifier timechainCompleted(address _protocolAddress) {
require((block.timestamp - BurningPools[_protocolAddress].startingBlock) >= 7 days, "Timechains are not completed yet");
_;
}
modifier hasRemainingINT(address _protocolAddress) {
BurningPool storage pool = BurningPools[_protocolAddress];
uint256 remainingINT = pool.totalInputs - pool.totalslashedAmount;
require(remainingINT > 0, "No INT remaining to be claimed");
_;
}
// Initialize the protocol's Burning pool with initial values
function initializeBurningPool(address _protocolAddress, address usdUsed, uint256 _totalamount) external nonReentrant {
require(_protocolAddress != address(0), "The address cannot be equal to zero address");
require(usdUsed != address(0), "the address cannot be equal to zero address");
require(_totalamount != 0, "the given amount cannot be equal to zero ");
require(BurningPools[_protocolAddress].totalInputs == 0, "Burning pool already initialized");
require(BurningPools[_protocolAddress].noOfinvestments == 0, "The pool is already initialized");
require(usdUsed == stableCoin1 || usdUsed == stableCoin2 || usdUsed == stableCoin3 || usdUsed == stableCoin4, "The token used should be any one of them");
BurningPools[_protocolAddress].totalInputs = _totalamount;
BurningPools[_protocolAddress].timeChainsLeft = 50;
BurningPools[_protocolAddress].slashingPercentage[1][_totalamount] = 2;
BurningPools[_protocolAddress].noOfinvestments = 1;
BurningPools[_protocolAddress].amountStaked[1] = _totalamount;
BurningPools[_protocolAddress].usdUsed = usdUsed;
BurningPools[_protocolAddress].startingBlock = block.timestamp;
// Transfer the usd to this account, before that he needs to give approval for this contract
IERC20(usdUsed).transferFrom(msg.sender, address(this), _totalamount);
}
// Function to add new inputs to the Burning pool
function addInputsToBurningPool(address _protocolAddress, uint256 _totalamount) external nonReentrant {
require(_protocolAddress != address(0), "The address cannot be equal to zero address");
require(_totalamount != 0, "the given amount cannot be equal to zero ");
BurningPool storage pool = BurningPools[_protocolAddress];
// Calculate the slashing percentage for the new supply of INT
uint256 slashingPercentage = 100 / pool.timeChainsLeft;
// Update the Burning pool data with the new inputs and slashing percentage
pool.totalInputs += _totalamount;
pool.noOfinvestments += 1;
pool.amountStaked[1] = _totalamount;
pool.slashingPercentage[pool.noOfinvestments][_totalamount] = slashingPercentage;
IERC20(pool.usdUsed).transferFrom(msg.sender, address(this), _totalamount);
}
// Function to slash the INT tokens based on the current timechain
function slashTokens(address _protocolAddress) external nonReentrant {
require(_protocolAddress != address(0), "The address cannot be equal to zero address");
BurningPool storage pool = BurningPools[_protocolAddress];
require(pool.timeChainsLeft > 0, "The Timechains needs to be greater than 0");
uint completedTimeChains = (block.timestamp - pool.startingBlock) / 7 days;
uint FinalTimeChainLeft = completedTimeChains - (50 - pool.timeChainsLeft);
uint256 slashedAmount;
for (uint i = 0; i <= pool.noOfinvestments; i++) {
uint amountstaked = pool.amountStaked[i + 1];
// Calculate the slashed amount for this period
slashedAmount += (amountstaked * (pool.slashingPercentage[i + 1][amountstaked] * completedTimeChains)) / 100;
}
// Update the Burning pool's total inputs after slashing
pool.totalslashedAmount += slashedAmount;
// Add the slashed amount to the GLIPs vault
glipsVaultAmount[msg.sender] += slashedAmount;
// Decrease the number of timechains left
pool.timeChainsLeft -= completedTimeChains;
// send the amount to the glipsVault
IERC20(pool.usdUsed).transfer(glipsVault, slashedAmount);
}
// Function to get the balance of INT available to spend at the start of the current timechain
function getBalance(address _protocolAddress) external view returns (uint256) {
require(_protocolAddress != address(0), "The address cannot be equal to zero address");
BurningPool storage pool = BurningPools[_protocolAddress];
return pool.totalInputs - pool.totalslashedAmount;
}
// Function to burn and claim the USD after the end of every timechain
function burnAndClaim(uint256 amount) external nonReentrant {
require(amount != 0, "Amount should be greater than 0");
require(intToken.balanceOf(msg.sender) >= amount, "Not enough INT balance to burn");
BurningPool storage pool = BurningPools[msg.sender];
require((block.timestamp - pool.startingBlock) >= 7 days, "The timechain has not completed 7 days yet");
address currentStableCoin = findGreatest(stableCoin1, stableCoin2, stableCoin3, stableCoin4);
intToken.burn(amount);
IERC20(currentStableCoin).transfer(msg.sender, amount);
}
// Function to find the greatest stablecoin balance among the four
function findGreatest(address _stableCoin1, address _stableCoin2, address _stableCoin3, address _stableCoin4) public view returns (address) {
address greatestCoin = _stableCoin1;
uint256 greatestBalance = IERC20(_stableCoin1).balanceOf(address(this));
if (IERC20(_stableCoin2).balanceOf(address(this)) > greatestBalance) {
greatestCoin = _stableCoin2;
greatestBalance = IERC20(_stableCoin2).balanceOf(address(this));
}
if (IERC20(_stableCoin3).balanceOf(address(this)) > greatestBalance) {
greatestCoin = _stableCoin3;
greatestBalance = IERC20(_stableCoin3).balanceOf(address(this));
}
if (IERC20(_stableCoin4).balanceOf(address(this)) > greatestBalance) {
greatestCoin = _stableCoin4;
}
return greatestCoin;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./Iint.sol";
contract TimechainProtocol is ReentrancyGuard{
// Define the structure for the protocol's Burning pool
struct BurningPool {
uint256 totalInputs;
uint256 timeChainsLeft;
mapping(uint=>mapping(uint=>uint)) slashingPercentage;//slashingpercent[number of investment][Amount]=slashpercent
mapping(uint => uint)amountStaked;
uint256 noOfinvestments;
address usdUsed;
uint256 startingBlock;
uint256 totalslashedAmount;
}
// Mapping to store the protocol's Burning pool data
mapping(address => BurningPool) public BurningPools;
// GLIPs vault to hold the slashed INT
mapping(address => uint256) public glipsVaultAmount;
address public stableCoin1;
address public stableCoin2;
address public stableCoin3;
address public stableCoin4;
address public glipsVault;
Iint public intToken;
address public owner;
constructor(address _stableCoin1,address _stableCoin2,address _stableCoin3,address _stableCoin4,address _intToken) {
stableCoin1 = _stableCoin1;
stableCoin2=_stableCoin2;
stableCoin3=_stableCoin3;
stableCoin4=_stableCoin4;
intToken=Iint(_intToken);
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only the owner can perform this action");
_;
}
// Initialize the protocol's Burning pool with initial values
function initializeBurningPool(address _protocolAddress,address usdUsed,uint _totalamount) external nonReentrant{
require(_protocolAddress!=address(0),"The address cannot be equal to zero address");
require(usdUsed != address(0),"the address cannot be equal to zero address");
require(_totalamount != 0,"the given amount cannot be equal to zero ");
require(BurningPools[_protocolAddress].totalInputs == 0, "Burning pool already initialized");
require(BurningPools[_protocolAddress].noOfinvestments == 0,"The pool is already initialized");
require(usdUsed == stableCoin1 || usdUsed == stableCoin2 || usdUsed ==stableCoin3 || usdUsed == stableCoin4 ,"The tokem used should be any one of them");
BurningPools[_protocolAddress].totalInputs=_totalamount;
BurningPools[_protocolAddress].timeChainsLeft=50;
BurningPools[_protocolAddress].slashingPercentage[1][_totalamount]=2;
BurningPools[_protocolAddress].noOfinvestments=1;
BurningPools[_protocolAddress].amountStaked[1]=_totalamount;
BurningPools[_protocolAddress].usdUsed=usdUsed;
BurningPools[_protocolAddress].startingBlock = block.timestamp;
//transfer the usd to this account,before that he need to give the approval for this contract
IERC20(usdUsed).transferFrom(msg.sender,address(this),_totalamount);
}
// Function to add new inputs to the Burning pool
function addInputsToBurningPool(address _protocolAddress,uint _totalamount) external nonReentrant{
require(_protocolAddress!=address(0),"The address cannot be equal to zero address");
require(_totalamount != 0,"the given amount cannot be equal to zero ");
BurningPool storage pool = BurningPools[_protocolAddress];
// Calculate the slashing percentage for the new supply of INT
uint256 slashingPercentage = 100 / pool.timeChainsLeft;
// Update the Burning pool data with the new inputs and slashing percentage
pool.totalInputs += _totalamount;
pool.noOfinvestments +=1;
pool.amountStaked[1]=_totalamount;
pool.slashingPercentage[pool.noOfinvestments][_totalamount]=slashingPercentage;
IERC20(pool.usdUsed).transferFrom(msg.sender,address(this),_totalamount);
}
// Function to slash the INT tokens based on the current timechain
function slashTokens(address _protocolAddress) external nonReentrant{
require(_protocolAddress!=address(0),"The address cannot be equal to zero address");
BurningPool storage pool = BurningPools[_protocolAddress];
require(pool.timeChainsLeft > 0,"The Timechains needs to be greater than 0");
uint completedTimeChains= (block.timestamp - pool.startingBlock)/7 days;
uint FinalTimeChainLeft=completedTimeChains-(50-pool.timeChainsLeft);
uint256 slashedAmount;
for(uint i= 0 ;i<=pool.noOfinvestments;i++)
{
uint amountstaked=pool.amountStaked[i+1];
// Calculate the slashed amount for this period
slashedAmount += (amountstaked * (pool.slashingPercentage[i+1][amountstaked]* completedTimeChains)) / 100;
}
// Update the Burning pool's total inputs after slashing
pool.totalslashedAmount += slashedAmount;
// Add the slashed amount to the GLIPs vault
glipsVaultAmount[msg.sender] += slashedAmount;
// Decrease the number of timechains left
pool.timeChainsLeft -= completedTimeChains;
//send the amount to the glipsVault
IERC20(pool.usdUsed).transfer(glipsVault,slashedAmount);
}
// Function to get the balance of INT available to spend at the start of the current timechain
function getBalance(address _protocolAddress) external view returns (uint256) {
require(_protocolAddress!=address(0),"The address cannot be equal to zero address");
BurningPool storage pool = BurningPools[_protocolAddress];
return pool.totalInputs - pool.totalslashedAmount;
}
function burnandClaim(address _protocol,uint256 amount) external nonReentrant {
require(amount!=0,"The address cannot be equal to zero address");
require(intToken.balanceOf(msg.sender)>= amount,"Not Sufficient Amount in your wallet");
require(IERC20(stableCoin1).balanceOf(address(this))>=amount || IERC20(stableCoin2).balanceOf(address(this))>=amount || IERC20(stableCoin3).balanceOf(address(this))>=amount || IERC20(stableCoin4).balanceOf(address(this))>=amount,"No sufficient Amount in the pool");
BurningPool storage pool = BurningPools[_protocolAddress];
require((block.timestamp - pool.startingBlock) >= 7 days,"The timechain had till not completed");
address currentStableCoin = findGreatest(stableCoin1, stableCoin2, stableCoin3, stableCoin4);
intToken.transferFrom(msg.sender,address(this),amount);
intToken.burn(amount);
IERC20(currentStableCoin).transfer(msg.sender,amount);
}
function findGreatest(address _stableCoin1,address _stableCoin2,address _stableCoin3,address _stableCoin4) public view returns (address) {
// Using if-else statements
address greatestCoin;
if ( IERC20(_stableCoin1).balanceOf(address(this))>= IERC20(_stableCoin2).balanceOf(address(this)) && IERC20(_stableCoin1).balanceOf(address(this)) >= IERC20(_stableCoin3).balanceOf(address(this)) && IERC20(_stableCoin1).balanceOf(address(this)) >= IERC20(_stableCoin4).balanceOf(address(this))) {
greatestCoin = _stableCoin1;
} else if (IERC20(_stableCoin2).balanceOf(address(this)) >= IERC20(_stableCoin1).balanceOf(address(this)) && IERC20(_stableCoin2).balanceOf(address(this)) >= IERC20(_stableCoin3).balanceOf(address(this)) && IERC20(_stableCoin2).balanceOf(address(this)) >= IERC20(_stableCoin4).balanceOf(address(this))) {
greatestCoin = _stableCoin2;
} else if (IERC20(_stableCoin3).balanceOf(address(this)) >= IERC20(_stableCoin1).balanceOf(address(this)) && IERC20(_stableCoin3).balanceOf(address(this)) >= IERC20(_stableCoin2).balanceOf(address(this)) && IERC20(_stableCoin3).balanceOf(address(this)) >= IERC20(_stableCoin4).balanceOf(address(this))) {
greatestCoin = _stableCoin3;
} else {
greatestCoin = _stableCoin4;
}
return greatestCoin;
}
}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/access/Ownable.sol";
contract TimechainProtocol is Ownable { using SafeMath for uint256;
struct BurningPool { uint256 totalInputs; uint256 timechainInterval; uint256 noOfTimechains; address usdUsed; uint256 startingBlock; }
mapping(address => BurningPool) public burningPools;
address[] public stableCoins; address public intToken;
constructor(address[] memory _stableCoins, address _intToken) { require(_stableCoins.length > 0, "No stable coins provided"); require(_intToken != address(0), "Invalid INT token address"); stableCoins = _stableCoins; intToken = _intToken; }
function initializeBurningPool(address _usdUsed, uint256 _totalAmount) external onlyOwner { require(_usdUsed != address(0), "Invalid token address"); require(_totalAmount > 0, "Total amount must be greater than zero");
burningPools[msg.sender] = BurningPool(_totalAmount, 7 days, 0, _usdUsed, block.timestamp);
IERC20(_usdUsed).transferFrom(msg.sender, address(this), _totalAmount);
}
function addInputsToBurningPool(uint256 _totalAmount) external { require(_totalAmount > 0, "Total amount must be greater than zero"); BurningPool storage pool = burningPools[msg.sender]; require(block.timestamp >= pool.startingBlock.add(pool.timechainInterval), "Cannot add inputs before the timechain interval is over");
pool.totalInputs = pool.totalInputs.add(_totalAmount);
pool.noOfTimechains = pool.noOfTimechains.add(1);
IERC20(pool.usdUsed).transferFrom(msg.sender, address(this), _totalAmount);
pool.startingBlock = block.timestamp;
}
function burnAndClaim() external { BurningPool storage pool = burningPools[msg.sender]; require(pool.noOfTimechains > 0, "Burning pool not initialized"); require(block.timestamp >= pool.startingBlock.add(pool.timechainInterval), "Cannot burn and claim before the timechain interval is over");
uint256 amount = IERC20(intToken).balanceOf(msg.sender);
require(amount > 0, "No INT to burn and claim");
address currentStableCoin = findGreatestStableCoin();
IERC20(intToken).transferFrom(msg.sender, address(this), amount);
IERC20(currentStableCoin).transfer(msg.sender, amount);
}
function getBalance() external view returns (uint256) { BurningPool storage pool = burningPools[msg.sender]; return pool.totalInputs; }
function findGreatestStableCoin() internal view returns (address) { address greatestCoin = stableCoins[0];
for (uint256 i = 1; i < stableCoins.length; i++) {
if (IERC20(stableCoins[i]).balanceOf(address(this)) > IERC20(greatestCoin).balanceOf(address(this))) {
greatestCoin = stableCoins[i];
}
}
return greatestCoin;
} }
@shivasai780 @sscodez @123456788940 @vinaykumar0103 @sscodez @yashpandey59