Last active
February 16, 2023 13:16
-
-
Save Falilah/8bfc9f34ecea56ad7bc4d0e8673c274c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.9; | |
interface IUSDT { | |
function approve(address _spender, uint256 _value) external; | |
function balanceOf(address who) external view returns (uint256); | |
function allowance(address _owner, address _spender) | |
external | |
returns (uint256 remaining); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ethers, network } from "hardhat"; | |
import { time } from "@nomicfoundation/hardhat-network-helpers"; | |
import hre from "hardhat"; | |
import { BigNumber } from "ethers"; | |
async function main() { | |
const DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; | |
const DAIHolder = "0x748dE14197922c4Ae258c7939C7739f3ff1db573"; | |
// const [owner, holder1, holder2, holder3] = await ethers.getSigners(); | |
//deploy reward token | |
const Token = await ethers.getContractFactory("CVIII"); | |
const token = await Token.deploy("web3Bridge", "VIII"); | |
await token.deployed(); | |
const tokenaddress = token.address; | |
console.log(`Reward Token deployed to ${tokenaddress}`); | |
///deploy Staking contract | |
const Staking = await ethers.getContractFactory("StakERC20"); | |
const staking = await Staking.deploy(tokenaddress); | |
await staking.deployed(); | |
console.log(`Staking contract deployed to ${staking.address}`); | |
/// connect dai | |
const dai = await ethers.getContractAt("IDAI", DAI); | |
const daiAdress = dai.address; | |
console.log(`staking Token deployed to ${daiAdress}`); | |
const balance = await dai.balanceOf(DAIHolder); | |
console.log(`balnce is ${balance}`); | |
const helpers = require("@nomicfoundation/hardhat-network-helpers"); | |
const address = DAIHolder; | |
await helpers.impersonateAccount(address); | |
const impersonatedSigner = await ethers.getSigner(address); | |
const tokenSet = await staking.setStakeToken(daiAdress); | |
// console.log(await tokenSet.wait()); | |
console.log(`staked Token ${await staking.stakeToken()}`); | |
const stakeDai = await ethers.utils.parseEther("50"); | |
await dai.connect(impersonatedSigner).approve(staking.address, stakeDai); | |
const allowance = await dai.allowance(DAIHolder, staking.address); | |
// console.log(`allowance ${allowance.wait()}`); | |
const staker1 = await staking.connect(impersonatedSigner).stake(stakeDai); | |
const userInfo1 = await staking.userInfo(impersonatedSigner.address); | |
console.log(`holder1 infornation ${userInfo1}`); | |
await ethers.provider.send("evm_mine", [1708037999]); | |
await staking.connect(impersonatedSigner).updateReward(); | |
const userInfo = await staking.userInfo(impersonatedSigner.address); | |
console.log(`holder1 infornation ${userInfo}`); | |
let a = BigNumber.from("10000000000000000000"); | |
// let b = BigNumber.from("10000000000000000000"); | |
await token.transfer(staking.address, a); | |
await staking.connect(impersonatedSigner).claimReward(a); | |
const userInfoAfter = await staking.userInfo(impersonatedSigner.address); | |
console.log(`holder1 infornation ${userInfoAfter}`); | |
} | |
// We recommend this pattern to be able to use async/await everywhere | |
// and properly handle errors. | |
main().catch((error) => { | |
console.error(error); | |
process.exitCode = 1; | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.9; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
//users stake usdt | |
//user get 20% APY CVIII as reward; | |
// tken ratio 1: 1 | |
contract StakERC20 is Ownable { | |
IERC20 public rewardToken; | |
IERC20 public stakeToken; | |
uint256 constant SECONDS_PER_YEAR = 31536000; | |
struct User { | |
uint256 stakedAmount; | |
uint256 startTime; | |
uint256 rewardAccrued; | |
} | |
mapping(address => User) user; | |
error tryAgain(); | |
constructor(address _rewardToken) { | |
rewardToken = IERC20(_rewardToken); | |
} | |
function setStakeToken(address _token) | |
external | |
onlyOwner | |
returns (address _newToken) | |
{ | |
require(IERC20(_token) != stakeToken, "Token already set"); | |
require(IERC20(_token) != rewardToken, "canot stake reward"); | |
require(_token != address(0), "cannot set address zero"); | |
stakeToken = IERC20(_token); | |
_newToken = address(stakeToken); | |
} | |
function stake(uint256 amount) external { | |
User storage _user = user[msg.sender]; | |
uint256 _amount = _user.stakedAmount; | |
stakeToken.transferFrom(msg.sender, address(this), amount); | |
if (_amount == 0) { | |
_user.stakedAmount = amount; | |
_user.startTime = block.timestamp; | |
} else { | |
updateReward(); | |
_user.stakedAmount += amount; | |
} | |
} | |
function calcReward() public view returns (uint256 _reward) { | |
User storage _user = user[msg.sender]; | |
uint256 _amount = _user.stakedAmount; | |
uint256 _startTime = _user.startTime; | |
uint256 duration = block.timestamp - _startTime; | |
_reward = (duration * 20 * _amount) / (SECONDS_PER_YEAR * 100); | |
} | |
function claimReward(uint256 amount) public { | |
User storage _user = user[msg.sender]; | |
updateReward(); | |
uint256 _claimableReward = _user.rewardAccrued; | |
require(_claimableReward >= amount, "insufficient funds"); | |
_user.rewardAccrued -= amount; | |
if (amount > rewardToken.balanceOf(address(this))) revert tryAgain(); | |
rewardToken.transfer(msg.sender, amount); | |
} | |
function updateReward() public { | |
User storage _user = user[msg.sender]; | |
uint256 _reward = calcReward(); | |
_user.rewardAccrued += _reward; | |
_user.startTime = block.timestamp; | |
} | |
function withdrawStaked(uint256 amount) public { | |
User storage _user = user[msg.sender]; | |
uint256 staked = _user.stakedAmount; | |
require(staked >= amount, "insufficient fund"); | |
updateReward(); | |
_user.stakedAmount -= amount; | |
stakeToken.transfer(msg.sender, amount); | |
} | |
function closeAccount() external { | |
User storage _user = user[msg.sender]; | |
uint256 staked = _user.stakedAmount; | |
withdrawStaked(staked); | |
uint256 reward = _user.rewardAccrued; | |
claimReward(reward); | |
} | |
function userInfo(address _user) external view returns (User memory) { | |
return user[_user]; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ethers, network } from "hardhat"; | |
import { time } from "@nomicfoundation/hardhat-network-helpers"; | |
async function main() { | |
const [owner, holder1, holder2, holder3] = await ethers.getSigners(); | |
//deploy reward token | |
const Token = await ethers.getContractFactory("CVIII"); | |
const token = await Token.deploy("web3Bridge", "VIII"); | |
await token.deployed(); | |
const tokenaddress = token.address; | |
console.log(`Reward Token deployed to ${tokenaddress}`); | |
///deploy Staking contract | |
const Staking = await ethers.getContractFactory("StakERC20"); | |
const staking = await Staking.deploy(tokenaddress); | |
await staking.deployed(); | |
console.log(`Staking contract deployed to ${staking.address}`); | |
// Mock usdt | |
const USDT = await ethers.getContractFactory("USDT"); | |
const usdt = await USDT.deploy("Tether", "USDT"); | |
await usdt.deployed(); | |
const usdtAdress = usdt.address; | |
console.log(`staking Token deployed to ${usdtAdress}`); | |
const tokenSet = await staking.setStakeToken(usdtAdress); | |
// console.log(await tokenSet.wait()); | |
console.log(`staked Token ${await staking.stakeToken()}`); | |
const staker1Minting = await usdt.connect(holder1).mint(100); | |
await usdt.connect(holder1).approve(staking.address, 100000000); | |
const staker1 = await staking.connect(holder1).stake(50000000); | |
const userInfo1 = await staking.userInfo(holder1.address); | |
console.log(`holder1 infornation ${userInfo1}`); | |
await ethers.provider.send("evm_mine", [1708037999]); | |
await staking.connect(holder1).updateReward(); | |
const userInfo = await staking.userInfo(holder1.address); | |
console.log(`holder1 infornation ${userInfo}`); | |
await token.transfer(staking.address, 100000000); | |
await staking.connect(holder1).claimReward(10000000); | |
const userInfoAfter = await staking.userInfo(holder1.address); | |
console.log(`holder1 infornation ${userInfoAfter}`); | |
} | |
// We recommend this pattern to be able to use async/await everywhere | |
// and properly handle errors. | |
main().catch((error) => { | |
console.error(error); | |
process.exitCode = 1; | |
}); | |
//18 772 231 | |
// 18 772 216 | |
// 10 005 054 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment