# **CrytoCamp Homework3**
###### tags: `Solidity`
## 1. <基礎作業>
1. 透過 remix JavaScript VM 部署合約
2. 部署任一自訂 ERC20 Token
3. 部署質押合約
- Deposit(存入)
- Reward(回饋)
- TimeLock(固定鎖倉期)
### ERC20
```solidity=
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor() ERC20("MyToken", "MT") {
_mint(msg.sender, 100000);
}
}
```
### Bank
```solidity=
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract Bank {
IERC20 public stakingToken;
mapping(address => uint256) public balanceOf;
// 池中總量
uint256 public totalSupply;
// 鎖倉時間
uint256 public lockRcord;
mapping(address => uint256) public lockStartOf;
mapping(address => uint256) public lockEndOf;
// 獎勵
uint256 public rewardRate = 1;
mapping(address => uint256) public rewardOf;
constructor(IERC20 _stakingToken) {
stakingToken = _stakingToken;
}
// 質押
function deposit(uint256 _amount, uint256 _lockTime) external {
require(_lockTime > 5, "Please enter a longer time");
lockRcord = _lockTime;
stakingToken.transferFrom(msg.sender, address(this), _amount); // 轉移代幣
totalSupply += _amount; // 紀錄質押數量
balanceOf[msg.sender] += _amount; // 紀錄個人質押數量
// 紀錄鎖倉時間
lockStartOf[msg.sender] = block.timestamp;
lockEndOf[msg.sender] = block.timestamp + _lockTime;
}
// 贖回
function withdraw(uint256 _amount) public {
require(block.timestamp > lockEndOf[msg.sender], "withdraw too soon");
require(_amount <= balanceOf[msg.sender], "insufficient token");
// 獲得獎勵
rewardOf[msg.sender] += getReward();
stakingToken.transfer(msg.sender, _amount);
totalSupply -= _amount;
balanceOf[msg.sender] -= _amount;
}
// 獎勵
function getReward() public view returns (uint256) {
uint256 duration = block.timestamp - lockStartOf[msg.sender];
//Rewaord scale
if (lockRcord <= 20) {
return duration * (rewardRate * 5) * balanceOf[msg.sender];
}else if (lockRcord > 20 && lockRcord <= 40) {
return duration * (rewardRate * 10) * balanceOf[msg.sender];
}else {
return duration * (rewardRate * 20) * balanceOf[msg.sender];
}
}
}
```
### 功能說明
存入時需要輸入存放金額與時間
一開始決定存放的時間,會影響到結算Reward金額
## 2. <進階作業>
### ERC20
```solidity=
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor() ERC20("MyToken", "MT") {
_mint(msg.sender, 100000);
}
}
```
### 會找時間補上 X﹏X
## 3. <進階作業>
### ERC20
```solidity=
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor() ERC20("MyToken", "MT") {
_mint(msg.sender, 100000);
}
}
```
### 會找時間補上 X﹏X