This repository has been archived by the owner on Mar 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
SmartVaultManagerV5.sol
144 lines (121 loc) · 5.58 KB
/
SmartVaultManagerV5.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
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "contracts/interfaces/INFTMetadataGenerator.sol";
import "contracts/interfaces/IEUROs.sol";
import "contracts/interfaces/ISmartVault.sol";
import "contracts/interfaces/ISmartVaultDeployer.sol";
import "contracts/interfaces/ISmartVaultIndex.sol";
import "contracts/interfaces/ISmartVaultManager.sol";
import "contracts/interfaces/ISmartVaultManagerV2.sol";
contract SmartVaultManagerV5 is ISmartVaultManager, ISmartVaultManagerV2, Initializable, ERC721Upgradeable, OwnableUpgradeable {
using SafeERC20 for IERC20;
uint256 public constant HUNDRED_PC = 1e5;
address public protocol;
address public liquidator;
address public euros;
uint256 public collateralRate;
address public tokenManager;
address public smartVaultDeployer;
ISmartVaultIndex private smartVaultIndex;
uint256 private lastToken;
address public nftMetadataGenerator;
uint256 public mintFeeRate;
uint256 public burnFeeRate;
uint256 public swapFeeRate;
address public weth;
address public swapRouter;
address public swapRouter2;
event VaultDeployed(address indexed vaultAddress, address indexed owner, address vaultType, uint256 tokenId);
event VaultLiquidated(address indexed vaultAddress);
event VaultTransferred(uint256 indexed tokenId, address from, address to);
struct SmartVaultData {
uint256 tokenId; uint256 collateralRate; uint256 mintFeeRate;
uint256 burnFeeRate; ISmartVault.Status status;
}
function initialize() initializer public {}
modifier onlyLiquidator {
require(msg.sender == liquidator, "err-invalid-liquidator");
_;
}
function vaults() external view returns (SmartVaultData[] memory) {
uint256[] memory tokenIds = smartVaultIndex.getTokenIds(msg.sender);
uint256 idsLength = tokenIds.length;
SmartVaultData[] memory vaultData = new SmartVaultData[](idsLength);
for (uint256 i = 0; i < idsLength; i++) {
uint256 tokenId = tokenIds[i];
vaultData[i] = SmartVaultData({
tokenId: tokenId,
collateralRate: collateralRate,
mintFeeRate: mintFeeRate,
burnFeeRate: burnFeeRate,
status: ISmartVault(smartVaultIndex.getVaultAddress(tokenId)).status()
});
}
return vaultData;
}
function mint() external returns (address vault, uint256 tokenId) {
tokenId = lastToken + 1;
_safeMint(msg.sender, tokenId);
lastToken = tokenId;
vault = ISmartVaultDeployer(smartVaultDeployer).deploy(address(this), msg.sender, euros);
smartVaultIndex.addVaultAddress(tokenId, payable(vault));
IEUROs(euros).grantRole(IEUROs(euros).MINTER_ROLE(), vault);
IEUROs(euros).grantRole(IEUROs(euros).BURNER_ROLE(), vault);
emit VaultDeployed(vault, msg.sender, euros, tokenId);
}
function liquidateVault(uint256 _tokenId) external onlyLiquidator {
ISmartVault vault = ISmartVault(smartVaultIndex.getVaultAddress(_tokenId));
try vault.undercollateralised() returns (bool _undercollateralised) {
require(_undercollateralised, "vault-not-undercollateralised");
vault.liquidate();
IEUROs(euros).revokeRole(IEUROs(euros).MINTER_ROLE(), address(vault));
IEUROs(euros).revokeRole(IEUROs(euros).BURNER_ROLE(), address(vault));
emit VaultLiquidated(address(vault));
} catch {
revert("other-liquidation-error");
}
}
function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
ISmartVault.Status memory vaultStatus = ISmartVault(smartVaultIndex.getVaultAddress(_tokenId)).status();
return INFTMetadataGenerator(nftMetadataGenerator).generateNFTMetadata(_tokenId, vaultStatus);
}
function totalSupply() external view returns (uint256) {
return lastToken;
}
function setMintFeeRate(uint256 _rate) external onlyOwner {
mintFeeRate = _rate;
}
function setBurnFeeRate(uint256 _rate) external onlyOwner {
burnFeeRate = _rate;
}
function setSwapFeeRate(uint256 _rate) external onlyOwner {
swapFeeRate = _rate;
}
function setWethAddress(address _weth) external onlyOwner() {
weth = _weth;
}
function setSwapRouter2(address _swapRouter) external onlyOwner() {
swapRouter2 = _swapRouter;
}
function setNFTMetadataGenerator(address _nftMetadataGenerator) external onlyOwner() {
nftMetadataGenerator = _nftMetadataGenerator;
}
function setSmartVaultDeployer(address _smartVaultDeployer) external onlyOwner() {
smartVaultDeployer = _smartVaultDeployer;
}
function setProtocolAddress(address _protocol) external onlyOwner() {
protocol = _protocol;
}
function setLiquidatorAddress(address _liquidator) external onlyOwner() {
liquidator = _liquidator;
}
function _afterTokenTransfer(address _from, address _to, uint256 _tokenId, uint256) internal override {
smartVaultIndex.transferTokenId(_from, _to, _tokenId);
if (address(_from) != address(0)) ISmartVault(smartVaultIndex.getVaultAddress(_tokenId)).setOwner(_to);
emit VaultTransferred(_tokenId, _from, _to);
}
}