-
Notifications
You must be signed in to change notification settings - Fork 0
/
etf.sol
153 lines (114 loc) · 4.9 KB
/
etf.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import '@openzeppelin/contracts/security/ReentrancyGuard.sol';
interface IBTC {
function claimtokenRebase(address _address, uint256 amount) external;
}
interface Itoken is IERC20 {
function decimals() external view returns(uint256);
}
contract ETF is ERC20("ETF", "ETF"), Ownable(msg.sender) , ReentrancyGuard{
struct UserInfo {
uint256 totalbonded;
uint256 finalInteractionBlock;
uint256 VestTime;
}
Itoken public BondToken;
IBTC BTC;
constructor(address _BTC, address _Bondtoken) {
_mint(msg.sender, 0 * 10 ** decimals());
_setceil(0e18);
BTC = IBTC(_BTC);
BondToken = Itoken(_Bondtoken);
}
mapping(address => UserInfo) public userInfo;
using SafeERC20 for Itoken;
using SafeMath for uint256;
uint256 public bondPrice = 1000;
uint256 public bondCap = 0;
uint256 public maxperTX = 300e18;
uint256 public vestingTime = 5 days;
bool public bondOpen = false;
function burn(uint256 _amount) external {
_burn(msg.sender, _amount);
}
function setceil(uint256 _bondCap) external onlyOwner {
bondCap = _bondCap;
}
function _setceil(uint256 _bondCap) internal {
bondCap = _bondCap;
}
function setbondPrice(uint256 _bondPrice) external onlyOwner {
bondPrice = _bondPrice;
}
function setvestingTime(uint256 _period) external onlyOwner {
require(_period >= 0 days &&_period <=30 days);
vestingTime = _period;
}
function canclaimTokens(address _address) external view returns(uint256) {
uint256 durationPass = block.timestamp.sub(userInfo[_address].finalInteractionBlock);
uint256 canclaim;
if (durationPass >= userInfo[_address].VestTime){
canclaim = userInfo[_address].totalbonded;
}
else {
canclaim = userInfo[_address].totalbonded.mul(durationPass).div(userInfo[_address].VestTime);
}
return canclaim;
}
function setOpenbond(bool _bondOpen) external onlyOwner {
bondOpen = _bondOpen;
}
function setMAXtx(uint256 _max) external onlyOwner {
maxperTX = _max;
}
function recoverTreasuryTokens() external onlyOwner {
BondToken.safeTransfer(owner(), BondToken.balanceOf(address(this)));
}
function bond(uint256 _amount) external nonReentrant {
require(_amount <= maxperTX, "max");
require(bondOpen, "bnot opened");
require(BondToken.balanceOf(msg.sender) >= _amount, "BondToken b too low");
uint256 _amountin = _amount.mul(10**18).div(10**BondToken.decimals());
uint256 amountOut = _amountin.mul(1000).div(bondPrice);
require(this.totalSupply().add(amountOut) <= bondCap, "over bond cap");
userInfo[msg.sender].totalbonded = userInfo[msg.sender].totalbonded.add(amountOut);
userInfo[msg.sender].finalInteractionBlock = block.timestamp;
userInfo[msg.sender].VestTime = vestingTime;
_mint(address(this), amountOut);
BondToken.safeTransferFrom(msg.sender, address(this), _amount);
}
function claim() external nonReentrant {
require(userInfo[msg.sender].totalbonded > 0, "no bond");
uint256 durationPass = block.timestamp.sub(userInfo[msg.sender].finalInteractionBlock);
uint256 canclaim;
if (durationPass >= userInfo[msg.sender].VestTime){
canclaim = userInfo[msg.sender].totalbonded;
userInfo[msg.sender].VestTime = 0;
}
else {
canclaim = userInfo[msg.sender].totalbonded.mul(durationPass).div(userInfo[msg.sender].VestTime);
userInfo[msg.sender].VestTime = userInfo[msg.sender].VestTime.sub(durationPass);
}
userInfo[msg.sender].totalbonded = userInfo[msg.sender].totalbonded.sub(canclaim);
userInfo[msg.sender].finalInteractionBlock = block.timestamp;
this.burn(canclaim);
BTC.claimtokenRebase(msg.sender, canclaim);
}
function remainingbondableTokens() external view returns(uint256){
return bondCap.sub(this.totalSupply());
}
function remainingVestedTime(address _address) external view returns(uint256){
uint256 durationPass = block.timestamp.sub(userInfo[_address].finalInteractionBlock);
if (durationPass >= userInfo[_address].VestTime){
return 0;
}
else {
return userInfo[_address].VestTime.sub(durationPass);
}
}
}