-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor(contracts-rfq): docs cleanup [SLT-493] #3405
Conversation
WalkthroughThe changes in this pull request involve extensive documentation updates and code refinements across multiple contracts, including Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (13)
packages/contracts-rfq/contracts/interfaces/IZapRecipient.sol (2)
4-8
: LGTM! Consider adding implementation guidance.The interface documentation is clear and well-structured. It effectively explains the purpose and context of Zap operations in relation to FastBridge transactions.
Consider adding a
@dev
section to provide implementation guidance, such as:/// @notice Interface for contracts that can perform Zap operations. Such contracts could be used as Recipients /// in a FastBridge transaction that includes a Zap operation. The Zap Data should include instructions on how /// exactly the Zap operation should be executed, which would typically include the target address and calldata /// to use. The exact implementation of the Zap Data encoding is up to the Recipient contract. +/// @dev Implementers should ensure proper validation of zapData and handle failed operations gracefully. +/// The implementation should also include appropriate access controls and safety checks.
9-14
: LGTM! Consider documenting error conditions.The function documentation is comprehensive with clear parameter descriptions and return value specification.
Consider enhancing the documentation with:
- Expected revert conditions
- Specific details about the expected bytes4 return value
/// @notice Performs a Zap operation with the given token and amount according to the provided Zap data. /// @param token The address of the token being used for the Zap operation. /// @param amount The amount of tokens to be used. /// @param zapData The encoded data specifying how the Zap operation should be executed. - /// @return The function selector to indicate successful execution. + /// @return The function selector (0x12345678) to indicate successful execution. + /// @dev Should revert if: + /// - zapData is malformed or invalid + /// - token transfer fails + /// - underlying zap operation failspackages/contracts-rfq/contracts/interfaces/IAdminV2.sol (3)
9-10
: Enhance documentation with implementation detailsThe documentation should include:
- The time unit of the cancel delay (blocks or seconds)
- Valid range for
newCancelDelay
parameter- Behavior during the delay period
/// @notice Allows the governor to set the cancel delay. The cancel delay is the time period after the transaction /// deadline during which a transaction can be permissionlessly cancelled if it hasn't been proven by any Relayer. +/// @param newCancelDelay The new cancel delay duration in seconds +/// @dev The delay must be greater than 0 and less than MAX_CANCEL_DELAY
13-16
: Add technical details about fee rate implementationThe documentation should specify:
- The fee rate format (e.g., basis points, percentage)
- Valid range for
newFeeRate
- How the fee is calculated
/// @notice Allows the governor to set the protocol fee rate. The protocol fee is taken from the origin /// amount and is only applied to completed and claimed transactions. /// @dev The protocol fee is abstracted away from the relayers; they always operate using the amounts after fees. /// The origin amount they see in the emitted log is what they get credited with. +/// @param newFeeRate The new fee rate in basis points (1 = 0.01%) +/// @dev The fee rate must be less than MAX_FEE_RATE basis points
19-19
: Expand documentation for security-critical functionThis function handles protocol fees and should have comprehensive documentation including:
- Supported token types
- Requirements for the recipient address
- Security considerations
/// @notice Allows the governor to withdraw the accumulated protocol fees from the contract. +/// @param token The address of the token to sweep (must be a valid ERC20 token) +/// @param recipient The address to receive the fees (must not be zero address) +/// @dev This function should be called carefully as it transfers all accumulated fees +/// @return The amount of fees sweptpackages/contracts-rfq/contracts/interfaces/IMulticallTarget.sol (2)
12-19
: Consider adding a usage example in the documentation.While the documentation is clear, adding a simple example of how to construct the
data
array would make it more developer-friendly.Example addition:
/// @param data List of ABI-encoded calldata for the calls to execute /// @param ignoreReverts Whether to skip calls that revert +/// @dev Example: +/// ``` +/// bytes[] memory data = new bytes[](2); +/// data[0] = abi.encodeCall(IMulticallTarget.someFunction, (param1, param2)); +/// data[1] = abi.encodeCall(IMulticallTarget.anotherFunction, (param3)); +/// ```
Line range hint
21-35
: Consider documenting reentrancy and gas considerations.While the implementation is solid, it would be helpful to document:
- Potential reentrancy implications when batching multiple calls
- Gas considerations when collecting return data from multiple calls
Add the following documentation:
/// @dev This method is non-payable, so only calls with msg.value of 0 can be batched. /// If ignoreReverts is set to true, reverted calls will be skipped. /// Otherwise, the entire batch will revert with the original revert reason. +/// @dev Security considerations: +/// - Be aware of potential reentrancy when batching multiple state-modifying calls +/// - Gas usage increases with the size of return data from each callpackages/contracts-rfq/contracts/utils/MulticallTarget.sol (2)
Line range hint
12-24
: Consider enhancing security documentationWhile the implementation is secure and well-commented, consider adding explicit documentation about:
- The reentrancy implications of delegatecall
- The importance of careful implementation in inheriting contracts
Add the following to the function documentation:
/// @inheritdoc IMulticallTarget + /// @dev Security considerations: + /// - Inheriting contracts must ensure their functions are protected against reentrancy + /// - All state-changing operations should follow checks-effects-interactions pattern
Line range hint
26-42
: Consider gas optimization for array operationsThe current implementation pre-allocates the full results array. For large batches, this could be gas-intensive. Consider adding a maximum batch size limit to prevent excessive gas consumption.
function multicallWithResults( bytes[] calldata data, bool ignoreReverts ) external returns (Result[] memory results) { + require(data.length <= MAX_BATCH_SIZE, "Batch size exceeds limit"); results = new Result[](data.length);
packages/contracts-rfq/contracts/AdminV2.sol (1)
42-42
: Consider clarifying the fee rate decimal representation.The comment could be more explicit about how the decimal places work with the constant value
0.01e6
.Suggested documentation:
- /// @notice The maximum protocol fee rate: 1% of the origin amount. + /// @notice The maximum protocol fee rate: 1% of the origin amount (represented as 10000 in 6 decimal places).packages/contracts-rfq/contracts/FastBridgeV2.sol (3)
47-49
: Use@deprecated
tag to indicate variable deprecationConsider adding the
@deprecated
annotation to formally mark thenonce
variable as deprecated, aiding developers in understanding its status.
75-79
: Use@deprecated
tag to indicate function deprecationConsider adding the
@deprecated
annotation to therefund
function's documentation to formally indicate its deprecated status.
103-116
: Use descriptive variable names instead of$
Using
$
as a variable name may reduce code readability. Consider renaming it to a more descriptive name likebridgeDetails
for better clarity.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (8)
packages/contracts-rfq/contracts/AdminV2.sol
(1 hunks)packages/contracts-rfq/contracts/FastBridgeV2.sol
(15 hunks)packages/contracts-rfq/contracts/interfaces/IAdminV2.sol
(1 hunks)packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol
(2 hunks)packages/contracts-rfq/contracts/interfaces/IMulticallTarget.sol
(1 hunks)packages/contracts-rfq/contracts/interfaces/IZapRecipient.sol
(1 hunks)packages/contracts-rfq/contracts/libs/BridgeTransactionV2.sol
(1 hunks)packages/contracts-rfq/contracts/utils/MulticallTarget.sol
(2 hunks)
✅ Files skipped from review due to trivial changes (2)
- packages/contracts-rfq/contracts/interfaces/IFastBridgeV2.sol
- packages/contracts-rfq/contracts/libs/BridgeTransactionV2.sol
🧰 Additional context used
📓 Learnings (1)
packages/contracts-rfq/contracts/FastBridgeV2.sol (1)
Learnt from: ChiTimesChi
PR: synapsecns/sanguine#3284
File: packages/contracts-rfq/contracts/FastBridgeV2.sol:100-118
Timestamp: 2024-11-12T03:37:08.148Z
Learning: When reviewing code in `packages/contracts-rfq/contracts/FastBridgeV2.sol` (Solidity), focus on changes introduced in the PR and avoid commenting on existing functions like `refund` if they are not modified by the PR, as such comments are considered out of scope.
🔇 Additional comments (13)
packages/contracts-rfq/contracts/interfaces/IMulticallTarget.sol (1)
4-11
: LGTM! Clear documentation and well-structured definition.
The interface documentation properly credits the inspiration source and the Result struct is well-defined for its purpose.
packages/contracts-rfq/contracts/utils/MulticallTarget.sol (2)
7-8
: Documentation improvements enhance clarity
The updated documentation better reflects the contract's nature as an abstract template and provides more precise conditions for batched calls.
Line range hint 12-42
: Verify delegatecall implementation safety
The contract uses delegatecall for preserving msg.sender. While the implementation looks secure, we should verify that all inheriting contracts properly handle this pattern.
✅ Verification successful
Let me gather more information about the state variables and functions in these contracts to ensure delegatecall safety.
Let me analyze the implementation further by checking for any potential state modifications in the delegatecall path.
Let me gather more information about the delegatecall usage and state variables in the MulticallTarget contract.
Based on the analysis of the code and verification results, I can now provide a final response about the delegatecall implementation safety.
Delegatecall implementation is secure
The implementation is safe because:
- MulticallTarget is an abstract contract with no state variables that could be corrupted
- The delegatecall is only to
address(this)
, ensuring the code context remains within the same contract - The contract only exposes one external function
multicallNoResults
that can be delegatecalled - All inheriting contracts (FastBridge, FastBridgeV2) properly maintain their own state variables without conflicts
- The implementation follows the checks-effects-interactions pattern with proper validation of msg.sender
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for contracts inheriting MulticallTarget
ast-grep --pattern 'contract $_ is $$$MulticallTarget$$$'
# Search for potential dangerous state modifications in inheriting contracts
rg -p "contract.*is.*MulticallTarget" -A 10
Length of output: 4098
Script:
#!/bin/bash
# Check for state variables in all related contracts
ast-grep --pattern 'contract $_ is $$$MulticallTarget$$$ {
$$$
$_ public $_
$$$
}'
# Check for storage write operations in functions
rg "storage|mapping.*=>" -p
# Check for functions that could modify state
ast-grep --pattern 'function $name($$$) $$${
$$$
}'
Length of output: 140336
Script:
#!/bin/bash
# Check for state variables in MulticallTarget and inheriting contracts
ast-grep --pattern 'contract $_ {
$$$
$_ public $_
$$$
}'
# Check for functions that could modify state in MulticallTarget
ast-grep --pattern 'function $name($$$) $$${
$$$
$_ = $_
$$$
}'
# Check for potential dangerous delegatecall usage patterns
rg -p "delegatecall.*\(" -A 3
Length of output: 125581
Script:
#!/bin/bash
# Check for state variables in MulticallTarget
ast-grep --pattern 'contract MulticallTarget {
$$$
$_ $_ $_
$$$
}'
# Check for functions that could modify state in MulticallTarget
ast-grep --pattern 'function $name($$$) $$${
$$$
$_ = $_
$$$
}' packages/contracts-rfq/contracts/utils/MulticallTarget.sol
# Check for functions that could be called via delegatecall
rg -p "function.*external" packages/contracts-rfq/contracts/utils/MulticallTarget.sol
Length of output: 383
packages/contracts-rfq/contracts/AdminV2.sol (3)
11-13
: LGTM! Clear and comprehensive contract documentation.
The documentation effectively communicates the contract's purpose and main functionalities.
63-66
: LGTM! Parameter name change improves clarity.
The rename from _owner
to defaultAdmin
better reflects the parameter's purpose and aligns with AccessControl terminology.
Line range hint 97-105
: LGTM! Well-documented private function with clear security boundaries.
The documentation clearly explains the function's purpose and security considerations.
packages/contracts-rfq/contracts/FastBridgeV2.sol (7)
17-24
: Improved contract documentation enhances clarity
The updated comments provide a clearer understanding of the contract's purpose and functionality, benefiting developers and users alike.
29-35
: Well-defined constants with clear documentation
The added constants and their associated comments improve code readability and maintainability by clearly specifying their purposes and values.
38-44
: Enhanced mapping documentation improves comprehension
The detailed descriptions for bridgeTxDetails
, bridgeRelayDetails
, and senderNonces
mappings offer better insights into their roles within the contract.
50-52
: Introduction of deployBlock
enhances deployment tracking
Adding the deployBlock
variable with appropriate documentation helps in tracking the contract's deployment block, which can be useful for auditing and debugging.
53-55
: Constructor documentation clarifies initialization
The added comments in the constructor provide valuable information about the initialization process, improving code readability.
364-370
: Use descriptive variable names instead of $
As previously mentioned, consider renaming the variable $
to something more descriptive, such as bridgeDetails
, to improve code readability.
437-440
: Use descriptive variable names instead of $
As noted earlier, using $
as a variable name can impact readability. Renaming it to a meaningful name like balanceBefore
or initialBalance
could enhance understanding.
/// @inheritdoc IAdminV2 | ||
function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) { | ||
// Early exit if no accumulated fees. | ||
uint256 feeAmount = protocolFees[token]; | ||
if (feeAmount == 0) return; // skip if no accumulated fees | ||
|
||
if (feeAmount == 0) return; | ||
// Reset the accumulated fees first. | ||
protocolFees[token] = 0; | ||
emit FeesSwept(token, recipient, feeAmount); | ||
/// Sweep the fees as the last transaction action | ||
// Sweep the fees as the last transaction action. | ||
if (token == NATIVE_GAS_TOKEN) { | ||
Address.sendValue(payable(recipient), feeAmount); | ||
} else { | ||
IERC20(token).safeTransfer(recipient, feeAmount); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix potential reentrancy vulnerability in sweepProtocolFees.
The function updates state after making external calls, which could be exploited in a reentrancy attack.
Suggested fix:
function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) {
uint256 feeAmount = protocolFees[token];
if (feeAmount == 0) return;
- // Reset the accumulated fees first.
- protocolFees[token] = 0;
- emit FeesSwept(token, recipient, feeAmount);
- // Sweep the fees as the last transaction action.
+ // Reset the accumulated fees before external calls (Checks-Effects-Interactions pattern)
+ protocolFees[token] = 0;
+ emit FeesSwept(token, recipient, feeAmount);
+
if (token == NATIVE_GAS_TOKEN) {
Address.sendValue(payable(recipient), feeAmount);
} else {
IERC20(token).safeTransfer(recipient, feeAmount);
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
/// @inheritdoc IAdminV2 | |
function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) { | |
// Early exit if no accumulated fees. | |
uint256 feeAmount = protocolFees[token]; | |
if (feeAmount == 0) return; // skip if no accumulated fees | |
if (feeAmount == 0) return; | |
// Reset the accumulated fees first. | |
protocolFees[token] = 0; | |
emit FeesSwept(token, recipient, feeAmount); | |
/// Sweep the fees as the last transaction action | |
// Sweep the fees as the last transaction action. | |
if (token == NATIVE_GAS_TOKEN) { | |
Address.sendValue(payable(recipient), feeAmount); | |
} else { | |
IERC20(token).safeTransfer(recipient, feeAmount); | |
} | |
/// @inheritdoc IAdminV2 | |
function sweepProtocolFees(address token, address recipient) external onlyRole(GOVERNOR_ROLE) { | |
// Early exit if no accumulated fees. | |
uint256 feeAmount = protocolFees[token]; | |
if (feeAmount == 0) return; | |
// Reset the accumulated fees before external calls (Checks-Effects-Interactions pattern) | |
protocolFees[token] = 0; | |
emit FeesSwept(token, recipient, feeAmount); | |
if (token == NATIVE_GAS_TOKEN) { | |
Address.sendValue(payable(recipient), feeAmount); | |
} else { | |
IERC20(token).safeTransfer(recipient, feeAmount); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not, reread the code again please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ChiTimesChi You are correct; upon re-reading the code, I see that the state is updated before the external calls, following the Checks-Effects-Interactions pattern. Thank you for pointing that out.
✏️ Learnings added
Learnt from: ChiTimesChi
PR: synapsecns/sanguine#3405
File: packages/contracts-rfq/contracts/AdminV2.sol:81-94
Timestamp: 2024-11-22T12:02:52.806Z
Learning: Ensure that when reviewing functions like `sweepProtocolFees` in `AdminV2.sol`, verify that state updates occur before external calls to accurately assess reentrancy vulnerabilities.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
Changes to gas cost
🧾 Summary (50% most significant diffs)
Full diff report 👇
|
Deploying sanguine-fe with
|
Latest commit: |
aad9617
|
Status: | ✅ Deploy successful! |
Preview URL: | https://3544a3c7.sanguine-fe.pages.dev |
Branch Preview URL: | https://refactor-fbv2-cleanup.sanguine-fe.pages.dev |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #3405 +/- ##
===================================================
+ Coverage 3.10368% 42.36502% +39.26134%
===================================================
Files 44 87 +43
Lines 2932 3019 +87
Branches 0 82 +82
===================================================
+ Hits 91 1279 +1188
+ Misses 2838 1737 -1101
Partials 3 3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
packages/contracts-rfq/contracts/FastBridgeV2.sol (3)
Line range hint
425-445
: Optimize token balance checks for gas efficiency.The function correctly handles fee-on-transfer tokens and includes proper validations. However, the balance difference calculation could be optimized:
Consider this optimization:
- amountTaken = IERC20(token).balanceOf(address(this)); - IERC20(token).safeTransferFrom(msg.sender, address(this), amount); - amountTaken = IERC20(token).balanceOf(address(this)) - amountTaken; + uint256 balanceBefore = IERC20(token).balanceOf(address(this)); + IERC20(token).safeTransferFrom(msg.sender, address(this), amount); + amountTaken = IERC20(token).balanceOf(address(this)) - balanceBefore;
448-467
: Enhance documentation for zap validation checks.The function implements proper validation checks, but the documentation could be more explicit about:
- Expected return value format
- Potential revert scenarios
- Gas implications of the external call
Consider adding these details to the function's documentation:
/// @notice Calls the recipient's hook function with the specified zapData and validates /// the returned value. +/// @dev The function expects the recipient to return exactly the selector of IZapRecipient.zap +/// @dev May revert if: +/// - Recipient contract doesn't exist +/// - Recipient reverts +/// - Return value is missing or incorrect +/// - Insufficient gas for the external call
Line range hint
481-510
: Consider breaking down validation logic for better maintainability.While the validation is thorough, the function's complexity could be reduced by breaking it into smaller, focused functions.
Consider splitting the validations:
+ function _validateBasicParams(BridgeParams memory params) internal view { + if (params.dstChainId == block.chainid) revert ChainIncorrect(); + if (params.originAmount == 0 || params.destAmount == 0) revert AmountIncorrect(); + if (params.sender == address(0) || params.to == address(0)) revert ZeroAddress(); + if (params.originToken == address(0) || params.destToken == address(0)) revert ZeroAddress(); + if (params.deadline < block.timestamp + MIN_DEADLINE_PERIOD) revert DeadlineTooShort(); + } + + function _validateZapParams(BridgeParamsV2 memory paramsV2, address destToken) internal pure { + if (paramsV2.zapData.length > MAX_ZAP_DATA_LENGTH) revert ZapDataLengthAboveMax(); + if (paramsV2.zapNative != 0 && destToken == NATIVE_GAS_TOKEN) { + revert ZapNativeNotSupported(); + } + }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
packages/contracts-rfq/contracts/FastBridgeV2.sol
(15 hunks)
🧰 Additional context used
📓 Learnings (1)
packages/contracts-rfq/contracts/FastBridgeV2.sol (1)
Learnt from: ChiTimesChi
PR: synapsecns/sanguine#3284
File: packages/contracts-rfq/contracts/FastBridgeV2.sol:100-118
Timestamp: 2024-11-12T03:37:08.148Z
Learning: When reviewing code in `packages/contracts-rfq/contracts/FastBridgeV2.sol` (Solidity), focus on changes introduced in the PR and avoid commenting on existing functions like `refund` if they are not modified by the PR, as such comments are considered out of scope.
🔇 Additional comments (3)
packages/contracts-rfq/contracts/FastBridgeV2.sol (3)
17-24
: Well-structured documentation improvements!
The contract documentation clearly explains the role and functionality of FastBridgeV2 within the SynapseRFQ protocol, including its support for different token types and the Zap feature.
238-271
: Review timestamp dependency in cancel function.
While the function implementation is solid, it relies heavily on block.timestamp
for deadline validation. Miners can manipulate timestamps within certain bounds, which could affect the cancellation timing.
Consider implementing additional safety measures:
- Use block numbers instead of timestamps where possible
- Add a grace period to account for timestamp variations
29-32
: Consider extending timing constants for better security.
The 30-minute constants for both DISPUTE_PERIOD
and MIN_DEADLINE_PERIOD
might be too short:
- Dispute period: Cross-chain transaction verification might take longer during network congestion
- Minimum deadline: Network delays could exceed 30 minutes during high congestion periods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Description
A clear and concise description of the features you're adding in this pull request.
Additional context
Add any other context about the problem you're solving.
Metadata
Summary by CodeRabbit
New Features
refund
function in the FastBridge contract, allowing users to reclaim funds under specific conditions.multicall
functions added for executing multiple calls in a single transaction.IZapRecipient
interface for performing Zap operations.Improvements
BridgeStatus
enum comments for better understanding.Bug Fixes
claim
function of the FastBridge contract.