Skip to content

Commit ae03579

Browse files
committed
fix: standardize function order in some contracts (C4 QA)
1 parent eeb4bd0 commit ae03579

File tree

4 files changed

+139
-139
lines changed

4 files changed

+139
-139
lines changed

contracts/gateway/GraphTokenGateway.sol

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,6 @@ abstract contract GraphTokenGateway is GraphUpgradeable, Pausable, Managed, ITok
3535
_setPauseGuardian(_newPauseGuardian);
3636
}
3737

38-
/**
39-
* @dev Override the default pausing from Managed to allow pausing this
40-
* particular contract instead of pausing from the Controller.
41-
*/
42-
function _notPaused() internal view override {
43-
require(!_paused, "Paused (contract)");
44-
}
45-
4638
/**
4739
* @notice Change the paused state of the contract
4840
* @param _newPaused New value for the pause state (true means the transfers will be paused)
@@ -62,6 +54,14 @@ abstract contract GraphTokenGateway is GraphUpgradeable, Pausable, Managed, ITok
6254
return _paused;
6355
}
6456

57+
/**
58+
* @dev Override the default pausing from Managed to allow pausing this
59+
* particular contract instead of pausing from the Controller.
60+
*/
61+
function _notPaused() internal view override {
62+
require(!_paused, "Paused (contract)");
63+
}
64+
6565
/**
6666
* @dev Runs state validation before unpausing, reverts if
6767
* something is not set properly

contracts/gateway/L1GraphTokenGateway.sol

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess
223223
bytes memory outboundCalldata;
224224
{
225225
bytes memory extraData;
226-
(from, maxSubmissionCost, extraData) = parseOutboundData(_data);
226+
(from, maxSubmissionCost, extraData) = _parseOutboundData(_data);
227227
require(
228228
extraData.length == 0 || callhookAllowlist[msg.sender] == true,
229229
"CALL_HOOK_DATA_NOT_ALLOWED"
@@ -285,37 +285,17 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess
285285
}
286286

287287
/**
288-
* @notice Decodes calldata required for migration of tokens
289-
* @dev Data must include maxSubmissionCost, extraData can be left empty. When the router
290-
* sends an outbound message, data also contains the from address.
291-
* @param _data encoded callhook data
292-
* @return Sender of the tx
293-
* @return Base ether value required to keep retryable ticket alive
294-
* @return Additional data sent to L2
288+
* @notice Calculate the L2 address of a bridged token
289+
* @dev In our case, this would only work for GRT.
290+
* @param _l1ERC20 address of L1 GRT contract
291+
* @return L2 address of the bridged GRT token
295292
*/
296-
function parseOutboundData(bytes calldata _data)
297-
private
298-
view
299-
returns (
300-
address,
301-
uint256,
302-
bytes memory
303-
)
304-
{
305-
address from;
306-
uint256 maxSubmissionCost;
307-
bytes memory extraData;
308-
if (msg.sender == l1Router) {
309-
// Data encoded by the Gateway Router includes the sender address
310-
(from, extraData) = abi.decode(_data, (address, bytes));
311-
} else {
312-
from = msg.sender;
313-
extraData = _data;
293+
function calculateL2TokenAddress(address _l1ERC20) external view override returns (address) {
294+
IGraphToken token = graphToken();
295+
if (_l1ERC20 != address(token)) {
296+
return address(0);
314297
}
315-
// User-encoded data contains the max retryable ticket submission cost
316-
// and additional L2 calldata
317-
(maxSubmissionCost, extraData) = abi.decode(extraData, (uint256, bytes));
318-
return (from, maxSubmissionCost, extraData);
298+
return l2GRT;
319299
}
320300

321301
/**
@@ -349,20 +329,6 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess
349329
);
350330
}
351331

352-
/**
353-
* @notice Calculate the L2 address of a bridged token
354-
* @dev In our case, this would only work for GRT.
355-
* @param _l1ERC20 address of L1 GRT contract
356-
* @return L2 address of the bridged GRT token
357-
*/
358-
function calculateL2TokenAddress(address _l1ERC20) external view override returns (address) {
359-
IGraphToken token = graphToken();
360-
if (_l1ERC20 != address(token)) {
361-
return address(0);
362-
}
363-
return l2GRT;
364-
}
365-
366332
/**
367333
* @dev Runs state validation before unpausing, reverts if
368334
* something is not set properly
@@ -373,4 +339,38 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess
373339
require(l2Counterpart != address(0), "L2_COUNTERPART_NOT_SET");
374340
require(escrow != address(0), "ESCROW_NOT_SET");
375341
}
342+
343+
/**
344+
* @notice Decodes calldata required for migration of tokens
345+
* @dev Data must include maxSubmissionCost, extraData can be left empty. When the router
346+
* sends an outbound message, data also contains the from address.
347+
* @param _data encoded callhook data
348+
* @return Sender of the tx
349+
* @return Base ether value required to keep retryable ticket alive
350+
* @return Additional data sent to L2
351+
*/
352+
function _parseOutboundData(bytes calldata _data)
353+
private
354+
view
355+
returns (
356+
address,
357+
uint256,
358+
bytes memory
359+
)
360+
{
361+
address from;
362+
uint256 maxSubmissionCost;
363+
bytes memory extraData;
364+
if (msg.sender == l1Router) {
365+
// Data encoded by the Gateway Router includes the sender address
366+
(from, extraData) = abi.decode(_data, (address, bytes));
367+
} else {
368+
from = msg.sender;
369+
extraData = _data;
370+
}
371+
// User-encoded data contains the max retryable ticket submission cost
372+
// and additional L2 calldata
373+
(maxSubmissionCost, extraData) = abi.decode(extraData, (uint256, bytes));
374+
return (from, maxSubmissionCost, extraData);
375+
}
376376
}

contracts/l2/gateway/L2GraphTokenGateway.sol

Lines changed: 71 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,65 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
122122
emit L1CounterpartAddressSet(_l1Counterpart);
123123
}
124124

125+
/**
126+
* @notice Burns L2 tokens and initiates a transfer to L1.
127+
* The tokens will be received on L1 only after the wait period (7 days) is over,
128+
* and will require an Outbox.executeTransaction to finalize.
129+
* @dev no additional callhook data is allowed
130+
* @param _l1Token L1 Address of GRT (needed for compatibility with Arbitrum Gateway Router)
131+
* @param _to Recipient address on L1
132+
* @param _amount Amount of tokens to burn
133+
* @param _data Contains sender and additional data to send to L1
134+
* @return ID of the withdraw tx
135+
*/
136+
function outboundTransfer(
137+
address _l1Token,
138+
address _to,
139+
uint256 _amount,
140+
bytes calldata _data
141+
) external returns (bytes memory) {
142+
return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data);
143+
}
144+
145+
/**
146+
* @notice Receives token amount from L1 and mints the equivalent tokens to the receiving address
147+
* @dev Only accepts transactions from the L1 GRT Gateway.
148+
* The function is payable for ITokenGateway compatibility, but msg.value must be zero.
149+
* Note that allowlisted senders (some protocol contracts) can include additional calldata
150+
* for a callhook to be executed on the L2 side when the tokens are received. In this case, the L2 transaction
151+
* can revert if the callhook reverts, potentially locking the tokens on the bridge if the callhook
152+
* never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that
153+
* the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks
154+
* with token transfers.
155+
* @param _l1Token L1 Address of GRT
156+
* @param _from Address of the sender on L1
157+
* @param _to Recipient address on L2
158+
* @param _amount Amount of tokens transferred
159+
* @param _data Extra callhook data, only used when the sender is allowlisted
160+
*/
161+
function finalizeInboundTransfer(
162+
address _l1Token,
163+
address _from,
164+
address _to,
165+
uint256 _amount,
166+
bytes calldata _data
167+
) external payable override nonReentrant notPaused onlyL1Counterpart {
168+
require(_l1Token == l1GRT, "TOKEN_NOT_GRT");
169+
require(msg.value == 0, "INVALID_NONZERO_VALUE");
170+
171+
L2GraphToken(calculateL2TokenAddress(l1GRT)).bridgeMint(_to, _amount);
172+
173+
if (_data.length > 0) {
174+
bytes memory callhookData;
175+
{
176+
(, callhookData) = abi.decode(_data, (bytes, bytes));
177+
}
178+
ICallhookReceiver(_to).onTokenTransfer(_from, _amount, callhookData);
179+
}
180+
181+
emit DepositFinalized(_l1Token, _from, _to, _amount);
182+
}
183+
125184
/**
126185
* @notice Burns L2 tokens and initiates a transfer to L1.
127186
* The tokens will be available on L1 only after the wait period (7 days) is over,
@@ -151,7 +210,7 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
151210

152211
OutboundCalldata memory outboundCalldata;
153212

154-
(outboundCalldata.from, outboundCalldata.extraData) = parseOutboundData(_data);
213+
(outboundCalldata.from, outboundCalldata.extraData) = _parseOutboundData(_data);
155214
require(outboundCalldata.extraData.length == 0, "CALL_HOOK_DATA_NOT_ALLOWED");
156215

157216
// from needs to approve this contract to burn the amount first
@@ -176,26 +235,6 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
176235
return abi.encode(id);
177236
}
178237

179-
/**
180-
* @notice Burns L2 tokens and initiates a transfer to L1.
181-
* The tokens will be received on L1 only after the wait period (7 days) is over,
182-
* and will require an Outbox.executeTransaction to finalize.
183-
* @dev no additional callhook data is allowed
184-
* @param _l1Token L1 Address of GRT (needed for compatibility with Arbitrum Gateway Router)
185-
* @param _to Recipient address on L1
186-
* @param _amount Amount of tokens to burn
187-
* @param _data Contains sender and additional data to send to L1
188-
* @return ID of the withdraw tx
189-
*/
190-
function outboundTransfer(
191-
address _l1Token,
192-
address _to,
193-
uint256 _amount,
194-
bytes calldata _data
195-
) external returns (bytes memory) {
196-
return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data);
197-
}
198-
199238
/**
200239
* @notice Calculate the L2 address of a bridged token
201240
* @dev In our case, this would only work for GRT.
@@ -209,45 +248,6 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
209248
return address(graphToken());
210249
}
211250

212-
/**
213-
* @notice Receives token amount from L1 and mints the equivalent tokens to the receiving address
214-
* @dev Only accepts transactions from the L1 GRT Gateway.
215-
* The function is payable for ITokenGateway compatibility, but msg.value must be zero.
216-
* Note that allowlisted senders (some protocol contracts) can include additional calldata
217-
* for a callhook to be executed on the L2 side when the tokens are received. In this case, the L2 transaction
218-
* can revert if the callhook reverts, potentially locking the tokens on the bridge if the callhook
219-
* never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that
220-
* the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks
221-
* with token transfers.
222-
* @param _l1Token L1 Address of GRT
223-
* @param _from Address of the sender on L1
224-
* @param _to Recipient address on L2
225-
* @param _amount Amount of tokens transferred
226-
* @param _data Extra callhook data, only used when the sender is allowlisted
227-
*/
228-
function finalizeInboundTransfer(
229-
address _l1Token,
230-
address _from,
231-
address _to,
232-
uint256 _amount,
233-
bytes calldata _data
234-
) external payable override nonReentrant notPaused onlyL1Counterpart {
235-
require(_l1Token == l1GRT, "TOKEN_NOT_GRT");
236-
require(msg.value == 0, "INVALID_NONZERO_VALUE");
237-
238-
L2GraphToken(calculateL2TokenAddress(l1GRT)).bridgeMint(_to, _amount);
239-
240-
if (_data.length > 0) {
241-
bytes memory callhookData;
242-
{
243-
(, callhookData) = abi.decode(_data, (bytes, bytes));
244-
}
245-
ICallhookReceiver(_to).onTokenTransfer(_from, _amount, callhookData);
246-
}
247-
248-
emit DepositFinalized(_l1Token, _from, _to, _amount);
249-
}
250-
251251
/**
252252
* @notice Creates calldata required to send tx to L1
253253
* @dev encodes the target function with its params which
@@ -277,14 +277,24 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
277277
);
278278
}
279279

280+
/**
281+
* @dev Runs state validation before unpausing, reverts if
282+
* something is not set properly
283+
*/
284+
function _checksBeforeUnpause() internal view override {
285+
require(l2Router != address(0), "ROUTER_NOT_SET");
286+
require(l1Counterpart != address(0), "L1_COUNTERPART_NOT_SET");
287+
require(l1GRT != address(0), "L1GRT_NOT_SET");
288+
}
289+
280290
/**
281291
* @notice Decodes calldata required for migration of tokens
282292
* @dev extraData can be left empty
283293
* @param _data Encoded callhook data
284294
* @return Sender of the tx
285295
* @return Any other data sent to L1
286296
*/
287-
function parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {
297+
function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {
288298
address from;
289299
bytes memory extraData;
290300
if (msg.sender == l2Router) {
@@ -295,14 +305,4 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran
295305
}
296306
return (from, extraData);
297307
}
298-
299-
/**
300-
* @dev Runs state validation before unpausing, reverts if
301-
* something is not set properly
302-
*/
303-
function _checksBeforeUnpause() internal view override {
304-
require(l2Router != address(0), "ROUTER_NOT_SET");
305-
require(l1Counterpart != address(0), "L1_COUNTERPART_NOT_SET");
306-
require(l1GRT != address(0), "L1GRT_NOT_SET");
307-
}
308308
}

contracts/upgrades/GraphProxy.sol

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy {
5959
_setPendingImplementation(_impl);
6060
}
6161

62+
/**
63+
* @notice Fallback function that delegates calls to implementation. Will run if call data
64+
* is empty.
65+
*/
66+
receive() external payable {
67+
_fallback();
68+
}
69+
70+
/**
71+
* @notice Fallback function that delegates calls to implementation. Will run if no other
72+
* function in the contract matches the call data.
73+
*/
74+
fallback() external payable {
75+
_fallback();
76+
}
77+
6278
/**
6379
* @notice Get the current admin
6480
*
@@ -193,20 +209,4 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy {
193209
}
194210
}
195211
}
196-
197-
/**
198-
* @notice Fallback function that delegates calls to implementation. Will run if no other
199-
* function in the contract matches the call data.
200-
*/
201-
fallback() external payable {
202-
_fallback();
203-
}
204-
205-
/**
206-
* @notice Fallback function that delegates calls to implementation. Will run if call data
207-
* is empty.
208-
*/
209-
receive() external payable {
210-
_fallback();
211-
}
212212
}

0 commit comments

Comments
 (0)