Skip to content

Instantly share code, notes, and snippets.

@ChanJuiHuang
Created September 3, 2022 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChanJuiHuang/dc0b08988b959f9f7646de8868763bf1 to your computer and use it in GitHub Desktop.
Save ChanJuiHuang/dc0b08988b959f9f7646de8868763bf1 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/*
建立一個 Bank 銀行
在 web3 世界人人都可以當銀行家!我們想開張一間去中心化金融中心,簡易小而美的銀行
使用者可以將我們發行的 Staking Token (ERC20代幣)存入銀行
使用者執行定存,會開始計算 Reward 利息回饋
使用者解除定存(withdraw),獲得 Reward 利息回饋
Deposit 定存:實作 deposit function,可以將 Staking Token 存入 Bank 合約
Withdraw 解除定存並提款,實作 withdraw function
TimeLock 固定鎖倉期
*/
contract AdvanceBank {
IERC20 public stakingToken;
IERC20 public rewardToken;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
uint256 public withdrawDeadline = 10 seconds;
uint256 public rewardRate = 1;
mapping (address => uint256) public rewardOf;
struct Deposit {
uint256 amount;
uint256 startTime;
uint256 endTime;
}
mapping (address => Deposit[]) public depositOf;
mapping (address => uint256) public lastUpdateTime;
constructor(IERC20 _stakingToken, IERC20 _rewardToken) {
stakingToken = _stakingToken;
rewardToken = _rewardToken;
}
modifier updateReward() {
rewardOf[msg.sender] = earned();
lastUpdateTime[msg.sender] = block.timestamp;
_;
}
function earned() public view returns (uint256) {
uint256 duration = block.timestamp - lastUpdateTime[msg.sender];
return balanceOf[msg.sender] * duration * rewardRate + rewardOf[msg.sender];
}
function deposit(uint256 _amount) external updateReward {
stakingToken.transferFrom(msg.sender, address(this), _amount);
totalSupply = totalSupply + _amount;
balanceOf[msg.sender] = balanceOf[msg.sender] + _amount;
depositOf[msg.sender].push(Deposit({
amount: _amount,
startTime: block.timestamp,
endTime: (block.timestamp + withdrawDeadline)
}));
}
function withdraw(uint256 _index) external updateReward {
require(balanceOf[msg.sender] > 0, "You have no balance to withdraw");
Deposit[] storage deposits = depositOf[msg.sender];
require(block.timestamp > deposits[_index].endTime, "End time does not reach");
uint256 amount = deposits[_index].amount;
stakingToken.transfer(msg.sender, amount);
totalSupply = totalSupply - amount;
balanceOf[msg.sender] = balanceOf[msg.sender] - amount;
deposits[_index] = deposits[deposits.length - 1];
deposits.pop();
}
function getReward() external updateReward {
require(rewardOf[msg.sender] > 0, "You have no reward");
uint256 reward = rewardOf[msg.sender];
rewardOf[msg.sender] = 0;
rewardToken.transfer(msg.sender, reward);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment