forked from InverterNetwork/contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLM_ManualExternalPriceSetter_v1.sol
175 lines (150 loc) · 6.2 KB
/
LM_ManualExternalPriceSetter_v1.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity 0.8.23;
// Internal
import {ILM_ManualExternalPriceSetter_v1} from
"@lm/interfaces/ILM_ManualExternalPriceSetter_v1.sol";
import {Module_v1} from "src/modules/base/Module_v1.sol";
import {IOrchestrator_v1} from
"src/orchestrator/interfaces/IOrchestrator_v1.sol";
import {IOraclePrice_v1} from "@lm/interfaces/IOraclePrice_v1.sol";
// External
import {IERC20Metadata} from "@oz/token/ERC20/extensions/IERC20Metadata.sol";
import {ERC165Upgradeable} from
"@oz-up/utils/introspection/ERC165Upgradeable.sol";
/**
* @title Manual External Price Oracle Implementation
*
* @notice This contract provides a manual price feed mechanism for token
* operations, allowing authorized users to set and update prices
* for both issuance (buying) and redemption (selling) operations.
*
* @dev This contract inherits functionalities from:
* - Module_v1
* The contract maintains two separate price feeds:
* 1. Issuance price for token minting/buying.
* 2. Redemption price for token burning/selling.
* Both prices are manually set by the contract owner and must be
* non-zero values.
*
* Price Context:
* - Prices are stored internally with 18 decimals for consistent
* math.
* - When setting prices: Input values should be in collateral
* token decimals.
* - When getting prices: Output values will be in issuance
* token decimals.
*
* @custom:security-contact [email protected]
* In case of any concerns or findings, please refer
* to our Security Policy at security.inverter.network
* or email us directly!
*
* @custom:version v1.0.0
*
* @custom:standard-version v1.0.0
*
* @author Zealynx Security
*/
contract LM_ManualExternalPriceSetter_v1 is
ILM_ManualExternalPriceSetter_v1,
Module_v1
{
/// @inheritdoc ERC165Upgradeable
function supportsInterface(bytes4 interfaceId)
public
view
override
returns (bool)
{
return interfaceId == type(ILM_ManualExternalPriceSetter_v1).interfaceId
|| interfaceId == type(IOraclePrice_v1).interfaceId
|| super.supportsInterface(interfaceId);
}
// -------------------------------------------------------------------------
// Constants
/// @notice Role identifier for accounts authorized to set prices.
/// @dev This role should be granted to trusted price feeders only.
bytes32 public constant PRICE_SETTER_ROLE = "PRICE_SETTER_ROLE";
/// @notice Role identifier for the admin authorized to assign the price
/// setter role.
/// @dev This role should be set as the role admin within the Authorizer
/// module.
bytes32 public constant PRICE_SETTER_ROLE_ADMIN = "PRICE_SETTER_ROLE_ADMIN";
// -------------------------------------------------------------------------
// State Variables
/// @notice The price for issuing tokens (in collateral token decimals)
uint private _issuancePrice;
/// @notice The price for redeeming tokens (in collateral token decimals)
uint private _redemptionPrice;
/// @notice Decimals of the collateral token (e.g., USDC with 6 decimals).
/// @dev This is the token used to pay/buy with.
uint8 private _collateralTokenDecimals;
// -------------------------------------------------------------------------
// Initialization
/// @inheritdoc Module_v1
function init(
IOrchestrator_v1 orchestrator_,
Metadata memory metadata_,
bytes memory configData_
) external override(Module_v1) initializer {
__Module_init(orchestrator_, metadata_);
// Decode collateral token address from configData_.
(address collateralToken) = abi.decode(configData_, (address));
// Store token decimals for price normalization.
_collateralTokenDecimals = IERC20Metadata(collateralToken).decimals();
}
// -------------------------------------------------------------------------
// External Functions
/// @inheritdoc ILM_ManualExternalPriceSetter_v1
function setIssuancePrice(uint price_)
external
onlyModuleRole(PRICE_SETTER_ROLE)
{
_setIssuancePrice(price_);
}
/// @inheritdoc ILM_ManualExternalPriceSetter_v1
function setRedemptionPrice(uint price_)
external
onlyModuleRole(PRICE_SETTER_ROLE)
{
_setRedemptionPrice(price_);
}
/// @inheritdoc ILM_ManualExternalPriceSetter_v1
function setIssuanceAndRedemptionPrice(
uint issuancePrice_,
uint redemptionPrice_
) external onlyModuleRole(PRICE_SETTER_ROLE) {
_setIssuancePrice(issuancePrice_);
_setRedemptionPrice(redemptionPrice_);
}
/// @inheritdoc ILM_ManualExternalPriceSetter_v1
function getCollateralTokenDecimals() external view returns (uint8) {
return _collateralTokenDecimals;
}
/// @inheritdoc ILM_ManualExternalPriceSetter_v1
function getPriceForIssuance() external view returns (uint) {
return _issuancePrice;
}
/// @inheritdoc ILM_ManualExternalPriceSetter_v1
function getPriceForRedemption() external view returns (uint) {
return _redemptionPrice;
}
//--------------------------------------------------------------------------
// Internal Functions
/// @notice Internal function to set the issuance price
/// @param price_ The price to set
function _setIssuancePrice(uint price_) internal {
if (price_ == 0) revert Module__LM_ExternalPriceSetter__InvalidPrice();
_issuancePrice = price_;
emit IssuancePriceSet(price_, msg.sender);
}
/// @notice Internal function to set the redemption price
/// @param price_ The price to set
function _setRedemptionPrice(uint price_) internal {
if (price_ == 0) revert Module__LM_ExternalPriceSetter__InvalidPrice();
_redemptionPrice = price_;
emit RedemptionPriceSet(price_, msg.sender);
}
/// @dev Storage gap for upgradeable contracts.
uint[50] private __gap;
}