This Solidity code defines a WrappedTokenBridge
contract that facilitates the wrapping and transferring of tokens across chains using Chainlink's CCIP (Cross-Chain Interoperability Protocol). While it looks mostly well-structured, there are several areas to consider for potential vulnerabilities and improvements:
Reentrancy Vulnerability:
The contract performs token transfers (both in transferTokens
and _ccipReceive
) after changing state (i.e., updating balances). Although you’re using SafeERC20
, it’s still a good practice to follow the Checks-Effects-Interactions pattern to minimize reentrancy risks.
You should use a reentrancy guard (e.g., OpenZeppelin's ReentrancyGuard
) on functions that involve external calls.
Approval Race Condition:
In the setRouter
function, the contract sets approvals for the new router without first setting the old router's approval to zero. This could potentially lead to a situation where the old router can still transfer tokens until the approval is fully updated. Ensure that old approvals are cleared before setting new ones.
Fee Calculation:
The getFee
method calls getFee
on the router. Ensure that this method cannot be manipulated (e.g., through oracle manipulation) to return excessive fees that could result in a loss of funds.
The fee validation (InsufficientFee
and FeeExceedsLimit
) does not account for potential changes in fees after calling getFee
. This could lead to a situation where the actual fee is higher than the checked values if there is an external change.
Lack of Input Validation:
In the transferTokens
and onTokenTransfer
functions, the _receiver
address is not validated (other than checking for zero). It could be beneficial to add additional checks (e.g., ensuring it's a contract or a valid address based on your application logic).
Token and Wrapped Token Balance Management:
When transferring tokens and wrapping them, there are implicit assumptions about the balances of the contract and the expected behavior of the wrap
and unwrap
methods. If these methods fail (e.g., due to insufficient funds), it may lead to unexpected behavior. Consider adding checks to ensure the contract has enough balance before calling these functions.
Error Handling:
Ensure that any external calls, especially those to untrusted contracts (like the router
), handle failures appropriately. For example, consider implementing fallback mechanisms or handling cases where the transfer may fail without reverting.
Gas Limit Management:
The gas limit is set to zero in the message-building function. While it may not directly cause vulnerabilities, setting a non-zero value could help in ensuring that transactions do not run out of gas.
Owner Privileges:
The use of onlyOwner
can lead to a central point of failure. Consider implementing more nuanced access controls or governance mechanisms if this contract will be used in a decentralized context.
Testing and Auditing: Ensure the code is thoroughly tested, especially for edge cases. Consider an external audit by a reputable firm specializing in smart contract security.
Upgradeability: If this contract will be in use for an extended period, consider using a proxy pattern for upgradeability to allow for fixes or improvements over time without needing to migrate users.
Documentation: Ensure all functions are well-documented, especially regarding their expected inputs and outputs, to facilitate understanding and usage.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.