-
Notifications
You must be signed in to change notification settings - Fork 47
/
LoanToken.sol
145 lines (132 loc) · 4.84 KB
/
LoanToken.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
/**
* Copyright 2017-2020, bZeroX, LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0.
*/
pragma solidity 0.5.17;
import "./AdvancedTokenStorage.sol";
/**
* @title Loan Token contract.
* @notice This contract code comes from bZx. bZx is a protocol for tokenized
* margin trading and lending https://bzx.network similar to the dYdX protocol.
*
* A loan token (iToken) is created as a proxy to an upgradable token contract.
*
* Examples of loan tokens on Sovryn are iRBTC, iDOC, iUSDT, iBPro,
* iSOV (near future).
*
* Lenders receive iTokens that collect interest from the lending pool
* which they can redeem by withdrawing them. The i in iToken stands for interest.
*
* Do not confuse iTokens with underlying tokens. iDOC is an iToken (loan token)
* whilest DOC is the underlying token (currency).
*
* @dev TODO: can I change this proxy to EIP-1822 proxy standard, please.
* https://eips.ethereum.org/EIPS/eip-1822. It's really hard to work with this.
* */
contract LoanToken is AdvancedTokenStorage {
/// @dev It is important to maintain the variables order so the delegate
/// calls can access sovrynContractAddress and wrbtcTokenAddress
address public sovrynContractAddress;
address public wrbtcTokenAddress;
address internal target_;
address public admin;
/**
* @notice Deploy loan token proxy.
* Sets ERC20 parameters of the token.
*
* @param _newOwner The address of the new owner.
* @param _newTarget The address of the new target contract instance.
* @param _sovrynContractAddress The address of the new sovrynContract instance.
* @param _wrbtcTokenAddress The address of the new wrBTC instance.
* */
constructor(
address _newOwner,
address _newTarget,
address _sovrynContractAddress,
address _wrbtcTokenAddress
) public {
transferOwnership(_newOwner);
_setTarget(_newTarget);
_setSovrynContractAddress(_sovrynContractAddress);
_setWrbtcTokenAddress(_wrbtcTokenAddress);
}
/**
* @notice Fallback function performs a delegate call
* to the actual implementation address is pointing this proxy.
* Returns whatever the implementation call returns.
* */
function() external payable {
if (gasleft() <= 2300) {
return;
}
address target = target_;
bytes memory data = msg.data;
assembly {
let result := delegatecall(gas, target, add(data, 0x20), mload(data), 0, 0)
let size := returndatasize
let ptr := mload(0x40)
returndatacopy(ptr, 0, size)
switch result
case 0 {
revert(ptr, size)
}
default {
return(ptr, size)
}
}
}
/**
* @notice Public owner setter for target address.
* @dev Calls internal setter.
* @param _newTarget The address of the new target contract instance.
* */
function setTarget(address _newTarget) public onlyOwner {
_setTarget(_newTarget);
}
/**
* @notice Internal setter for target address.
* @param _newTarget The address of the new target contract instance.
* */
function _setTarget(address _newTarget) internal {
require(Address.isContract(_newTarget), "target not a contract");
target_ = _newTarget;
}
/**
* @notice Internal setter for sovrynContract address.
* @param _sovrynContractAddress The address of the new sovrynContract instance.
* */
function _setSovrynContractAddress(address _sovrynContractAddress) internal {
require(Address.isContract(_sovrynContractAddress), "sovryn not a contract");
sovrynContractAddress = _sovrynContractAddress;
}
/**
* @notice Internal setter for wrBTC address.
* @param _wrbtcTokenAddress The address of the new wrBTC instance.
* */
function _setWrbtcTokenAddress(address _wrbtcTokenAddress) internal {
require(Address.isContract(_wrbtcTokenAddress), "wrbtc not a contract");
wrbtcTokenAddress = _wrbtcTokenAddress;
}
/**
* @notice Public owner cloner for pointed loan token.
* Sets ERC20 parameters of the token.
*
* @dev TODO: add check for double init.
* idk but init usually can be called only once.
*
* @param _loanTokenAddress The address of the pointed loan token instance.
* @param _name The ERC20 token name.
* @param _symbol The ERC20 token symbol.
* */
function initialize(
address _loanTokenAddress,
string memory _name,
string memory _symbol
) public onlyOwner {
loanTokenAddress = _loanTokenAddress;
name = _name;
symbol = _symbol;
decimals = IERC20(loanTokenAddress).decimals();
initialPrice = 10 ** 18; /// starting price of 1
}
}