-
Notifications
You must be signed in to change notification settings - Fork 17
/
BathHouseV2.sol
150 lines (129 loc) · 4.68 KB
/
BathHouseV2.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
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./compound-v2-fork/InterestRateModel.sol";
import "./compound-v2-fork/CErc20Delegator.sol";
import "./compound-v2-fork/Comptroller.sol";
import "./compound-v2-fork/Unitroller.sol";
import "./periphery/BathBuddy.sol";
// G D Em A G/F C Cm Cm6 Am B G7 <- fortissimo
contract BathHouseV2 {
/// @notice unitroller's address
Comptroller public comptroller;
address public admin;
// guy who manages BathTokens
address public proxyAdmin;
bool private initialized;
mapping(address => address) private tokenToBathToken;
mapping(address => address) private bathTokenToBuddy;
event BathTokenCreated(address bathToken, address underlying);
event BuddySpawned(address bathToken, address bathBuddy);
modifier onlyAdmin() {
require(msg.sender == admin, "onlyAdmin: !admin");
_;
}
// proxy-constructor
function initialize(address _comptroller, address _pAdmin) external {
require(!initialized, "BathHouseV2 already initialized!");
comptroller = Comptroller(_comptroller);
admin = msg.sender;
proxyAdmin = _pAdmin;
initialized = true;
}
//============================= VIEW =============================
/// @notice returns the address of any bathToken in the
/// system based on its corresponding underlying asset
function getBathTokenFromAsset(
address asset
) public view returns (address) {
return tokenToBathToken[asset];
}
function whoIsBuddy(
address bathToken
) external view returns (address buddy) {
buddy = bathTokenToBuddy[bathToken];
}
//============================= BATH TOKENS =============================
/// @notice create new CErc20 based bathToken
function createBathToken(
address underlying,
InterestRateModel interestRateModel,
uint256 initialExchangeRateMantissa,
address implementation,
bytes memory becomeImplementationData
) external onlyAdmin {
// underlying can be used only for one bathToken
require(
tokenToBathToken[underlying] == address(0),
"createBathToken: BATHTOKEN WITH THIS ERC20 EXIST ALDREADY"
);
require(
underlying != address(0),
"createBathToken: UNDERLYING == ADDRESS 0"
);
require(
implementation != address(0),
"createBathToken: IMPLEMENTATION == ADDRESS 0"
);
// get bathToken metadata that semantically reflects underlying ERC20
(string memory name, string memory symbol, uint8 decimals) = _bathify(
underlying
);
// BathTokenDelegator
address bathToken = address(
new CErc20Delegator(
underlying,
comptroller,
interestRateModel,
initialExchangeRateMantissa,
name,
symbol,
decimals,
payable(proxyAdmin),
implementation,
becomeImplementationData
)
);
// spawn buddy
BathBuddy buddy = new BathBuddy();
buddy.spawnBuddy(admin, bathToken, address(this));
tokenToBathToken[underlying] = bathToken;
bathTokenToBuddy[bathToken] = address(buddy);
emit BathTokenCreated(bathToken, underlying);
emit BuddySpawned(bathToken, address(buddy));
}
/// @notice claim available rewards
/// across all the pools
function claimRewards(
address[] memory buddies,
address[] memory rewardsTokens
) external {
// claim rewards from comptroller
comptroller.claimComp(msg.sender);
// get rewards from bathBuddy
for (uint256 i = 0; i < buddies.length; ++i) {
IBathBuddy(buddies[i]).getReward(
IERC20(rewardsTokens[i]),
msg.sender
);
}
}
/// @notice claim rewards from only one BathBuddy
function getReward(address buddy, address rewardsToken) external {
IBathBuddy(buddy).getReward(IERC20(rewardsToken), msg.sender);
}
//============================= INTERNALS =============================
// 🛀
function _bathify(
address _underlying
)
internal
view
returns (string memory _name, string memory _symbol, uint8 _decimals)
{
require(_underlying != address(0), "_bathify: ADDRESS ZERO");
_name = string.concat("bath", ERC20(_underlying).symbol());
_symbol = string.concat(_name, "v2");
_decimals = ERC20(_underlying).decimals();
}
}