Skip to content

Commit 615f6ca

Browse files
mrice32tbwebb22
andauthored
feat: disallow deposits with output token set to 0x0 (#1031)
* feat: disallow deposits with output token set to 0x0 Signed-off-by: Matt Rice <matthewcrice32@gmail.com> * [N-11] Unused Errors Due To Deprecated Logic (#1047) After the removal of the _deposit function from the SpokePool contract, the InvalidRelayerFeePct and MaxTransferSizeExceeded errors are no longer in use. Consider removing the unused errors. * [L-13] Function Selectors On Deprecated Functions Are Not Locked (#1048) * [L-13] Function Selectors On Deprecated Functions Are Not Locked Pull request 1031 removes already announced deprecated functionalities, such as the depositDeprecated_5947912356 and depositFor functions, alongside their _deposit internal function. However, as these entry points are removed, future versions of the codebase might introduce new functions that could have the same function selector as the removed ones. In such case, a protocol that might have used the deprecated functionalities could now call to the new ones with unexpected outcomes. Similarly, if a fallback function is used in the future, depending on its implementation, it might take the calldata of protocols using the old deprecated functionalities with similar results. In order to prevent the reuse of the deprecated function selectors, consider keeping the public functions' declaration, without their original definition, and reverting the calls to them. * Add note about selector collision with original deposit function * update for no address(0) changes Signed-off-by: Taylor Webb <tbwebb22@gmail.com> --------- Signed-off-by: Matt Rice <matthewcrice32@gmail.com> Signed-off-by: Taylor Webb <tbwebb22@gmail.com> Co-authored-by: Taylor Webb <tbwebb22@gmail.com>
1 parent 1b2bfd6 commit 615f6ca

File tree

6 files changed

+78
-566
lines changed

6 files changed

+78
-566
lines changed

contracts/SpokePool.sol

Lines changed: 33 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -395,87 +395,46 @@ abstract contract SpokePool is
395395
}
396396

397397
/**************************************
398-
* LEGACY DEPOSITOR FUNCTIONS *
398+
* REMOVED DEPOSITOR FUNCTIONS *
399399
**************************************/
400400

401401
/**
402-
* @dev DEPRECATION NOTICE: this function is deprecated and will be removed in the future.
403-
* Please use deposit (under DEPOSITOR FUNCTIONS below) or depositV3 instead.
404-
* @notice Called by user to bridge funds from origin to destination chain. Depositor will effectively lock
405-
* tokens in this contract and receive a destination token on the destination chain. The origin => destination
406-
* token mapping is stored on the L1 HubPool.
407-
* @notice The caller must first approve this contract to spend amount of originToken.
408-
* @notice The originToken => destinationChainId must be enabled.
409-
* @notice This method is payable because the caller is able to deposit native token if the originToken is
410-
* wrappedNativeToken and this function will handle wrapping the native token to wrappedNativeToken.
411-
* @dev Produces a FundsDeposited event with an infinite expiry, meaning that this deposit can never expire.
412-
* Moreover, the event's outputToken is set to 0x0 meaning that this deposit can always be slow filled.
413-
* @param recipient Address to receive funds at on destination chain.
414-
* @param originToken Token to lock into this contract to initiate deposit.
415-
* @param amount Amount of tokens to deposit. Will be amount of tokens to receive less fees.
416-
* @param destinationChainId Denotes network where user will receive funds from SpokePool by a relayer.
417-
* @param relayerFeePct % of deposit amount taken out to incentivize a fast relayer.
418-
* @param quoteTimestamp Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid
419-
* to LP pool on HubPool.
420-
* @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.
421-
* Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.
402+
* @dev REMOVED: This function has been removed and is now disallowed to prevent selector reuse.
403+
* @notice This function was removed from the protocol. Calling it will revert.
404+
* Function selector is preserved to prevent accidental reuse in future versions.
405+
* @notice This function shares the same selector as the original "deposit" function that was removed.
406+
* The collision was intentionally created to allow reusing the "deposit" name for a different function signature.
422407
*/
423408
function depositDeprecated_5947912356(
424-
address recipient,
425-
address originToken,
426-
uint256 amount,
427-
uint256 destinationChainId,
428-
int64 relayerFeePct,
429-
uint32 quoteTimestamp,
430-
bytes memory message,
431-
uint256 // maxCount. Deprecated.
432-
) public payable nonReentrant unpausedDeposits {
433-
_deposit(
434-
msg.sender,
435-
recipient,
436-
originToken,
437-
amount,
438-
destinationChainId,
439-
relayerFeePct,
440-
quoteTimestamp,
441-
message
442-
);
409+
address,
410+
address,
411+
uint256,
412+
uint256,
413+
int64,
414+
uint32,
415+
bytes memory,
416+
uint256
417+
) public payable {
418+
revert RemovedFunction();
443419
}
444420

445421
/**
446-
* @dev DEPRECATION NOTICE: this function is deprecated and will be removed in the future.
447-
* Please use the other deposit or depositV3 instead.
448-
* @notice The only difference between depositFor and deposit is that the depositor address stored
449-
* in the relay hash can be overridden by the caller. This means that the passed in depositor
450-
* can speed up the deposit, which is useful if the deposit is taken from the end user to a middle layer
451-
* contract, like an aggregator or the SpokePoolVerifier, before calling deposit on this contract.
452-
* @notice The caller must first approve this contract to spend amount of originToken.
453-
* @notice The originToken => destinationChainId must be enabled.
454-
* @notice This method is payable because the caller is able to deposit native token if the originToken is
455-
* wrappedNativeToken and this function will handle wrapping the native token to wrappedNativeToken.
456-
* @param depositor Address who is credited for depositing funds on origin chain and can speed up the deposit.
457-
* @param recipient Address to receive funds at on destination chain.
458-
* @param originToken Token to lock into this contract to initiate deposit.
459-
* @param amount Amount of tokens to deposit. Will be amount of tokens to receive less fees.
460-
* @param destinationChainId Denotes network where user will receive funds from SpokePool by a relayer.
461-
* @param relayerFeePct % of deposit amount taken out to incentivize a fast relayer.
462-
* @param quoteTimestamp Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid
463-
* to LP pool on HubPool.
464-
* @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.
465-
* Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.
422+
* @dev REMOVED: This function has been removed and is now disallowed to prevent selector reuse.
423+
* @notice This function was removed from the protocol. Calling it will revert.
424+
* Function selector is preserved to prevent accidental reuse in future versions.
466425
*/
467426
function depositFor(
468-
address depositor,
469-
address recipient,
470-
address originToken,
471-
uint256 amount,
472-
uint256 destinationChainId,
473-
int64 relayerFeePct,
474-
uint32 quoteTimestamp,
475-
bytes memory message,
476-
uint256 // maxCount. Deprecated.
477-
) public payable nonReentrant unpausedDeposits {
478-
_deposit(depositor, recipient, originToken, amount, destinationChainId, relayerFeePct, quoteTimestamp, message);
427+
address,
428+
address,
429+
address,
430+
uint256,
431+
uint256,
432+
int64,
433+
uint32,
434+
bytes memory,
435+
uint256
436+
) public payable {
437+
revert RemovedFunction();
479438
}
480439

481440
/********************************************
@@ -1342,6 +1301,9 @@ abstract contract SpokePool is
13421301
// Verify depositor is a valid EVM address.
13431302
params.depositor.checkAddress();
13441303

1304+
// Verify output token is not zero address.
1305+
if (params.outputToken == bytes32(0)) revert InvalidOutputToken();
1306+
13451307
// Require that quoteTimestamp has a maximum age so that depositors pay an LP fee based on recent HubPool usage.
13461308
// It is assumed that cross-chain timestamps are normally loosely in-sync, but clock drift can occur. If the
13471309
// SpokePool time stalls or lags significantly, it is still possible to make deposits by setting quoteTimestamp
@@ -1417,71 +1379,6 @@ abstract contract SpokePool is
14171379
);
14181380
}
14191381

1420-
function _deposit(
1421-
address depositor,
1422-
address recipient,
1423-
address originToken,
1424-
uint256 amount,
1425-
uint256 destinationChainId,
1426-
int64 relayerFeePct,
1427-
uint32 quoteTimestamp,
1428-
bytes memory message
1429-
) internal {
1430-
// We limit the relay fees to prevent the user spending all their funds on fees.
1431-
if (SignedMath.abs(relayerFeePct) >= 0.5e18) revert InvalidRelayerFeePct();
1432-
if (amount > MAX_TRANSFER_SIZE) revert MaxTransferSizeExceeded();
1433-
1434-
// Require that quoteTimestamp has a maximum age so that depositors pay an LP fee based on recent HubPool usage.
1435-
// It is assumed that cross-chain timestamps are normally loosely in-sync, but clock drift can occur. If the
1436-
// SpokePool time stalls or lags significantly, it is still possible to make deposits by setting quoteTimestamp
1437-
// within the configured buffer. The owner should pause deposits if this is undesirable. This will underflow if
1438-
// quoteTimestamp is more than depositQuoteTimeBuffer; this is safe but will throw an unintuitive error.
1439-
1440-
// slither-disable-next-line timestamp
1441-
if (getCurrentTime() - quoteTimestamp > depositQuoteTimeBuffer) revert InvalidQuoteTimestamp();
1442-
1443-
// Increment count of deposits so that deposit ID for this spoke pool is unique.
1444-
uint32 newDepositId = numberOfDeposits++;
1445-
1446-
// If the address of the origin token is a wrappedNativeToken contract and there is a msg.value with the
1447-
// transaction then the user is sending ETH. In this case, the ETH should be deposited to wrappedNativeToken.
1448-
if (originToken == address(wrappedNativeToken) && msg.value > 0) {
1449-
if (msg.value != amount) revert MsgValueDoesNotMatchInputAmount();
1450-
wrappedNativeToken.deposit{ value: msg.value }();
1451-
// Else, it is a normal ERC20. In this case pull the token from the user's wallet as per normal.
1452-
// Note: this includes the case where the L2 user has WETH (already wrapped ETH) and wants to bridge them.
1453-
// In this case the msg.value will be set to 0, indicating a "normal" ERC20 bridging action.
1454-
} else {
1455-
IERC20Upgradeable(originToken).safeTransferFrom(msg.sender, address(this), amount);
1456-
}
1457-
1458-
emit FundsDeposited(
1459-
originToken.toBytes32(), // inputToken
1460-
bytes32(0), // outputToken. Setting this to 0x0 means that the outputToken should be assumed to be the
1461-
// canonical token for the destination chain matching the inputToken. Therefore, this deposit
1462-
// can always be slow filled.
1463-
// - setting token to 0x0 will signal to off-chain validator that the "equivalent"
1464-
// token as the inputToken for the destination chain should be replaced here.
1465-
amount, // inputAmount
1466-
_computeAmountPostFees(amount, relayerFeePct), // outputAmount
1467-
// - output amount will be the deposit amount less relayerFeePct, which should now be set
1468-
// equal to realizedLpFeePct + gasFeePct + capitalCostFeePct where (gasFeePct + capitalCostFeePct)
1469-
// is equal to the old usage of `relayerFeePct`.
1470-
destinationChainId,
1471-
newDepositId,
1472-
quoteTimestamp,
1473-
INFINITE_FILL_DEADLINE, // fillDeadline. Default to infinite expiry because
1474-
// expired deposits refunds could be a breaking change for existing users of this function.
1475-
0, // exclusivityDeadline. Setting this to 0 along with the exclusiveRelayer to 0x0 means that there
1476-
// is no exclusive deadline
1477-
depositor.toBytes32(),
1478-
recipient.toBytes32(),
1479-
bytes32(0), // exclusiveRelayer. Setting this to 0x0 will signal to off-chain validator that there
1480-
// is no exclusive relayer.
1481-
message
1482-
);
1483-
}
1484-
14851382
function _distributeRelayerRefunds(
14861383
uint256 _chainId,
14871384
uint256 amountToReturn,

contracts/interfaces/SpokePoolInterface.sol

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ interface SpokePoolInterface {
4646

4747
function emergencyDeleteRootBundle(uint256 rootBundleId) external;
4848

49+
// REMOVED FUNCTIONS: These functions have been removed and are now disallowed.
50+
// Function selectors are preserved to prevent accidental reuse in future versions.
51+
// All calls to these functions will revert.
52+
53+
/**
54+
* @dev REMOVED: This function has been removed and is now disallowed.
55+
* @notice Calling this function will revert. Use deposit() or depositV3() instead.
56+
* @notice This function shares the same selector as the original "deposit" function that was removed.
57+
* The collision was intentionally created to allow reusing the "deposit" name for a different function signature.
58+
*/
4959
function depositDeprecated_5947912356(
5060
address recipient,
5161
address originToken,
@@ -57,6 +67,10 @@ interface SpokePoolInterface {
5767
uint256 maxCount
5868
) external payable;
5969

70+
/**
71+
* @dev REMOVED: This function has been removed and is now disallowed.
72+
* @notice Calling this function will revert. Use deposit() or depositV3() instead.
73+
*/
6074
function depositFor(
6175
address depositor,
6276
address recipient,
@@ -79,8 +93,6 @@ interface SpokePoolInterface {
7993

8094
error NotEOA();
8195
error InvalidDepositorSignature();
82-
error InvalidRelayerFeePct();
83-
error MaxTransferSizeExceeded();
8496
error InvalidCrossDomainAdmin();
8597
error InvalidWithdrawalRecipient();
8698
error DepositsArePaused();

contracts/interfaces/V3SpokePoolInterface.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ interface V3SpokePoolInterface {
327327
error InvalidQuoteTimestamp();
328328
error InvalidFillDeadline();
329329
error InvalidExclusiveRelayer();
330+
error InvalidOutputToken();
331+
error RemovedFunction();
330332
error MsgValueDoesNotMatchInputAmount();
331333
error NotExclusiveRelayer();
332334
error NoSlowFillsInExclusivityWindow();

test/evm/foundry/local/SpokePoolDeprecatedMethods.t.sol

Lines changed: 0 additions & 141 deletions
This file was deleted.

0 commit comments

Comments
 (0)