stake.link

stake.link
DeFiHardhatBridge
27,500 USDC
View results
Submission Details
Severity: medium
Invalid

A user have to wait less time of locking if he bridges his lock between chains

Summary

If a user locks a certain amount of sdl tokens for an arbitrary amount of time, he can get benefited from bridging his token between chains and have to wait less time than expected.

Vulnerability Details

block.timestamp can differ between chains due to the differences of average block time. This difference of times can be benefited from users by bridging his locks between chains because when a lock is bridged, the timestamps when the lock was created are sent along.

https://github.com/Cyfrin/2023-12-stake-link/blob/main/contracts/core/ccip/RESDLTokenBridge.sol#L226-L228

RESDLTokenBridge

function _buildCCIPMessage(
address _receiver,
uint256 _tokenId,
ISDLPool.RESDLToken memory _reSDLToken,
address _destination,
address _feeTokenAddress,
bytes memory _extraArgs
) internal view returns (Client.EVM2AnyMessage memory) {
Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1);
Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({
token: address(sdlToken),
amount: _reSDLToken.amount
});
tokenAmounts[0] = tokenAmount;
Client.EVM2AnyMessage memory evm2AnyMessage = Client.EVM2AnyMessage({
receiver: abi.encode(_destination),
data: abi.encode(
_receiver,
_tokenId,
_reSDLToken.amount,
_reSDLToken.boostAmount,
_reSDLToken.startTime,
_reSDLToken.duration,
_reSDLToken.expiry
),
tokenAmounts: tokenAmounts,
extraArgs: _extraArgs,
feeToken: _feeTokenAddress
});
return evm2AnyMessage;
}

If we go to Arbitrum docs we can find:

Block timestamps: Arbitrum vs. Ethereum

Block timestamps on Arbitrum are not linked to the timestamp of the L1 block. They are updated every L2 block based on the sequencer's clock. These timestamps must follow these two rules:

  1. Must be always equal or greater than the previous L2 block timestamp

  2. Must fall within the established boundaries (24 hours earlier than the current time or 1 hour in the future).

The same way happens for Optimism.
If we run the following python script we can see the block.timestamp differences:

from web3 import Web3
arbitrum_https = "your arbitrum https"
ethereum_https = "your ethereum https"
optimism_https = "your optimism https"
def get_arbitrum_block_timestamp(httpsAddress):
try:
web3 = Web3(Web3.HTTPProvider(httpsAddress))
if web3.is_connected():
block_number = web3.eth.block_number
block = web3.eth.get_block(block_number)
current_timestamp = block['timestamp']
return current_timestamp
else:
return "Failed to connect to the node"
except Exception as e:
return f"An error occurred: {e}"
ethereumTimestamp = get_arbitrum_block_timestamp(ethereum_https)
arbitrumTimestamp = get_arbitrum_block_timestamp(arbitrum_https)
optimismTimestamp = get_arbitrum_block_timestamp(optimism_https)
print("Ethereum: ", ethereumTimestamp)
print("Arbitrum: ", arbitrumTimestamp)
print("Optimism: ", optimismTimestamp)

Output:

Ethereum: 1704492011
Arbitrum: 1704492038
Optimism: 1704492023

Impact

Medium

Tools Used

Manual review

Recommendations

Do not allow to bridge a lock that has initiated the unlock of funds

Updates

Lead Judging Commences

0kage Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.