@@ -87,43 +87,72 @@ contract OnChainAllocator is IOnChainAllocator {
8787 bytes32 typehash ,
8888 bytes32 witness
8989 ) public payable returns (bytes32 claimHash , uint256 [] memory registeredAmounts , uint256 nonce ) {
90- nonce = _getAndUpdateNonce (msg .sender , recipient);
91-
90+ // Check for empty commitments
9291 if (commitments.length == 0 ) {
9392 revert InvalidCommitments ();
9493 }
9594
95+ nonce = _getAndUpdateNonce (msg .sender , recipient);
96+
97+ // Transformed locks will be stored in idsAndAmounts
9698 uint256 [2 ][] memory idsAndAmounts = new uint256 [2 ][](commitments.length );
9799
100+ // Init minResetPeriod to the max value
98101 uint256 minResetPeriod = type (uint256 ).max;
99- uint256 i = 0 ;
102+
103+ // Process native token (zero address) first
104+ uint256 i;
100105 if (commitments[i].token == address (0 )) {
106+ // The Compact will revert if invalid value is provided for native token
107+ // Possible cases:
108+ // 1. The callvalue is zero but the first token is native
109+ // 2. the callvalue is nonzero but the first token is non-native
110+ // 3. the first token is native and the callvalue doesn't equal the first amount
111+
112+ // Handle first and third points
113+ if (commitments[i].amount == 0 || commitments[i].amount != msg .value ) {
114+ revert InvalidAmount (commitments[i].amount);
115+ }
116+
101117 minResetPeriod = _checkInput (commitments[i], recipient, expires, minResetPeriod);
118+
102119 idsAndAmounts[i][0 ] = AL.toId (commitments[i].lockTag, commitments[i].token);
120+ idsAndAmounts[i][1 ] = msg .value ;
103121
104- if (commitments[i].amount != 0 && commitments[i].amount != msg .value ) {
105- revert InvalidAmount (commitments[i].amount);
122+ unchecked {
123+ ++ i;
124+ }
125+ } else {
126+ // Handle second point
127+ if (msg .value != 0 ) {
128+ revert InvalidAmount (msg .value );
106129 }
107- idsAndAmounts[i][1 ] = msg .value ;
108- i++ ;
109130 }
131+
132+ // Process the rest of the commitments
110133 for (; i < commitments.length ; i++ ) {
111134 minResetPeriod = _checkInput (commitments[i], recipient, expires, minResetPeriod);
112- idsAndAmounts[i][0 ] = AL.toId (commitments[i].lockTag, commitments[i].token);
135+
136+ address token = commitments[i].token;
137+ // Safe to cast - _checkInput validated that the value fits the uint224
113138 uint224 amount = uint224 (commitments[i].amount);
114139
115- // If the amount is 0, we use the balance of the contract to deposit.
140+ // If the amount is 0, we use the balance of the contract to deposit
116141 if (amount == 0 ) {
117- amount = uint224 (IERC20 (commitments[i]. token).balanceOf (address (this )));
142+ amount = uint224 (IERC20 (token).balanceOf (address (this )));
118143 }
144+
145+ // Store the lock in idsAndAmounts
146+ idsAndAmounts[i][0 ] = AL.toId (commitments[i].lockTag, token);
119147 idsAndAmounts[i][1 ] = amount;
120148
121149 // Approve the compact contract to spend the tokens.
122- if (IERC20 (commitments[i]. token).allowance (address (this ), COMPACT_CONTRACT) < amount) {
123- SafeTransferLib.safeApproveWithRetry (commitments[i]. token, COMPACT_CONTRACT, type (uint256 ).max);
150+ if (IERC20 (token).allowance (address (this ), COMPACT_CONTRACT) < amount) {
151+ SafeTransferLib.safeApproveWithRetry (token, COMPACT_CONTRACT, type (uint256 ).max);
124152 }
125153 }
126- // Ensure expiration is not bigger then the smallest reset period
154+
155+ // Ensure expiration is less then the smallest reset period
127156 if (expires >= block .timestamp + minResetPeriod) {
128157 revert InvalidExpiration (expires, block .timestamp + minResetPeriod);
129158 }
0 commit comments