# 第 3 次讀書會主題實作練習 - 建立一個 Bank 銀行 Dapp_陳其駿_Jim <h3> Staking Token </h3> ```solidity= // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract testERC20 is ERC20 { constructor() ERC20("testERC20", "tERC") { // _mint(msg.sender, 10 ** (9 + 18)); _mint(msg.sender, 1_000_000_000 * 1e18); } } ``` <h3> Bank </h3> ```solidity= // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract BasicBank { IERC20 public stakingToken; uint256 public totalStakedToken; 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; constructor(IERC20 _stakingToken) { stakingToken = _stakingToken; } function updateTotalStakenToken() internal { totalStakedToken = stakingToken.balanceOf(address(this)); } function deposit(uint256 _amount) external { stakingToken.transferFrom(msg.sender, address(this), _amount); totalStakedToken += _amount; balanceOf[msg.sender] += _amount; depositOf[msg.sender].push( Deposit({ amount: _amount, startTime: block.timestamp, endTime: block.timestamp + withdrawDeadline }) ); } function withdraw(uint256 _depositId) external { require(balanceOf[msg.sender] > 0, "You have no balance to withdraw"); Deposit[] storage deposits = depositOf[msg.sender]; require(block.timestamp >= deposits[_depositId].endTime, "Withdrawal Period is not reached yet"); require(_depositId <= deposits.length, "Deposit ID not exist!!"); uint256 currentReward = deposits[_depositId].amount + getInterest(_depositId); updateTotalStakenToken(); require(totalStakedToken >= currentReward, "Tokens in the pool is insufficient for the withdrawal"); rewardOf[msg.sender] += currentReward; stakingToken.transfer(msg.sender, currentReward); totalStakedToken -= currentReward; balanceOf[msg.sender] -= deposits[_depositId].amount; deposits[_depositId] = deposits[deposits.length - 1]; deposits.pop(); } function getInterest(uint256 _depositId) public view returns (uint256) { uint256 start = depositOf[msg.sender][_depositId].startTime; uint256 _amount = depositOf[msg.sender][_depositId].amount; return (block.timestamp - start) * rewardRate * _amount; } function getAllInterest() public view returns (uint256){ uint256 N = depositOf[msg.sender].length; uint256 allRewards; for (uint256 i = 0; i < N; i++) { allRewards += getInterest(i); } return allRewards; } } ``` <h3>屬性與方法</h3> >mapping >>balanceOf:查詢地址的餘額 >>rewardOf:查詢地址領取的總額 >>depositOf:查詢地址的存款狀況 >function >>deposit:存款方法 >>getInterest:取得存款的利息 >>getAllInterest:取得所有存款的利息 >>withdraw:提領方法