/
Lock.sol
143 lines (125 loc) · 4.12 KB
/
Lock.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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "hardhat/console.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/IBondNFT.sol";
import "./interfaces/IGovNFT.sol";
contract Lock is Ownable{
uint public constant minPeriod = 7;
uint public constant maxPeriod = 365;
IBondNFT public immutable bondNFT;
IGovNFT public immutable govNFT;
mapping(address => bool) public allowedAssets;
mapping(address => uint) public totalLocked;
constructor(
address _bondNFTAddress,
address _govNFT
) {
bondNFT = IBondNFT(_bondNFTAddress);
govNFT = IGovNFT(_govNFT);
}
/**
* @notice Claim pending rewards from a bond
* @param _id Bond NFT id
* @return address claimed tigAsset address
*/
function claim(
uint256 _id
) public returns (address) {
claimGovFees();
(uint _amount, address _tigAsset) = bondNFT.claim(_id, msg.sender);
IERC20(_tigAsset).transfer(msg.sender, _amount);
return _tigAsset;
}
/**
* @notice Claim pending rewards left over from a bond transfer
* @param _tigAsset token address being claimed
*/
function claimDebt(
address _tigAsset
) external {
claimGovFees();
uint amount = bondNFT.claimDebt(msg.sender, _tigAsset);
IERC20(_tigAsset).transfer(msg.sender, amount);
}
/**
* @notice Lock up tokens to create a bond
* @param _asset tigAsset being locked
* @param _amount tigAsset amount
* @param _period number of days to be locked for
*/
function lock(
address _asset,
uint _amount,
uint _period
) public {
require(_period <= maxPeriod, "MAX PERIOD");
require(_period >= minPeriod, "MIN PERIOD");
require(allowedAssets[_asset], "!asset");
claimGovFees();
IERC20(_asset).transferFrom(msg.sender, address(this), _amount);
totalLocked[_asset] += _amount;
bondNFT.createLock( _asset, _amount, _period, msg.sender);
}
/**
* @notice Reset the lock time and extend the period and/or token amount
* @param _id Bond id being extended
* @param _amount tigAsset amount being added
* @param _period number of days being added
*/
function extendLock(
uint _id,
uint _amount,
uint _period
) public {
address _asset = claim(_id);
IERC20(_asset).transferFrom(msg.sender, address(this), _amount);
bondNFT.extendLock(_id, _asset, _amount, _period, msg.sender);
}
/**
* @notice Release the bond once it's expired
* @param _id Bond id being released
*/
function release(
uint _id
) public {
claimGovFees();
(uint amount, uint lockAmount, address asset, address _owner) = bondNFT.release(_id, msg.sender);
totalLocked[asset] -= lockAmount;
IERC20(asset).transfer(_owner, amount);
}
/**
* @notice Claim rewards from gov nfts and distribute them to bonds
*/
function claimGovFees() public {
address[] memory assets = bondNFT.getAssets();
for (uint i=0; i < assets.length; i++) {
uint balanceBefore = IERC20(assets[i]).balanceOf(address(this));
IGovNFT(govNFT).claim(assets[i]);
uint balanceAfter = IERC20(assets[i]).balanceOf(address(this));
IERC20(assets[i]).approve(address(bondNFT), type(uint256).max);
bondNFT.distribute(assets[i], balanceAfter - balanceBefore);
}
}
/**
* @notice Whitelist an asset
* @param _tigAsset tigAsset token address
* @param _isAllowed set tigAsset as allowed
*/
function editAsset(
address _tigAsset,
bool _isAllowed
) external onlyOwner() {
allowedAssets[_tigAsset] = _isAllowed;
}
/**
* @notice Owner can retreive Gov NFTs
* @param _ids array of gov nft ids
*/
function sendNFTs(
uint[] memory _ids
) external onlyOwner() {
govNFT.safeTransferMany(msg.sender, _ids);
}
}