-
Notifications
You must be signed in to change notification settings - Fork 15
/
MarketFactory.sol
219 lines (184 loc) · 10 KB
/
MarketFactory.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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.24;
import "@equilibria/perennial-v2-verifier/contracts/interfaces/IVerifier.sol";
import "@equilibria/root/attribute/Factory.sol";
import "./interfaces/IOracleProvider.sol";
import "./interfaces/IMarketFactory.sol";
/// @title MarketFactory
/// @notice Manages creating new markets and global protocol parameters.
contract MarketFactory is IMarketFactory, Factory {
/// @dev The oracle factory
IFactory public immutable oracleFactory;
/// @dev The verifier contract
IVerifier public immutable verifier;
/// @dev The global protocol parameters
ProtocolParameterStorage private _parameter;
/// @dev Mapping of allowed protocol-wide operators
mapping(address => bool) public extensions;
/// @dev Mapping of allowed operators per account
mapping(address => mapping(address => bool)) public operators;
/// @dev Registry of created markets by oracle and payoff
/// Note: address(0) is used in place of the deprecated payoff provider field
mapping(IOracleProvider => mapping(address => IMarket)) private _markets;
/// @dev The referreral fee level for each referrer for orders
mapping(address => UFixed6) private _referralFees;
/// @dev Mapping of allowed signers for each account
mapping(address => mapping(address => bool)) public signers;
/// @notice Constructs the contract
/// @param oracleFactory_ The oracle factory
/// @param verifier_ The verifier contract
/// @param implementation_ The initial market implementation contract
constructor(IFactory oracleFactory_, IVerifier verifier_, address implementation_) Factory(implementation_) {
oracleFactory = oracleFactory_;
verifier = verifier_;
}
/// @notice Initializes the contract state
function initialize() external initializer(1) {
__Factory__initialize();
}
/// @notice Returns the global protocol parameters
function parameter() public view returns (ProtocolParameter memory) {
return _parameter.read();
}
function markets(IOracleProvider oracle) external view returns (IMarket) {
return _markets[oracle][address(0)];
}
/// @notice Returns the referral fee for a referrer
/// @dev If the referrer has no fee set, the default protocol fee is returned
/// @param referrer The referrer to query
/// @return The referral fee for the referrer
function referralFees(address referrer) public view returns (UFixed6) {
if (referrer == address(0)) return UFixed6Lib.ZERO;
return _referralFees[referrer].isZero() ? parameter().referralFee : _referralFees[referrer];
}
/// @notice Returns authorizaton information for a market order
/// @param account The account the order is operating on
/// @param sender The sender of the order
/// @param signer The signer of the order
/// @param orderReferrer The referrer of the order
/// @return isOperator True if the sender is a valid operator for the account
/// @return isSigner True if the signer is a valid signer for the account
/// @return orderReferralFee The referral fee for the order
function authorization(
address account,
address sender,
address signer,
address orderReferrer
) external view returns (bool isOperator, bool isSigner, UFixed6 orderReferralFee) {
return (
account == sender || extensions[sender] || operators[account][sender],
account == signer || signers[account][signer],
referralFees(orderReferrer)
);
}
/// @notice Updates the global protocol parameters
/// @param newParameter The new protocol parameters
function updateParameter(ProtocolParameter memory newParameter) public onlyOwner {
_parameter.validateAndStore(newParameter);
emit ParameterUpdated(newParameter);
}
/// @notice Updates the status of an operator for the caller
/// @param extension The operator to update to enable protocol-wide
/// @param newEnabled The new status of the operator
function updateExtension(address extension, bool newEnabled) external {
extensions[extension] = newEnabled;
emit ExtensionUpdated(extension, newEnabled);
}
/// @notice Updates the status of an operator for the caller
/// @param operator The operator to update
/// @param newEnabled The new status of the operator
function updateOperator(address operator, bool newEnabled) external {
_updateOperator(msg.sender, operator, newEnabled);
}
/// @notice Updates the status of an operator for the signer verified via a signed message
/// @param operatorUpdate The operator update message to process
/// @param signature The signature of the operator update message
function updateOperatorWithSignature(OperatorUpdate calldata operatorUpdate, bytes calldata signature) external {
verifier.verifyOperatorUpdate(operatorUpdate, signature);
if (operatorUpdate.common.signer != operatorUpdate.common.account) revert MarketFactoryInvalidSignerError();
_updateOperator(operatorUpdate.common.account, operatorUpdate.access.accessor, operatorUpdate.access.approved);
}
/// @notice Updates the status of an operator for the account
/// @param account The account to update the operator for
/// @param operator The operator to update
/// @param newEnabled The new status of the operator
function _updateOperator(address account, address operator, bool newEnabled) private {
operators[account][operator] = newEnabled;
emit OperatorUpdated(account, operator, newEnabled);
}
/// @notice Updates the status of a signer for the caller
/// @param signer The signer to update
/// @param newEnabled The new status of the opersignerator
function updateSigner(address signer, bool newEnabled) external {
_updateSigner(msg.sender, signer, newEnabled);
}
/// @notice Updates the status of a signer for the caller verified via a signed message
/// @param signerUpdate The signer update message to process
/// @param signature The signature of the signer update message
function updateSignerWithSignature(SignerUpdate calldata signerUpdate, bytes calldata signature) external {
verifier.verifySignerUpdate(signerUpdate, signature);
if (signerUpdate.common.signer != signerUpdate.common.account) revert MarketFactoryInvalidSignerError();
_updateSigner(signerUpdate.common.account, signerUpdate.access.accessor, signerUpdate.access.approved);
}
/// @notice Updates the status of a signer for the caller
/// @param account The account to update the operator for
/// @param signer The signer to update
/// @param newEnabled The new status of the opersignerator
function _updateSigner(address account, address signer, bool newEnabled) private {
signers[account][signer] = newEnabled;
emit SignerUpdated(account, signer, newEnabled);
}
/// @notice Updates the status of the list of operators and signers for the caller
/// @param newOperators The list of operators to update
/// @param newSigners The list of signers to update
function updateAccessBatch(AccessUpdate[] calldata newOperators, AccessUpdate[] calldata newSigners) external {
_updateAccessBatch(msg.sender, newOperators, newSigners);
}
/// @notice Updates the status of the list of operators and signers for the caller verified via a signed message
/// @param accessUpdateBatch The batch access update message to process
/// @param signature The signature of the batch access update message
function updateAccessBatchWithSignature(
AccessUpdateBatch calldata accessUpdateBatch,
bytes calldata signature
) external {
verifier.verifyAccessUpdateBatch(accessUpdateBatch, signature);
if (accessUpdateBatch.common.signer != accessUpdateBatch.common.account) revert MarketFactoryInvalidSignerError();
_updateAccessBatch(accessUpdateBatch.common.account, accessUpdateBatch.operators, accessUpdateBatch.signers);
}
/// @notice Updates the status of the list of operators and signers for the caller
/// @param account The account to update the operators and signers for
/// @param newOperators The list of operators to update
/// @param newSigners The list of signers to update
function _updateAccessBatch(
address account,
AccessUpdate[] calldata newOperators,
AccessUpdate[] calldata newSigners
) private {
for (uint256 i = 0; i < newOperators.length; i++)
_updateOperator(account, newOperators[i].accessor, newOperators[i].approved);
for (uint256 i = 0; i < newSigners.length; i++)
_updateSigner(account, newSigners[i].accessor, newSigners[i].approved);
}
/// @notice Updates the referral fee for orders
/// @param referrer The referrer to update
/// @param newReferralFee The new referral fee
function updateReferralFee(address referrer, UFixed6 newReferralFee) external onlyOwner {
if (newReferralFee.gt(UFixed6Lib.ONE)) revert MarketFactoryInvalidReferralFeeError();
_referralFees[referrer] = newReferralFee;
emit ReferralFeeUpdated(referrer, newReferralFee);
}
/// @notice Creates a new market market with the given definition
/// @param definition The market definition
/// @return newMarket New market contract address
function create(IMarket.MarketDefinition calldata definition) external onlyOwner returns (IMarket newMarket) {
// verify oracle
if (!oracleFactory.instances(IInstance(address(definition.oracle)))) revert FactoryInvalidOracleError();
// verify invariants
if (_markets[definition.oracle][address(0)] != IMarket(address(0)))
revert FactoryAlreadyRegisteredError();
// create and register market
newMarket = IMarket(address(_create(abi.encodeCall(IMarket.initialize, (definition)))));
_markets[definition.oracle][address(0)] = newMarket;
emit MarketCreated(newMarket, definition);
}
}