-
Notifications
You must be signed in to change notification settings - Fork 125
/
Copy pathExchangeData.sol
269 lines (223 loc) · 8.93 KB
/
ExchangeData.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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// SPDX-License-Identifier: Apache-2.0
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
import "./IAgentRegistry.sol";
import "./IBlockVerifier.sol";
import "./IDepositContract.sol";
import "./ILoopringV3.sol";
/// @title ExchangeData
/// @dev All methods in this lib are internal, therefore, there is no need
/// to deploy this library independently.
/// @author Daniel Wang - <[email protected]>
/// @author Brecht Devos - <[email protected]>
library ExchangeData
{
// -- Enums --
enum TransactionType
{
NOOP,
DEPOSIT,
WITHDRAWAL,
TRANSFER,
SPOT_TRADE,
ACCOUNT_UPDATE,
AMM_UPDATE,
SIGNATURE_VERIFICATION,
NFT_MINT, // L2 NFT mint or L1-to-L2 NFT deposit
NFT_DATA
}
enum NftType
{
ERC1155,
ERC721
}
// -- Structs --
struct Token
{
address token;
}
struct ProtocolFeeData
{
uint32 syncedAt; // only valid before 2105 (85 years to go)
uint8 takerFeeBips;
uint8 makerFeeBips;
uint8 previousTakerFeeBips;
uint8 previousMakerFeeBips;
}
// General auxiliary data for each conditional transaction
struct AuxiliaryData
{
uint txIndex;
bool approved;
bytes data;
}
// This is the (virtual) block the owner needs to submit onchain to maintain the
// per-exchange (virtual) blockchain.
struct Block
{
uint8 blockType;
uint16 blockSize;
uint8 blockVersion;
bytes data;
uint256[8] proof;
// Whether we should store the @BlockInfo for this block on-chain.
bool storeBlockInfoOnchain;
// Block specific data that is only used to help process the block on-chain.
// It is not used as input for the circuits and it is not necessary for data-availability.
// This bytes array contains the abi encoded AuxiliaryData[] data.
bytes auxiliaryData;
// Arbitrary data, mainly for off-chain data-availability, i.e.,
// the multihash of the IPFS file that contains the block data.
bytes offchainData;
}
struct BlockInfo
{
// The time the block was submitted on-chain.
uint32 timestamp;
// The public data hash of the block (the 28 most significant bytes).
bytes28 blockDataHash;
}
// Represents an onchain deposit request.
struct Deposit
{
uint96 amount;
uint64 timestamp;
}
// A forced withdrawal request.
// If the actual owner of the account initiated the request (we don't know who the owner is
// at the time the request is being made) the full balance will be withdrawn.
struct ForcedWithdrawal
{
address owner;
uint64 timestamp;
}
struct Constants
{
uint SNARK_SCALAR_FIELD;
uint MAX_OPEN_FORCED_REQUESTS;
uint MAX_AGE_FORCED_REQUEST_UNTIL_WITHDRAW_MODE;
uint TIMESTAMP_HALF_WINDOW_SIZE_IN_SECONDS;
uint MAX_NUM_ACCOUNTS;
uint MAX_NUM_TOKENS;
uint MIN_AGE_PROTOCOL_FEES_UNTIL_UPDATED;
uint MIN_TIME_IN_SHUTDOWN;
uint TX_DATA_AVAILABILITY_SIZE;
uint MAX_AGE_DEPOSIT_UNTIL_WITHDRAWABLE_UPPERBOUND;
}
// This is the prime number that is used for the alt_bn128 elliptic curve, see EIP-196.
uint public constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
// 0.1% of pending deposited amount
uint public constant MIN_DEPOSIT_PERCENTAGE = 1;
uint public constant MAX_OPEN_FORCED_REQUESTS = 4096;
uint public constant MAX_AGE_FORCED_REQUEST_UNTIL_WITHDRAW_MODE = 15 days;
uint public constant TIMESTAMP_HALF_WINDOW_SIZE_IN_SECONDS = 7 days;
uint public constant MAX_NUM_ACCOUNTS = 2 ** 32;
uint public constant MAX_NUM_TOKENS = 2 ** 16;
uint public constant MIN_AGE_PROTOCOL_FEES_UNTIL_UPDATED = 7 days;
uint public constant MIN_TIME_IN_SHUTDOWN = 30 days;
// The amount of bytes each rollup transaction uses in the block data for data-availability.
// This is the maximum amount of bytes of all different transaction types.
uint32 public constant MAX_AGE_DEPOSIT_UNTIL_WITHDRAWABLE_UPPERBOUND = 15 days;
uint32 public constant ACCOUNTID_PROTOCOLFEE = 0;
uint public constant TX_DATA_AVAILABILITY_SIZE = 68;
uint public constant TX_DATA_AVAILABILITY_SIZE_PART_1 = 29;
uint public constant TX_DATA_AVAILABILITY_SIZE_PART_2 = 39;
uint public constant NFT_TOKEN_ID_START = 2 ** 15;
struct AccountLeaf
{
uint32 accountID;
address owner;
uint pubKeyX;
uint pubKeyY;
uint32 nonce;
uint feeBipsAMM;
}
struct BalanceLeaf
{
uint16 tokenID;
uint96 balance;
uint weightAMM;
uint storageRoot;
}
struct Nft
{
address minter; // Minter address for a L2 mint or
// the NFT's contract address in the case of a L1-to-L2 NFT deposit.
NftType nftType;
address token;
uint256 nftID;
uint8 creatorFeeBips;
}
struct MerkleProof
{
ExchangeData.AccountLeaf accountLeaf;
ExchangeData.BalanceLeaf balanceLeaf;
ExchangeData.Nft nft;
uint[48] accountMerkleProof;
uint[24] balanceMerkleProof;
}
struct BlockContext
{
bytes32 DOMAIN_SEPARATOR;
uint32 timestamp;
Block block;
uint txIndex;
}
// Represents the entire exchange state except the owner of the exchange.
struct State
{
uint32 maxAgeDepositUntilWithdrawable;
bytes32 DOMAIN_SEPARATOR;
ILoopringV3 loopring;
IBlockVerifier blockVerifier;
IAgentRegistry agentRegistry;
IDepositContract depositContract;
// The merkle root of the offchain data stored in a Merkle tree. The Merkle tree
// stores balances for users using an account model.
bytes32 merkleRoot;
// List of all blocks
mapping(uint => BlockInfo) blocks;
uint numBlocks;
// List of all tokens
Token[] tokens;
// A map from a token to its tokenID + 1
mapping (address => uint16) tokenToTokenId;
// A map from an accountID to a tokenID to if the balance is withdrawn
mapping (uint32 => mapping (uint16 => bool)) withdrawnInWithdrawMode;
// A map from an account to a token to the amount withdrawable for that account.
// This is only used when the automatic distribution of the withdrawal failed.
mapping (address => mapping (uint16 => uint)) amountWithdrawable;
// A map from an account to a token to the forced withdrawal (always full balance)
// The `uint16' represents ERC20 token ID (if < NFT_TOKEN_ID_START) or
// NFT balance slot (if >= NFT_TOKEN_ID_START)
mapping (uint32 => mapping (uint16 => ForcedWithdrawal)) pendingForcedWithdrawals;
// A map from an address to a token to a deposit
mapping (address => mapping (uint16 => Deposit)) pendingDeposits;
// A map from an account owner to an approved transaction hash to if the transaction is approved or not
mapping (address => mapping (bytes32 => bool)) approvedTx;
// A map from an account owner to a destination address to a tokenID to an amount to a storageID to a new recipient address
mapping (address => mapping (address => mapping (uint16 => mapping (uint => mapping (uint32 => address))))) withdrawalRecipient;
// Counter to keep track of how many of forced requests are open so we can limit the work that needs to be done by the owner
uint32 numPendingForcedTransactions;
// Cached data for the protocol fee
ProtocolFeeData protocolFeeData;
// Time when the exchange was shutdown
uint shutdownModeStartTime;
// Time when the exchange has entered withdrawal mode
uint withdrawalModeStartTime;
// Last time the protocol fee was withdrawn for a specific token
mapping (address => uint) protocolFeeLastWithdrawnTime;
// Duplicated loopring address
address loopringAddr;
// AMM fee bips
uint8 ammFeeBips;
// Enable/Disable `onchainTransferFrom`
bool allowOnchainTransferFrom;
// owner => NFT type => token address => nftID => Deposit
mapping (address => mapping (NftType => mapping (address => mapping(uint256 => Deposit)))) pendingNFTDeposits;
// owner => minter => NFT type => token address => nftID => amount withdrawable
// This is only used when the automatic distribution of the withdrawal failed.
mapping (address => mapping (address => mapping (NftType => mapping (address => mapping(uint256 => uint))))) amountWithdrawableNFT;
}
}