Created
September 3, 2022 03:49
-
-
Save ChanJuiHuang/dc0b08988b959f9f7646de8868763bf1 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: 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