@@ -9,16 +9,16 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
99
1010import "./GPv2AllowanceManager.sol " ;
1111import "./interfaces/GPv2Authentication.sol " ;
12- import "./libraries/GPv2Encoding.sol " ;
1312import "./libraries/GPv2Interaction.sol " ;
1413import "./libraries/GPv2Order.sol " ;
14+ import "./libraries/GPv2Trade.sol " ;
1515import "./libraries/GPv2TradeExecution.sol " ;
1616
1717/// @title Gnosis Protocol v2 Settlement Contract
1818/// @author Gnosis Developers
1919contract GPv2Settlement is ReentrancyGuard , StorageAccessible {
20- using GPv2Encoding for bytes ;
2120 using GPv2Order for bytes ;
21+ using GPv2Signing for GPv2Signing.RecoveredOrder;
2222 using GPv2TradeExecution for GPv2TradeExecution.Data;
2323 using SafeMath for uint256 ;
2424
@@ -142,7 +142,7 @@ contract GPv2Settlement is ReentrancyGuard, StorageAccessible {
142142 /// Orders and interactions encode tokens as indices into this array.
143143 /// @param clearingPrices An array of clearing prices where the `i`-th price
144144 /// is for the `i`-th token in the [`tokens`] array.
145- /// @param encodedTrades Encoded trades for signed orders.
145+ /// @param trades Trades for signed orders.
146146 /// @param interactions Smart contract interactions split into three
147147 /// separate lists to be run before the settlement, during the settlement
148148 /// and after the settlement respectively.
@@ -151,14 +151,14 @@ contract GPv2Settlement is ReentrancyGuard, StorageAccessible {
151151 function settle (
152152 IERC20 [] calldata tokens ,
153153 uint256 [] calldata clearingPrices ,
154- bytes calldata encodedTrades ,
154+ GPv2Trade.Data[] calldata trades ,
155155 GPv2Interaction.Data[][3 ] calldata interactions ,
156156 bytes [] calldata orderRefunds
157157 ) external nonReentrant onlySolver {
158158 executeInteractions (interactions[0 ]);
159159
160160 GPv2TradeExecution.Data[] memory executedTrades =
161- computeTradeExecutions (tokens, clearingPrices, encodedTrades );
161+ computeTradeExecutions (tokens, clearingPrices, trades );
162162 allowanceManager.transferIn (executedTrades);
163163
164164 executeInteractions (interactions[1 ]);
@@ -191,58 +191,63 @@ contract GPv2Settlement is ReentrancyGuard, StorageAccessible {
191191 /// [`computeTradeExecution`] for more details.
192192 /// @param tokens An array of ERC20 tokens to be traded in the settlement.
193193 /// @param clearingPrices An array of token clearing prices.
194- /// @param encodedTrades Encoded trades for signed orders.
194+ /// @param trades Trades for signed orders.
195195 /// @return executedTrades Array of executed trades.
196196 function computeTradeExecutions (
197197 IERC20 [] calldata tokens ,
198198 uint256 [] calldata clearingPrices ,
199- bytes calldata encodedTrades
199+ GPv2Trade.Data[] calldata trades
200200 ) internal returns (GPv2TradeExecution.Data[] memory executedTrades ) {
201- ( uint256 tradeCount , bytes calldata remainingEncodedTrades ) =
202- encodedTrades. decodeTradeCount ();
203- executedTrades = new GPv2TradeExecution. Data [](tradeCount);
204-
205- GPv2Encoding.Trade memory trade;
206- uint256 i = 0 ;
207- while (remainingEncodedTrades. length != 0 ) {
208- remainingEncodedTrades = remainingEncodedTrades. decodeTrade (
201+ GPv2Signing.RecoveredOrder memory recoveredOrder =
202+ GPv2Signing. allocateRecoveredOrder ();
203+
204+ executedTrades = new GPv2TradeExecution. Data [](trades. length );
205+ for ( uint256 i = 0 ; i < trades. length ; i ++ ) {
206+ GPv2Trade.Data calldata trade = trades[i] ;
207+
208+ recoveredOrder. recoverOrderFromTrade (
209209 domainSeparator,
210210 tokens,
211211 trade
212212 );
213213 computeTradeExecution (
214- trade ,
214+ recoveredOrder ,
215215 clearingPrices[trade.sellTokenIndex],
216216 clearingPrices[trade.buyTokenIndex],
217+ trade.executedAmount,
218+ trade.feeDiscount,
217219 executedTrades[i]
218220 );
219- i++ ;
220221 }
221-
222- require (i == tradeCount, "GPv2: invalid trade encoding " );
223222 }
224223
225224 /// @dev Compute the in and out transfer amounts for a single trade.
226225 /// This function reverts if:
227226 /// - The order has expired
228227 /// - The order's limit price is not respected.
229228 ///
230- /// @param trade The trade to process.
229+ /// @param recoveredOrder The recovered order to process.
231230 /// @param sellPrice The price of the order's sell token.
232231 /// @param buyPrice The price of the order's buy token.
232+ /// @param executedAmount The portion of the order to execute. This will be
233+ /// ignored for fill-or-kill orders.
234+ /// @param feeDiscount The discount to apply to the final executed fees.
233235 /// @param executedTrade Memory location for computed executed trade data.
234236 function computeTradeExecution (
235- GPv2Encoding.Trade memory trade ,
237+ GPv2Signing.RecoveredOrder memory recoveredOrder ,
236238 uint256 sellPrice ,
237239 uint256 buyPrice ,
240+ uint256 executedAmount ,
241+ uint256 feeDiscount ,
238242 GPv2TradeExecution.Data memory executedTrade
239243 ) internal {
240- GPv2Order.Data memory order = trade.order;
244+ GPv2Order.Data memory order = recoveredOrder.data;
245+ bytes memory orderUid = recoveredOrder.uid;
241246
242247 // solhint-disable-next-line not-rely-on-time
243248 require (order.validTo >= block .timestamp , "GPv2: order expired " );
244249
245- executedTrade.owner = trade .owner;
250+ executedTrade.owner = recoveredOrder .owner;
246251 executedTrade.receiver = order.receiver;
247252 executedTrade.sellToken = order.sellToken;
248253 executedTrade.buyToken = order.buyToken;
@@ -282,7 +287,7 @@ contract GPv2Settlement is ReentrancyGuard, StorageAccessible {
282287
283288 if (order.kind == GPv2Order.SELL) {
284289 if (order.partiallyFillable) {
285- executedSellAmount = trade. executedAmount;
290+ executedSellAmount = executedAmount;
286291 executedFeeAmount =
287292 order.feeAmount.mul (executedSellAmount) /
288293 order.sellAmount;
@@ -293,7 +298,7 @@ contract GPv2Settlement is ReentrancyGuard, StorageAccessible {
293298
294299 executedBuyAmount = executedSellAmount.mul (sellPrice) / buyPrice;
295300
296- currentFilledAmount = filledAmount[trade. orderUid].add (
301+ currentFilledAmount = filledAmount[orderUid].add (
297302 executedSellAmount
298303 );
299304 require (
@@ -302,7 +307,7 @@ contract GPv2Settlement is ReentrancyGuard, StorageAccessible {
302307 );
303308 } else {
304309 if (order.partiallyFillable) {
305- executedBuyAmount = trade. executedAmount;
310+ executedBuyAmount = executedAmount;
306311 executedFeeAmount =
307312 order.feeAmount.mul (executedBuyAmount) /
308313 order.buyAmount;
@@ -313,33 +318,31 @@ contract GPv2Settlement is ReentrancyGuard, StorageAccessible {
313318
314319 executedSellAmount = executedBuyAmount.mul (buyPrice) / sellPrice;
315320
316- currentFilledAmount = filledAmount[trade.orderUid].add (
317- executedBuyAmount
318- );
321+ currentFilledAmount = filledAmount[orderUid].add (executedBuyAmount);
319322 require (
320323 currentFilledAmount <= order.buyAmount,
321324 "GPv2: order filled "
322325 );
323326 }
324327
325328 require (
326- trade. feeDiscount <= executedFeeAmount,
329+ feeDiscount <= executedFeeAmount,
327330 "GPv2: fee discount too large "
328331 );
329- executedFeeAmount = executedFeeAmount - trade. feeDiscount;
332+ executedFeeAmount = executedFeeAmount - feeDiscount;
330333
331334 executedTrade.sellAmount = executedSellAmount.add (executedFeeAmount);
332335 executedTrade.buyAmount = executedBuyAmount;
333336
334- filledAmount[trade. orderUid] = currentFilledAmount;
337+ filledAmount[orderUid] = currentFilledAmount;
335338 emit Trade (
336339 executedTrade.owner,
337340 executedTrade.sellToken,
338341 executedTrade.buyToken,
339342 executedTrade.sellAmount,
340343 executedTrade.buyAmount,
341344 executedFeeAmount,
342- trade. orderUid
345+ orderUid
343346 );
344347 }
345348
0 commit comments