-
Notifications
You must be signed in to change notification settings - Fork 0
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
EVM Bridge contracts #1
base: main
Are you sure you want to change the base?
Conversation
5a1b0b8
to
7ee93d3
Compare
- Remove hardhat - Update docs - Add additional checks to validator - add .env.example
Added: - `event FeeReceiverChanged(address indexed changer, address indexed newFeeReceiver);` - `event NativeSendAmountChanged(address indexed changer, uint256 newNativeSendAmount);` - `event ValidatorChanged(address indexed changer, address indexed newValidator);` -`event TokenMapped(address indexed token, bytes32 indexed externalTokenAddress);` - `event TokenUnmapped(bytes32 indexed externalTokenAddress);` - `event PayloadSignerChanged(address changer, address payloadSigner);` - `event FeeValidityWindowChanged(address changer, uint256 validityWindow);` - `event ValidatorAdded(address validator);` - `event ValidatorRemoved(address validator);` Updated: - `event TokenRemoved(address indexed token, bytes32 indexed externalTokenAddress);` - `event TokenDeployed(bytes32 indexed externalTokenAddress, string name, string symbol, uint8 decimals, address token);` - Update gas snapshot - Update tests - Update docs
WalkthroughThe update overhauls the project’s core bridging functionality. It introduces new Foundry build and testing configurations, replaces Hardhat and TypeScript settings, and adds comprehensive documentation. Major changes include upgrading and extending Solidity contracts and interfaces, adding robust deployment scripts and signature generators, and dramatically expanding the test suite and mocks. New environment files, JSON payloads/receipts, and a submodule for forge-std are also included. Changes
Sequence Diagram(s)sequenceDiagram
participant U as Deployer Script
participant DB as DeployBridge (script)
participant DBase as DeployerBase
participant B as Bridge Contract
U->>DB: call run()
DB->>DBase: getDeployer()
DBase->>DB: return deployer info
DB->>DBase: checkDeployed("Bridge")
alt Bridge already deployed & !FORCE_DEPLOY
DBase->>DB: return existing Bridge address
DB->>U: Log existing deployment
else Bridge not deployed / FORCE_DEPLOY true
DB->>DBase: deployBridge()
DBase->>B: Deploy new Bridge contract
B-->>DBase: return new Bridge address
DBase->>DB: log deployment
end
DB->>U: Stop broadcast
sequenceDiagram
participant C as ClaimTokens (script)
participant FS as File System (JSON)
participant RU as ReceiptUtils
participant B as Bridge Contract
C->>FS: Read JSON file (receipt)
FS-->>C: JSON data
C->>RU: Parse/Convert JSON to FullReceipt
RU-->>C: Return FullReceipt struct
C->>B: Call claim(receipt, signature)
B-->>C: Process claim and update state
C->>C: Stop broadcast and log result
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
CodeRabbit Configuration File (
|
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: 28
🧹 Nitpick comments (75)
bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md (2)
19-123
: Consider enhancing function documentation.While the functions are well-structured, consider:
- Adding
@param
and@return
tags for better documentation- Including examples of usage
- Documenting potential revert conditions
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
50-50: Multiple headings with the same content
null(MD024, no-duplicate-heading)
59-59: Multiple headings with the same content
null(MD024, no-duplicate-heading)
78-78: Multiple headings with the same content
null(MD024, no-duplicate-heading)
88-88: Multiple headings with the same content
null(MD024, no-duplicate-heading)
107-107: Multiple headings with the same content
null(MD024, no-duplicate-heading)
116-116: Multiple headings with the same content
null(MD024, no-duplicate-heading)
125-132
: Consider enhancing error documentation.While the error is well-defined, consider:
- Adding
@param
descriptions forkey
andcurrentNonce
- Including examples of scenarios that trigger this error
bridge-evm/script/SetValidatorRelaySigner.s.sol (3)
3-3
: Remove redundant ABI coder pragma.The
pragma abicoder v2
directive is redundant as it's the default since Solidity 0.8.0.-pragma abicoder v2;
7-9
: Remove unused import.The
AccessManager
import is not used in this contract.-import {AccessManager} from - "@openzeppelin/contracts/access/manager/AccessManager.sol";
13-22
: Add access control and event logging.The
run
function lacks access control and event logging for tracking validator additions.Consider:
- Adding access control to restrict who can run this script
- Emitting events for validator additions for better transparency and tracking
- Adding a success log message using
console.log
function run() public override { + require(msg.sender == owner, "Unauthorized"); getDeployer(); vm.startBroadcast(deployer.privateKey); getValidator(); address[] memory signers = vm.envAddress("VALIDATORS", ","); for (uint256 i = 0; i < signers.length; i++) { validator.addValidator(signers[i]); + emit ValidatorAdded(signers[i]); + console.log("Added validator:", signers[i]); } vm.stopBroadcast(); }bridge-evm/test/mocks/MockBadNativeReceiver.sol (1)
6-8
: Add NatSpec documentation explaining the mock's purpose.While the implementation correctly simulates a contract that fails to receive Ether, adding documentation would help other developers understand its testing purpose.
contract MockBadNativeReceiver { + /// @notice A mock contract that always fails when receiving Ether + /// @dev Used for testing error handling when Ether transfers fail receive() external payable { require(false, "MockBadNativeReceiver: receive"); }Let's verify how this mock is used in tests:
❌ Verification inconclusive
🏁 Script executed:
#!/bin/bash # Search for test files using this mock rg -l "MockBadNativeReceiver" --type solLength of output: 68
I'll re-run the search using a broader pattern to verify how (or if) this mock is referenced in test files:
If this search still yields no references, it may be that the mock is only used implicitly in tests or imported via configuration. In any case, the implementation is functionally correct, but adding NatSpec documentation—as shown in the diff—is recommended to improve clarity on its testing purpose. Please manually verify the mock's usage in your tests to ensure that this extra documentation aligns with its intended role.
Action: Add NatSpec documentation to explain that this mock is used to simulate a contract that always rejects Ether reception.
🏁 Script executed:
#!/bin/bash rg -l "MockBadNativeReceiver" --include "*.sol" .Length of output: 491
Action: Add NatSpec documentation to clarify that this mock is used for testing error handling in Ether transfers, and please verify that tests indeed utilize this mock.
Our search using ripgrep with a stricter file filter (e.g., with the command below) did not return any references:
#!/bin/bash rg -l "MockBadNativeReceiver" -g "*.sol" .Because the current automated search produced no output, please manually confirm whether tests import or otherwise utilize this mock contract. If it is in active use as a testing tool, then the NatSpec addition (e.g.,
/// @notice A mock contract that always fails when receiving Ether
and/// @dev Used for testing error handling when Ether transfers fail
) will improve clarity for developers. Otherwise, consider if the mock is unnecessary.bridge-evm/contracts/Bridge.sol (1)
10-29
: Consider emitting an event during initialization
Currently, theinitialize
function does not emit any event. Emitting an event (e.g.,BridgeInitialized
) would help track initialization status on-chain, which can be particularly useful in upgradeable contracts.function initialize( address authority_, address SAMB_, IValidation validator_, address payable feeReceiver_, uint256 nativeSendAmount_ ) public initializer { + emit BridgeInitialized(authority_, SAMB_, address(validator_), feeReceiver_, nativeSendAmount_); __Bridge_init( authority_, SAMB_, validator_, feeReceiver_, nativeSendAmount_ ); } +event BridgeInitialized( + address authority_, + address samb_, + address validator_, + address feeReceiver_, + uint256 nativeSendAmount_ +);bridge-evm/contracts/utils/NoncesUpgradeable.sol (2)
42-48
: Overloaded function clarity
Overloadingnonces
foruint256
,address
, andbytes32
is handy but could confuse external consumers or tooling. Consider distinct function names or thoroughly documenting how each overload should be used.
100-105
: Enhanced debug context for nonce mismatch
_useCheckedNonce
reverts withInvalidAccountNonce
. You might consider also passing in thenonce
parameter that was attempted, to make debugging more straightforward.bridge-evm/contracts/interface/ITokenManager.sol (2)
3-3
: Consider removingpragma abicoder v2
.
For Solidity^0.8.x
,abicoder v2
is enabled by default, making this pragma redundant.-pragma abicoder v2;
85-190
: Check function consistency and naming collisions.
While the interface design is solid and covers bridging scenarios, consider the following improvements:
- Rename
bridgableTokens
toisBridgable
or similar for consistent naming with other “check” functions (e.g.,pausedTokens
).- Ensure the dual
addToken
overloads do not conflict in usage. If the first function requires apaused
parameter while the second omits it, confirm that calling code knows which to use.bridge-evm/script/DeployerBase.s.sol (2)
3-3
: Remove unnecessarypragma abicoder v2
.
Similar to the interface file, this pragma is redundant under Solidity^0.8.x
.-pragma abicoder v2;
44-77
: Confirmation prompt usage in a scripted environment.
Relying on user prompt responses (lines 56-63) during automated scripts can stall CI pipelines. Ensure an alternative or a bypass for non-interactive environments.bridge-evm/contracts/interface/IBridge.sol (3)
3-3
: Consider removingpragma abicoder v2
.
Same recommendation for Solidity^0.8.x
, whereabicoder v2
is enabled by default.-pragma abicoder v2;
101-126
: Duplicate documentation forclaim
withMiniReceipt
andFullReceipt
.
Consider referencing a single explanation for claiming tokens, or clarifying differences in logic ifMiniReceipt
usage differs fromFullReceipt
. This reduces confusion and ensures maintainers understand the distinction.
148-164
: Read-Only getters for bridging configuration.
It’s good practice to keep these asview
functions for clarity. Consider verifying usage in the implementing contract to ensure they remain pure getters without side effects.bridge-evm/contracts/upgradeable/ValidatorUpgradeable.sol (1)
27-51
: Unconventional variable name in_getValidatorStorage()
Using$
to reference the storage struct is slightly unconventional and may confuse new contributors. Consider renaming$
to a more descriptive label likestorageRef
to improve readability.- returns (ValidatorStorage storage $) + returns (ValidatorStorage storage storageRef)bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol (3)
40-60
: Initialization
The two-step initialization pattern (__TokenManager_init
,__TokenManager_init_unchained
) is consistent. Confirm that only the intended authority or admin can call these to avoid accidental re-initialization.
128-136
: Potential oversight inremoveToken
The comment at line 321 indicates a FIXME about removing a mapped external token. If removing a bridged token that has external mappings, consider unmapping it first or clarifying expected usage.Would you like a refactor to handle the associated external token unmapping in
_removeToken
?
200-211
: Pause logic
pausedTokens
is simply the negation ofunpausedTokens
. This is straightforward but might be confusing to new readers. Clarify thatfalse
in the mapping means “paused.”bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol (2)
323-352
: Consider adding a reentrancy guard.
The_validateSendValues()
method is part of a flow that ultimately uses_transferTokenToBridge()
. Although not necessarily vulnerable, external token transfers or calls can sometimes pose a reentrancy risk. A reentrancy guard (e.g.,ReentrancyGuard
from OpenZeppelin) or clear nonReentrant patterns might provide added safety.
497-515
: Validate potential reentrancy on claims.
_claim()
calls_transferClaim()
, which may involve external token transfers to user addresses. Consider guarding against malicious tokens, or incorporate a reentrancy guard to mitigate potential callback vulnerabilities.bridge-evm/test/bridge_tests/BridgeSend.t.sol (1)
181-226
: Consider refactoring duplicated “prepareSend” logic.
There are two overloads ofprepareSend()
plusprepareSendNative()
, all setting up chain state for sending tokens. It might be beneficial to unify shared logic in a common internal function to reduce code duplication and improve maintainability.bridge-evm/test/differential_testing/bytes2address.js (1)
1-22
: Add input validation to prevent errors.The functions should validate input length and format to prevent errors.
Apply this diff to add input validation:
function bytes2AddressLE(bytes) { + if (!bytes || typeof bytes !== 'string') { + throw new Error('Invalid input: bytes must be a non-empty string'); + } if (bytes.startsWith('0x')) { bytes = bytes.slice(2); } + if (bytes.length < 40) { + throw new Error('Invalid input: bytes string too short'); + } return `0x${bytes.slice(0, 40).toString('hex')}`; } function bytes2AddressBE(bytes) { + if (!bytes || typeof bytes !== 'string') { + throw new Error('Invalid input: bytes must be a non-empty string'); + } if (bytes.startsWith('0x')) { bytes = bytes.slice(2); } + if (bytes.length < 40) { + throw new Error('Invalid input: bytes string too short'); + } return `0x${bytes.slice(-40).toString('hex')}`; } function bytes2Address(bytes, isLE = false) { + if (!bytes || typeof bytes !== 'string') { + throw new Error('Invalid input: bytes must be a non-empty string'); + } if (bytes.startsWith('0x')) { bytes = bytes.slice(2); } + if (bytes.length < 40) { + throw new Error('Invalid input: bytes string too short'); + } return `0x${bytes.slice(isLE ? 0 : -40, isLE ? 40 : undefined).toString('hex')}`; }bridge-evm/contracts/interface/IWrapped.sol (1)
9-10
: Add natspec documentation for events.Events should be documented with natspec to improve code readability and maintainability.
Apply this diff to add natspec for events:
+ /// @notice Emitted when native currency is deposited and wrapped into ERC20 tokens + /// @param dst The address receiving the wrapped tokens + /// @param amount The amount of tokens being wrapped event Deposit(address indexed dst, uint256 amount); + /// @notice Emitted when ERC20 tokens are withdrawn and unwrapped into native currency + /// @param src The address unwrapping the tokens + /// @param amount The amount of tokens being unwrapped event Withdrawal(address indexed src, uint256 amount);bridge-evm/test/mocks/sAMB.sol (1)
16-20
: Add a zero amount check to prevent unnecessary gas consumption.Consider adding a check for zero amount to prevent unnecessary gas consumption from minting zero tokens and emitting events.
function deposit() public payable override { + require(msg.value > 0, "Cannot deposit zero amount"); _mint(msg.sender, msg.value); emit Deposit(msg.sender, msg.value); }
bridge-evm/script/DeployBridge.s.sol (1)
11-28
: Consider creating a base deployment contract.The deployment scripts share common patterns for validation, error handling, and deployment checks. Consider extracting these patterns into a base deployment contract to promote code reuse and maintainability.
This would help:
- Standardize error handling across deployments
- Ensure consistent validation of prerequisites
- Reduce code duplication
- Make it easier to add new deployment scripts
Would you like me to help create this base contract?
bridge-evm/contracts/Validator.sol (1)
8-12
: Enhance function documentation.Consider adding more details to the documentation:
- Explain what constitutes a valid
authority_
address.- Clarify the role and requirements for
validators_
array.- Document the purpose and impact of
feeValidityWindow_
.bridge-evm/test/Bridge.t.sol (1)
23-34
: Consider making the setup function more generic.The setup function currently only handles one specific test case. Consider:
- Adding a mapping of test selectors to setup functions.
- Supporting setup for other test cases.
- Adding documentation for the setup process.
+ /// Mapping of test selectors to setup functions + mapping(bytes4 => function() returns (bytes[] memory)) private setupFunctions; + + constructor() { + setupFunctions[this.test_revertWhen_send_BadFeeReceiver.selector] = _setupBadFeeReceiver; + // Add more setup functions here + } + + /// @notice Sets up bad fee receiver for testing + function _setupBadFeeReceiver() private pure returns (bytes[] memory) { + bytes[] memory calldata_ = new bytes[](1); + calldata_[0] = abi.encodeWithSelector( + this.setFeeReceiver.selector, + payable(address(badReceiver)) + ); + return calldata_; + } + function beforeTestSetup(bytes4 testSelector) public view returns (bytes[] memory beforeTestCalldata) { - if (testSelector == this.test_revertWhen_send_BadFeeReceiver.selector) { - beforeTestCalldata = new bytes[](1); - beforeTestCalldata[0] = abi.encodeWithSelector( - this.setFeeReceiver.selector, payable(address(badReceiver)) - ); + if (setupFunctions[testSelector] != function() returns (bytes[] memory)(0)) { + return setupFunctions[testSelector](); } + return new bytes[](0); }bridge-evm/test/SigUtils.sol (1)
4-51
: LGTM! Well-implemented EIP-712 signature utilities.The implementation correctly follows the EIP-712 standard for typed structured data hashing, with proper use of abi encoding methods and magic values.
Add natspec documentation for the Permit struct.
Consider adding natspec documentation to describe the purpose and fields of the Permit struct.
+ /// @notice A struct containing permit data for EIP-2612 token approvals + /// @param owner The owner of the tokens + /// @param spender The approved spender of the tokens + /// @param value The amount of tokens to approve + /// @param nonce The owner's nonce, increasing per permit + /// @param deadline The timestamp until which the permit is valid struct Permit { address owner; address spender; uint256 value; uint256 nonce; uint256 deadline; }bridge-evm/contracts/interface/IValidatorV1.sol (1)
5-50
: LGTM! Well-designed validator interface.The interface is well-structured with appropriate events, custom errors, and function declarations. Good use of natspec documentation and gas-efficient custom errors.
Consider removing version from interface name.
The interface name includes 'V1' which might complicate future upgrades. Consider using a version-less name and managing versions through inheritance or package versioning.
-interface IValidatorV1 { +interface IValidator {bridge-evm/contracts/utils/PayloadUtils.sol (1)
9-48
: LGTM! Well-implemented payload hashing utilities.The library correctly implements payload hashing using OpenZeppelin's MessageHashUtils, with proper encoding of all payload fields.
Complete the natspec documentation.
Add missing natspec tags and improve documentation clarity.
/// Shortcut to convert payload to hash /// @dev using [toEthSignedMessageHash](https://docs.openzeppelin.com/contracts/5.x/api/utils#MessageHashUtils-toEthSignedMessageHash-bytes32-) from OpenZeppelin's MessageHashUtils /// @param payload payload to convert /// @return hash converted + /// @notice A convenience function to hash a SendPayload using Ethereum signed message format function toHash(BridgeTypes.SendPayload memory payload) /// Convert payload to hash via toEthSignedMessageHash /// @dev using [toEthSignedMessageHash](https://docs.openzeppelin.com/contracts/5.x/api/utils#MessageHashUtils-toEthSignedMessageHash-bytes32-) from OpenZeppelin's MessageHashUtils /// @param payload payload to convert /// @return hash converted + /// @notice Hashes a SendPayload using Ethereum signed message format + /// @return hash The Ethereum signed message hash of the payload function toEthSignedMessageHash(BridgeTypes.SendPayload memory payload)bridge-evm/contracts/utils/AddressUtils.sol (1)
6-73
: LGTM! Well-implemented address conversion utilities.The library provides comprehensive address conversion utilities with support for different byte orders and clear documentation.
Add input validation for string conversion.
The string to address conversion relies on OpenZeppelin's parseAddress but could benefit from additional validation.
function toAddress(string memory _address) public pure returns (address converted) { + require(bytes(_address).length > 0, "AddressUtils: empty string"); + require(bytes(_address).length <= 42, "AddressUtils: string too long"); return _address.parseAddress(); }bridge-evm/test/PayloadUtils.t.sol (1)
14-26
: Consider adding input validation for buffer length.The
iToHex
function assumes the input buffer can be safely doubled in size. For very large inputs, this could lead to out-of-gas errors.function iToHex(bytes memory buffer) public pure returns (string memory) { + require(buffer.length <= 512, "Input too large"); bytes memory converted = new bytes(buffer.length * 2); bytes memory _base = "0123456789abcdef";
bridge-evm/contracts/utils/ReceiptUtils.sol (1)
28-29
: Document the rationale for the 65-bit shift.The flags field is shifted right by 65 bits. This magic number should be documented to explain its significance.
- flags: receipt.flags >> 65, + // Shift by 65 bits to extract the high-order flags, removing the lower bits used for [explain purpose] + flags: receipt.flags >> 65,bridge-evm/contracts/interface/IValidation.sol (1)
51-58
: Consider adding validation parameters for signature threshold.The
validate
functions accept signatures but don't specify the minimum number of required signatures. Consider adding a parameter or separate function to configure this.Consider adding:
function setMinSignatures(uint256 _minSignatures) external returns (bool success); function minSignatures() external view returns (uint256);Also applies to: 62-69
bridge-evm/test/ERC20Bridged.t.sol (2)
30-37
: Add test for zero amount transfer.The fuzz test assumes amount > 0, but it's important to verify that transfers with zero amount are properly handled.
Add a separate test case:
+ function test_revertIf_send_from_bridge_zero_amount(address to) public { + vm.assume(to != address(0) && to != fakeBridge); + vm.startPrank(fakeBridge); + vm.expectRevert("ERC20: transfer amount must be greater than zero"); + token.transfer(to, 0); + vm.stopPrank(); + }
39-53
: Add test for insufficient balance.The test suite should verify that transfers fail when the sender has insufficient balance.
Add a test case:
+ function test_revertIf_send_from_bridge_insufficient_balance(address to, uint256 amount) public { + vm.assume(to != address(0) && to != fakeBridge && amount > 0); + vm.startPrank(fakeBridge); + vm.expectRevert("ERC20: transfer amount exceeds balance"); + token.transfer(to, amount); + vm.stopPrank(); + }bridge-evm/test/differential_testing/receipt2hash.js (2)
54-61
: Remove commented-out code.The commented-out code should be removed if it's no longer needed.
- // const encoded = AbiCoder.defaultAbiCoder().encode( - // ['bytes32', 'bytes32', 'bytes32', 'bytes32', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'uint256', 'bytes'], - // [from, to, tokenAddressFrom, tokenAddressTo, amountFrom, amountTo, chainFrom, chainTo, eventId, flags, data] - // ) - // const messageHash = keccak256(encoded); - // return hashMessage( - // getBytes(messageHash) - // );
84-90
: Fix typo in help message.There's a spacing issue in the help message strings.
- fullHelp = "node receipt2Hash.js--full <from> <to> <tokenAddressFrom> <tokenAddressTo> <amountFrom> <amountTo> <chainFrom> <chainTo> <eventId> <flags> <data>" - miniHelp = "node receipt2Hash.js--mini <to> <tokenAddressTo> <amountTo> <chainFrom> <chainTo> <eventId> <flags> <data>" + fullHelp = "node receipt2Hash.js --full <from> <to> <tokenAddressFrom> <tokenAddressTo> <amountFrom> <amountTo> <chainFrom> <chainTo> <eventId> <flags> <data>" + miniHelp = "node receipt2Hash.js --mini <to> <tokenAddressTo> <amountTo> <chainFrom> <chainTo> <eventId> <flags> <data>"bridge-evm/contracts/interface/BridgeTypes.sol (3)
26-28
: Remove or implement TODO for SHOULD_RESTAKE flag.The TODO comment indicates that the SHOULD_RESTAKE flag is unused. Either implement the functionality or remove the flag.
Would you like me to help implement the restaking functionality or create an issue to track this?
43-55
: Consider adding validation ranges for numeric fields.The FullReceipt struct contains several numeric fields without documented valid ranges.
Add NatSpec comments to document valid ranges for numeric fields:
/// @param amountFrom amount of tokens sent (must be > 0) /// @param amountTo amount of tokens received (must be > 0) /// @param chainFrom chain id of the source chain (must be > 0) /// @param chainTo chain id of the destination chain (must be > 0) /// @param eventId transaction number (must be > 0)
84-93
: Document the purpose of flagData field.The flagData field's purpose is unclear from the current documentation.
- bytes flagData; // additional data of the sending operation (unused for now) + bytes flagData; // additional data for flag-specific operations (e.g., permit data for SEND_WITH_PERMIT flag)bridge-evm/test/ReceiptUtils.t.sol (2)
14-26
: Optimize hex conversion function.The iToHex function could be optimized by using a constant for the base string.
+ bytes constant private _HEX_DIGITS = "0123456789abcdef"; + function iToHex(bytes memory buffer) public pure returns (string memory) { bytes memory converted = new bytes(buffer.length * 2); - bytes memory _base = "0123456789abcdef"; for (uint256 i = 0; i < buffer.length; i++) { - converted[i * 2] = _base[uint8(buffer[i]) / _base.length]; - converted[i * 2 + 1] = _base[uint8(buffer[i]) % _base.length]; + converted[i * 2] = _HEX_DIGITS[uint8(buffer[i]) / 16]; + converted[i * 2 + 1] = _HEX_DIGITS[uint8(buffer[i]) % 16]; } return string(abi.encodePacked("0x", converted)); }
28-80
: Add edge case tests for receipt hashing.The fuzz tests should include specific edge cases.
Add test cases for:
function test_fullReceipt2hash_empty_data() public { // Test with empty data field } function test_fullReceipt2hash_max_values() public { // Test with maximum possible values }bridge-evm/test/Nonces.t.sol (2)
56-84
: Consider adding more edge cases to the fuzz test.The fuzz test for nonce operations is good, but could be enhanced by:
- Testing extremely large numbers for
keyUint
- Testing special addresses (e.g., zero address)
- Testing sequential nonce increments vs. large jumps
function test_fuzz_useNonce( bytes32 keyBytes, uint256 keyUint, address owner ) public { vm.assume( - keyBytes != bytes32(keyUint) && keyUint != uint256(uint160(owner)) + keyBytes != bytes32(keyUint) && + keyUint != uint256(uint160(owner)) && + owner != address(0) ); + // Test extremely large numbers + keyUint = bound(keyUint, type(uint128).max, type(uint256).max); // ... rest of the test }
162-172
: Enhance error case testing.The test for invalid nonce reversion could be expanded to cover more scenarios.
function test_revertIf_useCheckedNonce_that_NotExpected() public { uint256 currentNonce = mockNonce.nonces(alice); + // Test with various invalid nonce values + vm.expectRevert( + abi.encodeWithSelector( + NoncesUpgradeable.InvalidAccountNonce.selector, + uint256(uint160(alice)), + currentNonce + ) + ); + mockNonce.useCheckedNonce(alice, type(uint256).max); + vm.expectRevert( abi.encodeWithSelector( NoncesUpgradeable.InvalidAccountNonce.selector, uint256(uint160(alice)), currentNonce ) ); mockNonce.useCheckedNonce(alice, currentNonce + 1); }bridge-evm/test/bridge_tests/BridgeRestricted.t.sol (1)
118-155
: Consider testing role revocation scenarios.The role-based access test is thorough for granting roles but doesn't test role revocation or expiration.
function test_add_new_role_to_call_bridge() public { // ... existing test code ... + + // Test role revocation + authority.revokeRole(bridgeRoleID, bob, 0); + vm.startPrank(bob); + vm.expectRevert( + abi.encodeWithSelector( + IAccessManaged.AccessManagedUnauthorized.selector, + bob + ) + ); + bridgeInstance.setFeeReceiver(payable(alice)); + vm.stopPrank(); + + // Test role expiration + uint64 expiry = uint64(block.timestamp + 1 days); + authority.grantRole(bridgeRoleID, bob, expiry); + vm.warp(block.timestamp + 2 days); + vm.startPrank(bob); + vm.expectRevert( + abi.encodeWithSelector( + IAccessManaged.AccessManagedUnauthorized.selector, + bob + ) + ); + bridgeInstance.setFeeReceiver(payable(alice)); + vm.stopPrank(); }bridge-evm/test/bridge_tests/BridgeBase.t.sol (2)
80-135
: Consider adding validation for validator addresses.The
setUpValidator
function could benefit from additional validation of validator addresses.function setUpValidator( address authorityAddress, address[] memory validators, address pldSigner, uint256 feeValidityWindow ) public virtual returns (Validator) { + // Validate inputs + require(authorityAddress != address(0), "Invalid authority address"); + require(pldSigner != address(0), "Invalid payload signer address"); + require(validators.length > 0, "Empty validator set"); + for(uint256 i = 0; i < validators.length; i++) { + require(validators[i] != address(0), "Invalid validator address"); + } // ... rest of the function }
197-225
: Consider adding cleanup in tearDown.The
setUp
function creates multiple contracts but there's no corresponding tearDown to clean up resources.Add a tearDown function to clean up the test environment:
+function tearDown() public { + delete signers; + validatorSet = EnumerableSet.AddressSet(new address[](0)); +}bridge-evm/.gas-snapshot (1)
11-12
: Consider optimizing high gas usage in claim tests.The claim tests are consuming significant gas (>1M gas units). Consider optimizing the implementation to reduce gas costs.
Areas to investigate for optimization:
- Storage access patterns in the claim function
- Potential for batching operations
- Redundant state reads/writes
bridge-evm/test/bridge_tests/TokenManager.t.sol (1)
267-275
: Consider adding more edge cases to the zero address test.The test only checks for adding a zero address token. Consider testing other zero address scenarios like external token addresses.
function test_revertIf_addToken_zero_address() public { address token = address(0xD0D0); assertTrue(validatorInstance.addToken(newValidator)); assertFalse(validatorInstance.addToken(address(0))); + // Test external token address zero case + ITokenManager.ExternalTokenUnmapped memory externalToken = ITokenManager + .ExternalTokenUnmapped({ + externalTokenAddress: bytes32(0), + decimals: 18 + }); + vm.expectRevert(ITokenManager.InvalidExternalAddress.selector); + bridgeInstance.addToken(token, externalToken); }bridge-evm/.env.example (1)
15-17
: Add validation range for FEE_VALIDITY_WINDOW.Document the acceptable range for the fee validity window.
-#### Fee validity window (seconds) (0 by default) +#### Fee validity window (seconds) (0 by default, must be between 1 and 86400) FEE_VALIDITY_WINDOW=100bridge-evm/foundry.toml (2)
13-15
: Consider increasing optimizer runs for production.The current optimizer runs might be insufficient for complex contracts.
evm_version = 'istanbul' optimizer = true -runs = 1000 +runs = 10000 # Increased for better optimization
31-33
: Add HTML coverage report configuration.Enable HTML coverage reports for better visualization.
[profile.coverage] via-ir=true no-match-coverage="test|script/.*.sol" report-file="./coverage/lcov.info" +html-report="./coverage/html"
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md (2)
11-13
: Fix abbreviation in documentation.The abbreviation "a.k.a" should include periods for proper formatting: "a.k.a."
-Deposit tokens to the contract (a.k.a wrap tokens) +Deposit tokens to the contract (a.k.a. wrap tokens)🧰 Tools
🪛 LanguageTool
[uncategorized] ~11-~11: The abbreviation/initialism is missing a period after the last letter.
Context: ...eposit Deposit tokens to the contract (a.k.a wrap tokens) *converts msg.value amoun...(ABBREVIATION_PUNCTUATION)
🪛 markdownlint-cli2 (0.17.2)
13-13: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
22-24
: Fix abbreviation in documentation.The abbreviation "a.k.a" should include periods for proper formatting: "a.k.a."
-Withdraw tokens from the contract (a.k.a unwrap tokens) +Withdraw tokens from the contract (a.k.a. unwrap tokens)🧰 Tools
🪛 LanguageTool
[uncategorized] ~22-~22: The abbreviation/initialism is missing a period after the last letter.
Context: ...raw Withdraw tokens from the contract (a.k.a unwrap tokens) *converts ERC20 tokens ...(ABBREVIATION_PUNCTUATION)
🪛 markdownlint-cli2 (0.17.2)
24-24: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/Bridge.sol/contract.Bridge.md (1)
11-33
: Add initialization requirements and constraints.The documentation should specify:
- Valid parameter constraints (e.g., non-zero addresses)
- Order of contract deployment requirements
- Initialization failure conditions
bridge-evm/README.md (1)
1-57
: Enhance README with additional sections.Consider adding:
- Prerequisites section (required tools and versions)
- Deployment instructions
- Configuration guide (environment variables)
- Contributing guidelines
- License information
🧰 Tools
🪛 LanguageTool
[uncategorized] ~7-~7: Loose punctuation mark.
Context: ...s. ## Project Structure -contracts/
: Contains the Solidity smart contracts. ...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~8-~8: Loose punctuation mark.
Context: ...lidity smart contracts. -interface/
: Interfaces for the contracts. - `toke...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~9-~9: Loose punctuation mark.
Context: ...terfaces for the contracts. -token/
: Token-related contracts. - `upgradeab...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~10-~10: Loose punctuation mark.
Context: ...en-related contracts. -upgradeable/
: Upgradeable contracts. -utils/
: Ut...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~11-~11: Loose punctuation mark.
Context: ...e/: Upgradeable contracts. -
utils/: Utility contracts. -
docs/`: Documenta...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~12-~12: Loose punctuation mark.
Context: ...-utils/
: Utility contracts. -docs/
: Documentation for the contracts. - `lib...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~13-~13: Loose punctuation mark.
Context: ...ocumentation for the contracts. -lib/
: External libraries and dependencies. - ...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~14-~14: Loose punctuation mark.
Context: ...libraries and dependencies. -scripts/
: Scripts for deployment and management. ...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~15-~15: Loose punctuation mark.
Context: ...for deployment and management. -test/
: Unit tests for the contracts. ## Stack...(UNLIKELY_OPENING_PUNCTUATION)
🪛 markdownlint-cli2 (0.17.2)
20-20: Unordered list indentation
Expected: 0; Actual: 1(MD007, ul-indent)
21-21: Unordered list indentation
Expected: 0; Actual: 1(MD007, ul-indent)
23-23: Headings must start at the beginning of the line
null(MD023, heading-start-left)
52-52: Trailing punctuation in heading
Punctuation: ':'(MD026, no-trailing-punctuation)
.github/workflows/evm-test.yml (2)
8-11
: Fix YAML indentation.Correct the indentation for path specifications:
paths: - - "bridge-evm/**" + - "bridge-evm/**"🧰 Tools
🪛 YAMLlint (1.35.1)
[warning] 8-8: wrong indentation: expected 6 but found 8
(indentation)
[warning] 11-11: wrong indentation: expected 6 but found 8
(indentation)
1-70
: Optimize workflow configuration.Consider the following improvements:
- Add caching for Foundry installations
- Include job timeout limits
- Add concurrency limits for resource management
- Add a newline at the end of file
🧰 Tools
🪛 YAMLlint (1.35.1)
[warning] 8-8: wrong indentation: expected 6 but found 8
(indentation)
[warning] 11-11: wrong indentation: expected 6 but found 8
(indentation)
[warning] 36-36: wrong indentation: expected 10 but found 12
(indentation)
[error] 60-60: trailing spaces
(trailing-spaces)
[error] 63-63: trailing spaces
(trailing-spaces)
[error] 70-70: no new line character at the end of file
(new-line-at-end-of-file)
bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md (1)
32-34
: Add more details about the hashing process.Consider adding more details about the hashing process, such as:
- The order of fields being hashed
- The encoding method used (e.g., abi.encode, abi.encodePacked)
- Any potential security considerations
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md (3)
32-34
: Add missing descriptions for token address fields.The following fields are missing descriptions:
tokenAddressFrom
: Add description like "source token address"tokenAddressTo
: Add description like "destination token address"
34-36
: Add missing descriptions for amount fields.The following fields are missing descriptions:
amountFrom
: Add description like "amount of tokens sent from source"amountTo
: Add description like "amount of tokens to be received at destination"
93-94
: Add missing descriptions for external token and flag data fields.The following fields are missing descriptions:
externalTokenAddress
: Add description like "address of the token on the external chain"flagData
: Add description like "additional data for the flags"bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md (1)
87-105
: Add more details about validation requirements.Consider adding more details about:
- The validation process and requirements
- The format and structure of the signature
- The minimum number of validators required for a valid signature
- Any potential failure scenarios
bridge-evm/package.json (1)
15-32
: Consider parameterizing deployment configurations.The deployment scripts contain hardcoded addresses and URLs. Consider:
- Moving these configurations to a separate config file.
- Using environment variables for different environments.
- Removing the
--legacy
flag if not required for backward compatibility.Example configuration structure:
- "deploy:bridge:testnet": "WRAPPED_TOKEN=0x2Cf845b49e1c4E5D657fbBF36E97B7B5B7B7b74b forge script -v -g 200 --slow --legacy --broadcast --rpc-url https://network.ambrosus-test.io --verifier sourcify --verifier-url https://sourcify.ambrosus.io/ --verify ./script/DeployBridge.s.sol", + "deploy:bridge:testnet": "forge script -v -g 200 --slow --broadcast --rpc-url $RPC_URL --verifier sourcify --verifier-url $SOURCIFY_URL --verify ./script/DeployBridge.s.sol",Create a
.env.testnet
file:WRAPPED_TOKEN=0x2Cf845b49e1c4E5D657fbBF36E97B7B5B7B7b74b RPC_URL=https://network.ambrosus-test.io SOURCIFY_URL=https://sourcify.ambrosus.io/bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/contract.ValidatorUpgradeable.md (2)
250-250
: Improve documentation grammar.Change "Validate the send payload" to "Validate the payload to be sent" for better clarity.
🧰 Tools
🪛 LanguageTool
[grammar] ~250-~250: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...(A_INFINITIVE)
154-154
: Add missing parameter description.The
payloadSigner_
parameter lacks a description in the documentation.Add a description:
|Name|Type|Description| |----|----|-----------| -|`payloadSigner_`|`address`|| +|`payloadSigner_`|`address`|Address of the signer that will be used to validate payloads|bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md (1)
293-293
: Improve documentation grammar.Change "Validate the send payload" to "Validate the payload to be sent" for better clarity.
🧰 Tools
🪛 LanguageTool
[grammar] ~293-~293: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...(A_INFINITIVE)
bridge-evm/broadcast/DeployBridge.s.sol/22040/run-latest.json (1)
71-73
: Optimize gas usage for contract deployments.The gas usage for contract deployments appears high:
- Bridge implementation: 469a8a gas
- Bridge proxy: 7faf8 gas
Consider optimizing the contract code to reduce deployment costs. Some suggestions:
- Minimize the contract size by removing unused functions
- Optimize storage layout
- Use assembly for low-level operations
Also applies to: 92-94
bridge-evm/docs/src/contracts/Validator.sol/contract.Validator.md (1)
11-12
: Enhance documentation with security considerations.While the documentation covers the basic functionality, it would benefit from additional details about:
- Security implications of the authority role
- Validator management and consensus mechanisms
- Fee validity window constraints and implications
Add a "Security Considerations" section discussing:
- Authority privileges and risks
- Validator quorum requirements
- Fee validity window attack vectors
Also applies to: 28-31
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md (1)
45-46
: Fix grammar in flag description.The description should use "for" instead of "of":
-*Should send the additional native tokens to the receiver on the other chain in exchange of higher fee amount* +*Should send the additional native tokens to the receiver on the other chain in exchange for higher fee amount*🧰 Tools
🪛 LanguageTool
[grammar] ~45-~45: The usual preposition to use after “in exchange” is “for”, not “of”. Did you mean “in exchange for”?
Context: ...kens to the receiver on the other chain in exchange of higher fee amount* ```solidity uint25...(IN_CHARGE_OF_FROM)
🪛 markdownlint-cli2 (0.17.2)
45-45: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/README.md (1)
1-57
: Enhance README with additional sections.While the README covers the basics, it would benefit from:
- Add a "Prerequisites" section listing required tools and versions
- Include a "Configuration" section explaining environment variables
- Add a "Deployment" section with network-specific instructions
- Include a "Security" section with audit status and known risks
- Add a "Contributing" section with guidelines
🧰 Tools
🪛 LanguageTool
[uncategorized] ~7-~7: Loose punctuation mark.
Context: ...s. ## Project Structure -contracts/
: Contains the Solidity smart contracts. ...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~8-~8: Loose punctuation mark.
Context: ...lidity smart contracts. -interface/
: Interfaces for the contracts. - `toke...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~9-~9: Loose punctuation mark.
Context: ...terfaces for the contracts. -token/
: Token-related contracts. - `upgradeab...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~10-~10: Loose punctuation mark.
Context: ...en-related contracts. -upgradeable/
: Upgradeable contracts. -utils/
: Ut...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~11-~11: Loose punctuation mark.
Context: ...e/: Upgradeable contracts. -
utils/: Utility contracts. -
docs/`: Documenta...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~12-~12: Loose punctuation mark.
Context: ...-utils/
: Utility contracts. -docs/
: Documentation for the contracts. - `lib...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~13-~13: Loose punctuation mark.
Context: ...ocumentation for the contracts. -lib/
: External libraries and dependencies. - ...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~14-~14: Loose punctuation mark.
Context: ...libraries and dependencies. -scripts/
: Scripts for deployment and management. ...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~15-~15: Loose punctuation mark.
Context: ...for deployment and management. -test/
: Unit tests for the contracts. ## Stack...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~18-~18: A determiner appears to be missing. Consider inserting it.
Context: ...nit tests for the contracts. ## Stack Project utilizes the following stack: - [Found...(AI_EN_LECTOR_MISSING_DETERMINER)
bridge-evm/docs/src/contracts/utils/PayloadUtils.sol/library.PayloadUtils.md (1)
8-11
: Add technical details to function documentation.The documentation would benefit from:
- Explain the specific fields from SendPayload that are included in the hash
- Document the hashing algorithm and process
- Add examples of hash generation
- Include security considerations for message signing
Also applies to: 34-37
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
bridge-evm/docs/solidity.min.js
is excluded by!**/*.min.js
bridge-evm/package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (86)
.github/workflows/evm-test.yml
(1 hunks).gitmodules
(1 hunks)bridge-evm/.env.example
(1 hunks)bridge-evm/.gas-snapshot
(1 hunks)bridge-evm/.gitignore
(1 hunks)bridge-evm/README.md
(1 hunks)bridge-evm/broadcast/DeployBridge.s.sol/22040/run-latest.json
(1 hunks)bridge-evm/contracts/Bridge.sol
(1 hunks)bridge-evm/contracts/Validator.sol
(1 hunks)bridge-evm/contracts/interface/BridgeTypes.sol
(1 hunks)bridge-evm/contracts/interface/IBridge.sol
(1 hunks)bridge-evm/contracts/interface/ITokenManager.sol
(1 hunks)bridge-evm/contracts/interface/IValidation.sol
(1 hunks)bridge-evm/contracts/interface/IValidatorV1.sol
(1 hunks)bridge-evm/contracts/interface/IWrapped.sol
(1 hunks)bridge-evm/contracts/token/ERC20Bridged.sol
(1 hunks)bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol
(1 hunks)bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol
(1 hunks)bridge-evm/contracts/upgradeable/ValidatorUpgradeable.sol
(1 hunks)bridge-evm/contracts/utils/AddressUtils.sol
(1 hunks)bridge-evm/contracts/utils/NoncesUpgradeable.sol
(1 hunks)bridge-evm/contracts/utils/PayloadUtils.sol
(1 hunks)bridge-evm/contracts/utils/ReceiptUtils.sol
(1 hunks)bridge-evm/docs/.gitignore
(1 hunks)bridge-evm/docs/book.css
(1 hunks)bridge-evm/docs/book.toml
(1 hunks)bridge-evm/docs/src/README.md
(1 hunks)bridge-evm/docs/src/SUMMARY.md
(1 hunks)bridge-evm/docs/src/contracts/Bridge.sol/contract.Bridge.md
(1 hunks)bridge-evm/docs/src/contracts/README.md
(1 hunks)bridge-evm/docs/src/contracts/Validator.sol/contract.Validator.md
(1 hunks)bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
(1 hunks)bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
(1 hunks)bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
(1 hunks)bridge-evm/docs/src/contracts/interface/README.md
(1 hunks)bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
(1 hunks)bridge-evm/docs/src/contracts/token/README.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/README.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/contract.ValidatorUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md
(1 hunks)bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/utils/PayloadUtils.sol/library.PayloadUtils.md
(1 hunks)bridge-evm/docs/src/contracts/utils/README.md
(1 hunks)bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md
(1 hunks)bridge-evm/foundry.toml
(1 hunks)bridge-evm/hardhat.config.ts
(0 hunks)bridge-evm/ignition/modules/Lock.ts
(0 hunks)bridge-evm/lib/forge-std
(1 hunks)bridge-evm/package.json
(1 hunks)bridge-evm/remappings.txt
(1 hunks)bridge-evm/script/DeployAuthority.s.sol
(1 hunks)bridge-evm/script/DeployBridge.s.sol
(1 hunks)bridge-evm/script/DeployValidator.s.sol
(1 hunks)bridge-evm/script/DeployerBase.s.sol
(1 hunks)bridge-evm/script/SetValidatorPayloadSigner.s.sol
(1 hunks)bridge-evm/script/SetValidatorRelaySigner.s.sol
(1 hunks)bridge-evm/scripts/deploy.ts
(0 hunks)bridge-evm/test/AddressUtils.t.sol
(1 hunks)bridge-evm/test/Bridge.t.sol
(1 hunks)bridge-evm/test/ERC20Bridged.t.sol
(1 hunks)bridge-evm/test/Nonces.t.sol
(1 hunks)bridge-evm/test/PayloadUtils.t.sol
(1 hunks)bridge-evm/test/ReceiptUtils.t.sol
(1 hunks)bridge-evm/test/SigUtils.sol
(1 hunks)bridge-evm/test/Validator.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeBase.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeClaim.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeRestricted.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeSend.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeValidation.t.sol
(1 hunks)bridge-evm/test/bridge_tests/TokenManager.t.sol
(1 hunks)bridge-evm/test/differential_testing/bytes2address.js
(1 hunks)bridge-evm/test/differential_testing/payload2hash.js
(1 hunks)bridge-evm/test/differential_testing/receipt2hash.js
(1 hunks)bridge-evm/test/mocks/MockBadNativeReceiver.sol
(1 hunks)bridge-evm/test/mocks/MockERC20.sol
(1 hunks)bridge-evm/test/mocks/MockNonce.sol
(1 hunks)bridge-evm/test/mocks/sAMB.sol
(1 hunks)bridge-evm/tsconfig.json
(0 hunks)
💤 Files with no reviewable changes (4)
- bridge-evm/ignition/modules/Lock.ts
- bridge-evm/tsconfig.json
- bridge-evm/hardhat.config.ts
- bridge-evm/scripts/deploy.ts
✅ Files skipped from review due to trivial changes (13)
- bridge-evm/docs/.gitignore
- bridge-evm/remappings.txt
- bridge-evm/lib/forge-std
- .gitmodules
- bridge-evm/docs/book.css
- bridge-evm/docs/book.toml
- bridge-evm/docs/src/contracts/utils/README.md
- bridge-evm/docs/src/contracts/token/README.md
- bridge-evm/docs/src/contracts/upgradeable/README.md
- bridge-evm/.gitignore
- bridge-evm/docs/src/contracts/README.md
- bridge-evm/docs/src/contracts/interface/README.md
- bridge-evm/docs/src/SUMMARY.md
🧰 Additional context used
🪛 LanguageTool
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
[uncategorized] ~40-~40: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### MiniReceip...
(E_G)
[uncategorized] ~65-~65: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st token address| |amountTo
|uint256
|amount of tokens sent| |chainFrom
|uint256
|...
(AMOUNTOF_TO_NUMBEROF)
[uncategorized] ~70-~70: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### SendPayloa...
(E_G)
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
[uncategorized] ~11-~11: The abbreviation/initialism is missing a period after the last letter.
Context: ...eposit Deposit tokens to the contract (a.k.a wrap tokens) *converts msg.value amoun...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~22-~22: The abbreviation/initialism is missing a period after the last letter.
Context: ...raw Withdraw tokens from the contract (a.k.a unwrap tokens) *converts ERC20 tokens ...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~34-~34: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...-|----|-----------| |amount
|uint256
|amount of tokens to withdraw| ## Events ### ...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/README.md
[uncategorized] ~7-~7: Loose punctuation mark.
Context: ...s. ## Project Structure - contracts/
: Contains the Solidity smart contracts. ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~8-~8: Loose punctuation mark.
Context: ...lidity smart contracts. - interface/
: Interfaces for the contracts. - `toke...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~9-~9: Loose punctuation mark.
Context: ...terfaces for the contracts. - token/
: Token-related contracts. - `upgradeab...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~10-~10: Loose punctuation mark.
Context: ...en-related contracts. - upgradeable/
: Upgradeable contracts. - utils/
: Ut...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~11-~11: Loose punctuation mark.
Context: ...e/: Upgradeable contracts. -
utils/: Utility contracts. -
docs/`: Documenta...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~12-~12: Loose punctuation mark.
Context: ...- utils/
: Utility contracts. - docs/
: Documentation for the contracts. - `lib...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~13-~13: Loose punctuation mark.
Context: ...ocumentation for the contracts. - lib/
: External libraries and dependencies. - ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~14-~14: Loose punctuation mark.
Context: ...libraries and dependencies. - scripts/
: Scripts for deployment and management. ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~15-~15: Loose punctuation mark.
Context: ...for deployment and management. - test/
: Unit tests for the contracts. ## Stack...
(UNLIKELY_OPENING_PUNCTUATION)
bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
[uncategorized] ~80-~80: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...ct| ### _update *Transfers a value
amount of tokens from from
to to
, or alter...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
[grammar] ~143-~143: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...
(A_INFINITIVE)
bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md
[uncategorized] ~70-~70: A punctuation mark might be missing here.
Context: ...lue|
bytes32|bytes32 value to convert| |
le|
bool`|true if the value is in lit...
(AI_EN_LECTOR_MISSING_PUNCTUATION)
[uncategorized] ~119-~119: A punctuation mark might be missing here.
Context: ...ype|Description| |----|----|-----------| |_address
|string
|string value to con...
(AI_EN_LECTOR_MISSING_PUNCTUATION)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
[grammar] ~293-~293: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...
(A_INFINITIVE)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/contract.ValidatorUpgradeable.md
[grammar] ~250-~250: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...
(A_INFINITIVE)
bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md
[uncategorized] ~222-~222: Possible missing article found.
Context: ...ion should be called by admin to deploy external token to the chain.* ```solidity func...
(AI_HYDRA_LEO_MISSING_AN)
[uncategorized] ~509-~509: Possible missing article found.
Context: ...ion should be called by admin to deploy external token to the chain.* *This token will ...
(AI_HYDRA_LEO_MISSING_AN)
[uncategorized] ~511-~511: Possible missing comma found.
Context: ...e chain.* *This token will be used for bridging as minting and burning. For more detail...
(AI_HYDRA_LEO_MISSING_COMMA)
bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
[grammar] ~515-~515: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ..._validateSendValues Guard for validate the send values ```solidity function _validate...
(A_INFINITIVE)
[uncategorized] ~630-~630: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...dress of the token| |amount
|uint256
|amount of tokens to send| |receiver
|`address...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/README.md
[uncategorized] ~7-~7: Loose punctuation mark.
Context: ...s. ## Project Structure - contracts/
: Contains the Solidity smart contracts. ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~8-~8: Loose punctuation mark.
Context: ...lidity smart contracts. - interface/
: Interfaces for the contracts. - `toke...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~9-~9: Loose punctuation mark.
Context: ...terfaces for the contracts. - token/
: Token-related contracts. - `upgradeab...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~10-~10: Loose punctuation mark.
Context: ...en-related contracts. - upgradeable/
: Upgradeable contracts. - utils/
: Ut...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~11-~11: Loose punctuation mark.
Context: ...e/: Upgradeable contracts. -
utils/: Utility contracts. -
docs/`: Documenta...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~12-~12: Loose punctuation mark.
Context: ...- utils/
: Utility contracts. - docs/
: Documentation for the contracts. - `lib...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~13-~13: Loose punctuation mark.
Context: ...ocumentation for the contracts. - lib/
: External libraries and dependencies. - ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~14-~14: Loose punctuation mark.
Context: ...libraries and dependencies. - scripts/
: Scripts for deployment and management. ...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~15-~15: Loose punctuation mark.
Context: ...for deployment and management. - test/
: Unit tests for the contracts. ## Stack...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~18-~18: A determiner appears to be missing. Consider inserting it.
Context: ...nit tests for the contracts. ## Stack Project utilizes the following stack: - [Found...
(AI_EN_LECTOR_MISSING_DETERMINER)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
[grammar] ~45-~45: The usual preposition to use after “in exchange” is “for”, not “of”. Did you mean “in exchange for”?
Context: ...kens to the receiver on the other chain in exchange of higher fee amount* ```solidity uint25...
(IN_CHARGE_OF_FROM)
🪛 markdownlint-cli2 (0.17.2)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
26-26: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
59-59: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
88-88: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
13-13: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
24-24: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
30-30: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/README.md
20-20: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
21-21: Unordered list indentation
Expected: 0; Actual: 1
(MD007, ul-indent)
23-23: Headings must start at the beginning of the line
null
(MD023, heading-start-left)
52-52: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
43-43: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
49-49: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
56-56: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
69-69: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
75-75: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
101-101: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
10-10: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
19-19: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
47-47: Emphasis style
Expected: asterisk; Actual: underscore
(MD049, emphasis-style)
47-47: Emphasis style
Expected: asterisk; Actual: underscore
(MD049, emphasis-style)
55-55: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
71-71: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md
14-14: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
20-20: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
35-35: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
59-59: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
81-81: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md
16-16: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
22-22: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
39-39: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
45-45: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
66-66: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
73-73: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
80-80: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
90-90: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
96-96: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
103-103: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
116-116: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
122-122: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md
50-50: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
59-59: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
78-78: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
88-88: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
107-107: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
116-116: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
75-75: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
81-81: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
100-100: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
125-125: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
131-131: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
150-150: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
156-156: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
181-181: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
196-196: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
211-211: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
247-247: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
254-254: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
261-261: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
277-277: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
284-284: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
307-307: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
314-314: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/contract.ValidatorUpgradeable.md
75-75: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
81-81: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
100-100: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
125-125: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
131-131: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
150-150: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
156-156: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
181-181: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
196-196: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
211-211: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
234-234: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
241-241: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
264-264: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
271-271: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
47-47: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
71-71: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
86-86: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
92-92: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
113-113: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
121-121: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
128-128: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
141-141: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
148-148: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
168-168: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
192-192: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
198-198: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
224-224: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
233-233: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
248-248: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
254-254: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
269-269: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
275-275: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
290-290: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
296-296: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
312-312: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
326-326: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
341-341: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
355-355: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
372-372: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
386-386: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
400-400: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
423-423: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
437-437: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
451-451: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
465-465: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
479-479: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
493-493: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
507-507: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md
74-74: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
82-82: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
104-104: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
111-111: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
130-130: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
136-136: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
155-155: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
161-161: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
180-180: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
186-186: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
205-205: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
211-211: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
237-237: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
246-246: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
261-261: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
276-276: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
302-302: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
308-308: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
327-327: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
333-333: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
352-352: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
358-358: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
377-377: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
383-383: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
398-398: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
419-419: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
427-427: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
447-447: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
454-454: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
471-471: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
477-477: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
492-492: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
498-498: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
524-524: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
533-533: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
548-548: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
554-554: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
569-569: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
575-575: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
44-44: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
53-53: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
60-60: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
84-84: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
97-97: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
120-120: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
127-127: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
134-134: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
150-150: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
157-157: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
181-181: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
188-188: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
199-199: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
205-205: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
212-212: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
220-220: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
226-226: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
241-241: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
256-256: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
271-271: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
286-286: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
301-301: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
316-316: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
350-350: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
367-367: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
382-382: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
406-406: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
444-444: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
64-64: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
79-79: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
94-94: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
116-116: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
123-123: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
145-145: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
152-152: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
171-171: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
177-177: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
184-184: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
200-200: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
208-208: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
227-227: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
233-233: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
252-252: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
258-258: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
277-277: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
283-283: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
309-309: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
318-318: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
337-337: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
356-356: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
371-371: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
386-386: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
401-401: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
420-420: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
426-426: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
433-433: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
445-445: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
451-451: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
458-458: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
470-470: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
476-476: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
498-498: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
506-506: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
528-528: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
550-550: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
566-566: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
586-586: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
603-603: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
624-624: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
649-649: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
672-672: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
701-701: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
710-710: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
717-717: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
742-742: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
755-755: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
780-780: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
787-787: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
794-794: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
812-812: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
819-819: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/Validator.sol/contract.Validator.md
24-24: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
4-4: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
9-9: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
18-18: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
27-27: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
36-36: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
45-45: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
54-54: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/PayloadUtils.sol/library.PayloadUtils.md
19-19: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
25-25: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
45-45: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
51-51: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
🪛 YAMLlint (1.35.1)
.github/workflows/evm-test.yml
[warning] 8-8: wrong indentation: expected 6 but found 8
(indentation)
[warning] 11-11: wrong indentation: expected 6 but found 8
(indentation)
[warning] 36-36: wrong indentation: expected 10 but found 12
(indentation)
[error] 60-60: trailing spaces
(trailing-spaces)
[error] 63-63: trailing spaces
(trailing-spaces)
[error] 70-70: no new line character at the end of file
(new-line-at-end-of-file)
🔇 Additional comments (87)
bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md (2)
1-8
: LGTM! Well-documented contract overview.The contract follows the upgradeable pattern correctly and clearly states its purpose of tracking nonces for different types.
10-16
: Great use of ERC-7201 namespaced storage pattern!The implementation follows OpenZeppelin's best practices for upgradeable contracts by:
- Using namespaced storage to prevent storage collisions
- Properly defining the storage location constant
- Well-organized storage struct with clear mapping
Also applies to: 134-144
bridge-evm/script/SetValidatorRelaySigner.s.sol (1)
1-1
: Consider using an open-source license.The UNLICENSED SPDX identifier suggests this code is proprietary. Consider using an appropriate open-source license if this is intended to be an open-source project.
bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md (1)
12-14
: Good use of ERC7201 storage pattern!The contract follows best practices by using a namespaced storage slot for upgradeable contracts, which helps prevent storage collisions.
bridge-evm/test/mocks/MockBadNativeReceiver.sol (2)
1-2
: LGTM! License and pragma version are appropriate.The UNLICENSED identifier is suitable for test code, and the Solidity version is recent with built-in security features.
4-4
: LGTM! Contract name is descriptive and follows mock naming convention.The name
MockBadNativeReceiver
clearly indicates its purpose as a mock contract that fails to receive native tokens.bridge-evm/contracts/Bridge.sol (2)
4-6
: Check import usage
The import statements forIValidation
andBridgeUpgradeable
seem consistent with usage in the code. No immediate issues found.
8-8
: Solid usage of the upgradeable pattern
By inheritingBridgeUpgradeable
, the contract can delegate bridging logic to the upgradeable base. Ensure that any reentrancy or state-altering logic is protected via relevant modifiers (e.g., reentrancy guards) in the base if needed.bridge-evm/contracts/token/ERC20Bridged.sol (3)
1-8
: Imports look correct
The initial imports from OpenZeppelin’s ERC20 and ERC20Permit appear consistent with the usage in this file.
9-14
: Access considerations for_bridgeAddress
Declaring_bridgeAddress
asprivate
is good for encapsulation. However, ensure that the contract design specifies how (or if) this address can be updated. If the address is never intended to change, you might consider making itimmutable
.
58-79
: Assess bridging logic for potential reentrancy
The bridging logic for minting (whenfrom == _bridgeAddress
) and burning (whento == _bridgeAddress
) is functionally sound. However, consider usingReentrancyGuard
or similar safeguards if calls to the bridge can be externally triggered or reentered. Also, emitting events upon mint or burn could aid external indexing.bridge-evm/contracts/utils/NoncesUpgradeable.sol (3)
17-17
: Good use of a custom error
UsingInvalidAccountNonce
helps provide clearer revert reasons and saves gas compared to revert strings.
24-36
: Validate integrity of storage slot
_getNoncesStorage
sets the storage slot via inline assembly. Verify thatNoncesStorageLocation
is correct and remains consistent across any future upgrades to avoid nonce corruption.
69-77
: Potential overflow in unchecked block
While_useNonce
uses an unchecked increment, overflows are highly unlikely under normal conditions. Still, ensure you’re confident no attacker-controlled repetition could increment nonces enough to reach a boundary in extreme scenarios.bridge-evm/contracts/interface/ITokenManager.sol (3)
7-16
: Validate struct naming and documentation clarity.
The structsExternalToken
andExternalTokenUnmapped
appear consistent, but ensure documentation, especially aroundexternalTokenAddress
, highlights whether it’s a hashed form or a direct payload. This helps prevent confusion when referencing these values across bridging logic.
18-53
: Events appear comprehensive.
These event definitions provide clear auditing points. Ensure that test coverage includes verification of emitted events for each function that triggers them, and confirm that indexing the most relevant parameters is consistent with best practices.
54-84
: Good use of custom errors for clarity.
Defining specific error types improves readability and debugging. Verify that consuming contracts or libraries handle these errors appropriately—particularly in upgrade contexts.bridge-evm/script/DeployerBase.s.sol (5)
30-42
: Overall logic ofcheckDeployed
.
This function cleanly checks for prior deployments to avoid re-deployment. Remember to confirm that direct usage ofvm.getDeployment(contractName)
is consistent with your environment’s naming conventions to prevent false negatives.
101-106
:deployAuthority
is straightforward.
The function is concise and performs the minimal tasks needed for deployment. Confirm that theAUTHORITY_ADMIN
environment variable is set or defaulting todeployer.addr
is correct for your environment.
108-135
: Validator deployment logic.
Good use ofUpgrades.deployUUPSProxy
for upgradeable contracts. Confirm that environment variablesVALIDATORS
,PAYLOAD_SIGNER
, andFEE_VALIDITY_WINDOW
are correctly recognized by your environment (string splitting for arrays, fallback logic, etc.).
137-165
: Bridge deployment flows.
Check that the environment variables (WRAPPED_TOKEN
,FEE_RECEIVER
, etc.) are always available, and verify how default values are handled if not set. Also consider verifying thenativeSendAmount
is appropriate for your bridging needs.
168-197
:getAuthority
,getValidator
, andgetBridge
patterns.
These functions re-check existing deployments versus new. The logic is consistent, but ensure that thecheckDeployed("ContractName")
strings match the actual contract deployment labels in the environment.bridge-evm/contracts/interface/IBridge.sol (4)
10-26
: Specific custom errors add clarity.
Good approach using descriptive errors. Ensure that calling contracts and tests handle or expect these errors correctly (e.g.,vm.expectRevert(IBridge.InvalidChain.selector)
in Foundry tests).
28-53
: Events are well-defined.
Continue to confirm that relevant parameters are indexed. If bridging analytics rely on event indexing, verify the correct fields (changer
,newValidator
, etc.) are used as indexed.
127-146
: Overloads ofisClaimed
.
The interface supports three ways to check claims. Confirm that external documentation clarifies which scenario aligns with the bridging flow so integrators don’t call the more expensive function unnecessarily.
166-176
: Setter functions.
Ensure that only privileged roles (e.g., an admin or governance role) can call these functions in the implementation. Confirm that your contract extends an access control pattern to restrict usage.bridge-evm/contracts/upgradeable/ValidatorUpgradeable.sol (8)
1-4
: Use standard SPDX identifier and pragma settings
No issues found in the basic SPDX license identifier and pragma statements.
5-19
: Validate OpenZeppelin imports
Imports from OpenZeppelin’s upgradeable libraries and cryptography modules are appropriate for an upgradeable validator contract. Ensure theAccessManagedUpgradeable.sol
path is correct and that the rest of the project references remain consistent through any external library version changes.
20-25
: Abstract contract usage
DeclaringValidatorUpgradeable
as an abstract contract is sensible for partial implementations. Make sure the child contracts override and complete all required functionality from the interfaces.
52-89
: Upgrade-safe initialization and usage
The initialization functions (__Validator_init
and__Validator_init_unchained
) follow upgradeable contract best practices. However, there is a comment about uncertainty (“Dont know why it should be called here, according to docs…”) at line 75. Double-check the official OpenZeppelin upgradeable patterns to ensure correct parent initializer calls.
91-103
: Validation readiness checks
ThereadyToValidate
modifier correctly reverts if no validators exist, if payload signer is unset, or if fee validity window is 0. This is a good gate-keeping approach.
105-147
: Validator management
isValidator
,addValidator
,removeValidator
all look consistent.- Consider verifying that each validator is unique upon addition to avoid potential confusion in the chain of trust (although the
EnumerableSet
already ensures uniqueness).- Confirm that only authorized roles have permission to add or remove validators.
149-176
: Setter functions require validation
setPayloadSigner
andsetFeeValidityWindow
properly emit events and enforce constraints (feeValidityWindow_ > 0
). Ensure that these setter functions are restricted to appropriate roles (e.g.,restricted
fromAccessManagedUpgradeable
).
220-266
: Multiplevalidate
methods
Thevalidate
overloads forFullReceipt
,MiniReceipt
, andvalidatePayload
are clear. The code reuses_validate
for receipt-based checks, ensuring consistency.bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol (9)
1-3
: License and pragma
No issues found here.
4-6
: Upgradeability import check
The import ofInitializable.sol
aligns with standard upgradeable contract practices.
13-13
: Abstract contract approach
TokenManagerUpgradeable
is declared abstract, indicating other contracts need to implement any missing logic or override certain methods. This is aligned with the interface-based design.
15-38
: TokenManagerStorage struct
Storing data in a dedicated struct helps keep state succinct. Ensure all external references (e.g.,bridge
andSAMB
) are set properly in initialization.
62-67
:isBridgable
modifier
Checks bridging eligibility but referencesbridgableTokens(token.toAddress())
. Make sure no other bridging preconditions are missing, such as pause checks or external token mapping checks, if needed.
156-159
: Wrapping logic
Internal_wrap
usesIWrapped(_getTokenManagerStorage().SAMB).deposit{value: amount}()
. Verify that the contract will have sufficient native balance. Consider adding checks or revert messages if deposit fails.
219-260
:_addToken
flow
- Properly reverts if a token is already added or an external token is already mapped.
- The event emission is clear.
Ensure that only a privileged caller can add tokens.
293-311
:_unmapToken
Removes the mapping, then emitsTokenUnmapped
. This is precise. Checking for mapped tokens is good. No concerns here.
353-364
: Edge cases for_pauseToken
Reverts if the token is already paused. Ensure that if a token is paused repeatedly, the function doesn’t inadvertently lock the system. Current logic is correct for flip-based toggles.bridge-evm/test/bridge_tests/BridgeClaim.t.sol (14)
1-3
: Basic license and pragma
Standard disclaimers, no issues found.
4-5
: Foundry-based test
Usingforge-std/Test.sol
is standard for Foundry test setups and includesvm
cheatcodes. This structure is consistent with typical Foundry usage.
28-48
:signReceipt
function
This helper concats signatures from all signers. Code is generally sound. Confirm thatsigners
array is non-empty in the test setup, or else the code may produce an empty signature.
50-85
:test_claim_withFullReceipt
Good coverage of receipt-based claiming, balance checks, andisClaimed
calls. Helper methods likesignReceipt
and Foundry-specificvm.expectEmit
are used effectively.
87-123
:test_claim_withMiniReceipt
Similar logic to the full receipt test, ensuring coverage for the mini receipt flow. The test is well structured.
125-147
: Check for repeated claims
test_revertIf_claim_alreadyClaimed
properly verifies that a second claim attempt reverts with the expected reason. Great test of idempotent bridging claims.
149-170
:test_revertIf_claim_TokenNotBridgable
Ensures bridging fails when the token is unknown. This is a key negative test ensuring correct bridging restrictions.
172-198
:test_revertIf_claim_wrongChain
Checks chain ID mismatch. This negative test scenario is crucial for bridging logic.
200-230
:test_revertIf_claim_tokenPaused
Good test ensuring claims are blocked if the token is paused, verifying compliance with bridging pause logic.
232-261
:test_claim_wrapped
Simulates bridging a wrapped token. The test ensures unlocking logic is correct. The usage of Foundry’sdeal
for test setup is appropriate.
263-297
:test_claim_wrapped_with_unwrap
Tests unwrapping logic by settingBridgeFlags.SHOULD_UNWRAP
. Well done verifying native token redemption using the bridging contract.
299-330
:test_revertWhen_claim_wrapped_with_unwrap_BadReceiver
Tests a failing scenario where the receiver address cannot accept native transfers. Thorough coverage for bridging edge cases.
332-368
:test_claim_withSendNativeFlag
Verifies bridging contract’snativeSendAmount()
logic and that the partial native funds are correctly forwarded. Good demonstration of bridging + native extra fees.
370-401
:test_revertWhen_claim_withSendNativeFlag_BadReceiver
Ensures the bridging attempt reverts when a contract or address rejects native transfers. This is robust negative coverage.bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol (4)
1-3
: License header and version look good.
No issues found here.
49-60
: Verify storage collision safety when using custom storage slots.
This contract calculates a specificBridgeStorageLocation
constant and manually references it in_getBridgeStorage()
. While this is a standard pattern for upgradeable contracts, ensure that future revisions do not introduce unexpected storage collisions with inherited state variables.
62-93
: Confirm correct initialization ordering and state setup.
The initializer calls a series of parent initializers (__AccessManaged_init
,__Nonces_init
,__TokenManager_init
) before calling__Bridge_init_unchained
. This is typically sound, but always verify that each parent’s storage layout is finalized before referencing it within subsequent initializers.
489-489
: Double-check the bit shift of 65 for flags.
This code discards the lower 65 bits ofpayload.flags
by shifting right. Confirm that 65 bits is intentional and that it aligns with the defined meaning of the lower bits, especially if there is no separate mask.bridge-evm/test/bridge_tests/BridgeSend.t.sol (3)
340-369
: Fuzz testing coverage is good, but validate extreme bounds.
test_sendingToBridge
usesvm.assume(amountToSend > 0)
, which is helpful. Consider additional coverage for edge cases like extremely large amounts close totype(uint256).max
or zero amounts (though tested in separate revert tests) to ensure exhaustive coverage.
659-686
: Confirm expected revert scenario with a bad fee receiver.
test_revertWhen_send_BadFeeReceiver
verifiesSendFailed
revert when the fee receiver is invalid. Ensure the actual contract setup uses a legitimate fee receiver in production.
[approve]
1-728
: Overall test suite coverage appears robust.
The range of revert tests, normal sends, permit logic, and repeated calls covers the main bridging flows. The approach with Foundry’svm.expectRevert
andmockCall
is thorough.bridge-evm/test/mocks/MockERC20.sol (2)
7-16
: Open mint function is unrestricted.
function mint(address to, uint256 amount) external
allows any sender to mint arbitrary tokens, which is presumably intentional for testing. Confirm that this token is never deployed in production environments without proper access control.
17-21
: Permit functionality integrated correctly.
MockERC20Permit
correctly extendsERC20Permit
and the base mock token. This is a straightforward, valid approach for permit-based testing.bridge-evm/test/bridge_tests/BridgeValidation.t.sol (1)
9-14
: LGTM! Well-structured test case.The test effectively verifies the synchronization of fee validity window between validator and bridge instances.
bridge-evm/test/mocks/sAMB.sol (1)
9-14
: LGTM!The constructor correctly initializes the ERC20 token with the provided name and symbol.
bridge-evm/contracts/Validator.sol (1)
13-25
: LGTM!The initialization logic is well-structured:
- Proper use of the
initializer
modifier to prevent re-initialization.- Correct delegation to the parent contract's initialization.
bridge-evm/test/mocks/MockNonce.sol (2)
8-10
: LGTM!The initialization is properly implemented:
- Correct use of
initializer
modifier.- Proper delegation to parent contract's initialization.
12-34
: LGTM!The nonce operations are well-implemented:
- Clean overloading of functions for different key types.
- Proper delegation to parent contract's internal functions.
- Consistent function signatures across overloads.
bridge-evm/test/Bridge.t.sol (1)
14-21
: LGTM!The contract inheritance is well-structured:
- Clear separation of test concerns through base contracts.
- Proper ordering of inheritance.
bridge-evm/test/PayloadUtils.t.sol (1)
28-70
: Verify the security implications of FFI usage.The test executes external JavaScript code via
vm.ffi
. While this is acceptable for testing, ensure the JavaScript file is properly secured and validated.❌ Verification inconclusive
🏁 Script executed:
#!/bin/bash # Check if the JS file exists and has appropriate permissions ls -l ./test/differential_testing/payload2hash.js # Verify the file content doesn't contain malicious code cat ./test/differential_testing/payload2hash.jsLength of output: 268
Security Concern: Missing External JS File Impedes Verification
- The test in
bridge-evm/test/PayloadUtils.t.sol
callsvm.ffi
with"./test/differential_testing/payload2hash.js"
, but the file is not found in the repository.- Without the existence of the JS file, it is impossible to verify that the external code is properly secured and validated.
- Please verify whether the file was meant to be included. If so, add it under version control and review its content for any potential vulnerabilities tied to FFI usage.
bridge-evm/contracts/interface/IValidation.sol (1)
74-80
:⚠️ Potential issueAdd replay protection to payload validation.
The
validatePayload
function should include nonce or timestamp checks to prevent replay attacks.Consider adding nonce validation:
function validatePayload( SendPayload memory payload, - bytes memory signature + bytes memory signature, + uint256 nonce ) external view - returns (bool isValid); + returns (bool isValid) { + require(!usedNonces[nonce], "Nonce already used"); + // ... rest of validation + }Likely an incorrect or invalid review comment.
bridge-evm/test/ERC20Bridged.t.sol (2)
55-74
: LGTM! Comprehensive test for bridge transfers.The test effectively verifies the token burning mechanism when sending to bridge.
76-99
: LGTM! Well-structured user-to-user transfer test.The test thoroughly validates balances and total supply for user-to-user transfers.
bridge-evm/test/differential_testing/receipt2hash.js (1)
22-23
: Potential overflow in flags bit shift.The right shift by 65 bits on flags might cause issues with large numbers.
❌ Incorrect review comment
🌐 Web query:
What is the maximum safe integer value in JavaScript that can be used with bitwise operations?
💡 Result:
The maximum safe integer value in JavaScript that can be used with bitwise operations is 2³¹ − 1, or 2147483647. This limit arises because JavaScript converts numbers to 32-bit signed integers when applying bitwise operators[1][3][7].
Key Details:
Bitwise Operations:
- JavaScript treats numbers as 32-bit signed integers during bitwise operations (e.g.,
&
,|
,~
,<<
)[1][3][7].- The highest positive value in this format is 2147483647 (binary:
01111111111111111111111111111111
)[9].Why Not Higher?
- Numbers exceeding this range are truncated modulo 2³²[4][6]. For example:
0xaa11223344 // Truncated to a 32-bit integerContrast with General-Purpose Numbers:
- Regular numeric operations support up to 9007199254740991 (
Number.MAX_SAFE_INTEGER
), but this precision does not apply to bitwise operators[5][7].Example:
// Safe within 32-bit range const maxBitwiseSafe = 2147483647; console.log(maxBitwiseSafe << 0); // Output: 2147483647 // Beyond this limit causes unexpected behavior console.log(2147483648 << 0); // Output: -2147483648 (overflow)For exact handling of larger integers in bitwise contexts, use
BigInt
[2][4].Citations:
- 1: https://www.wikitechy.com/tutorials/javascript/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losing-precision
- 2: https://sanori.github.io/2024/01/Handling-Large-Integers-in-JavaScript/
- 3: https://www.tektutorialshub.com/javascript/javascript-number-min-max-safe-values/
- 4: https://8hob.io/posts/bitwise-operations-when-use-them/
- 5: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER?retiredLocale=pl
- 6: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_AND
- 7: https://www.tutorialspoint.com/what-is-javascript-s-highest-integer-value-that-a-number-can-go-to-without-losing-precision
- 8: https://javascript.plainenglish.io/working-with-bits-edbe4daeac6c?gi=34a6a8f9bf9f
- 9: https://blog.logrocket.com/guide-javascript-bitwise-operators/
- 10: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT
Clarification on BigInt Bit Shifting Behavior
The web query result refers to bitwise operations on Number values, which are indeed limited to 32-bit signed integers. However, this limitation does not apply here because the code explicitly converts
flags
into a BigInt. BigInt's bitwise operators (including>>
) work with arbitrarily large integers, so shifting by 65 bits will not “overflow” as it would with 32-bit Number bitwise operations.
- The use of
BigInt(flags) >> 65n
is valid and safe.- The overflow concern based on the maximum safe integer for Numbers is not applicable here.
Likely an incorrect or invalid review comment.
bridge-evm/.gas-snapshot (1)
18-19
: Investigate gas usage variance in fuzz tests.The fuzz tests for token operations show significant variance in gas usage between runs (μ ≠ ~). This could indicate inefficient handling of certain input combinations.
Run the following script to analyze the gas usage patterns:
❌ Verification inconclusive
🏁 Script executed:
#!/bin/bash # Description: Analyze gas usage patterns in fuzz tests # Extract and analyze gas usage patterns rg -A 5 "runs: 256" .gas-snapshot | \ grep -E "μ:|~:" | \ awk '{print $3}' | \ sort -n | \ uniq -cLength of output: 146
Re-run gas usage analysis with the correct file path
The initial script failed to produce output because it was looking for “.gas-snapshot” in the repository root instead of in the “bridge-evm” folder. We need to verify that the file exists at “bridge-evm/.gas-snapshot” and re-run the analysis using that path. Please execute the following script to check for the file and analyze gas usage:#!/bin/bash # Step 1: Locate the .gas-snapshot file fd "\.gas-snapshot$" # Step 2: Analyze gas usage patterns from bridge-evm/.gas-snapshot FILE="bridge-evm/.gas-snapshot" if [ -f "$FILE" ]; then echo "Using file: $FILE" rg -A 5 "runs: 256" "$FILE" | grep -E "μ:|~:" | awk '{print $3}' | sort -n | uniq -c else echo "File not found: $FILE" fiOnce you verify the file’s presence and the proper execution of the analysis, please re-check if the gas usage variance is indeed notable, or if further investigation is required.
bridge-evm/test/bridge_tests/TokenManager.t.sol (1)
34-45
: LGTM! Well-structured test contract setup.The contract is well-organized with proper library imports and utility functions. Good use of OpenZeppelin's EnumerableSet for managing token addresses.
bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md (1)
1-142
: LGTM!The documentation is well-structured with clear descriptions for all functions, events, and errors. The parameter descriptions are comprehensive and provide good context for the validator management functionality.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
14-14: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
20-20: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
35-35: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
59-59: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
81-81: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md (1)
1-129
: LGTM!The documentation is well-structured with clear descriptions and helpful examples for each conversion function. The examples effectively demonstrate the byte order differences between big-endian and little-endian conversions.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~70-~70: A punctuation mark might be missing here.
Context: ...lue|
bytes32|bytes32 value to convert| |
le|
bool`|true if the value is in lit...(AI_EN_LECTOR_MISSING_PUNCTUATION)
[uncategorized] ~119-~119: A punctuation mark might be missing here.
Context: ...ype|Description| |----|----|-----------| |_address
|string
|string value to con...(AI_EN_LECTOR_MISSING_PUNCTUATION)
🪛 markdownlint-cli2 (0.17.2)
16-16: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
22-22: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
39-39: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
45-45: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
66-66: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
73-73: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
80-80: Multiple headings with the same content
null(MD024, no-duplicate-heading)
90-90: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
96-96: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
103-103: Multiple headings with the same content
null(MD024, no-duplicate-heading)
116-116: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
122-122: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/package.json (1)
38-44
: LGTM! Dependencies are well-structured.The dependencies are appropriately configured with specific versions for better stability.
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md (1)
1-459
: LGTM! Well-documented interface.The IBridge interface is thoroughly documented with:
- Clear function descriptions
- Comprehensive error handling
- Well-structured events
- Detailed parameter descriptions
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
17-17: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
44-44: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
53-53: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
60-60: Multiple headings with the same content
null(MD024, no-duplicate-heading)
84-84: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
97-97: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
120-120: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
127-127: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
134-134: Multiple headings with the same content
null(MD024, no-duplicate-heading)
150-150: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
157-157: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
181-181: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
188-188: Multiple headings with the same content
null(MD024, no-duplicate-heading)
199-199: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
205-205: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
212-212: Multiple headings with the same content
null(MD024, no-duplicate-heading)
220-220: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
226-226: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
241-241: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
256-256: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
271-271: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
286-286: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
301-301: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
316-316: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
350-350: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
367-367: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
382-382: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
406-406: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
444-444: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md (1)
1-533
: LGTM! Well-documented interface.The ITokenManager interface is thoroughly documented with:
- Clear function descriptions
- Comprehensive error handling
- Well-structured events
- Detailed parameter descriptions
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
17-17: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
47-47: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
71-71: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
86-86: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
92-92: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
113-113: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
121-121: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
128-128: Multiple headings with the same content
null(MD024, no-duplicate-heading)
141-141: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
148-148: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
168-168: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
192-192: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
198-198: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
224-224: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
233-233: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
248-248: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
254-254: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
269-269: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
275-275: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
290-290: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
296-296: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
312-312: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
326-326: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
341-341: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
355-355: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
372-372: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
386-386: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
400-400: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
423-423: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
437-437: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
451-451: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
465-465: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
479-479: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
493-493: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
507-507: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/broadcast/DeployBridge.s.sol/22040/run-latest.json (2)
47-49
: Verify the Validator proxy initialization parameters.The Validator proxy is initialized with:
- Authority: 0x7ca7fb8f64f998d13eacf00ce6615805fcea3fee
- Payload signer: 0x71ec62addc25bd02effed8785fed3341f4024aa9
- Fee validity window: 0x12c (300 in decimal)
Please verify that:
- The authority address matches the deployed AccessManager
- The fee validity window (300) is appropriate for the network's block time
- The payload signer has proper key management procedures in place
87-89
: Verify the Bridge proxy initialization parameters.The Bridge proxy is initialized with:
- Authority: 0x7ca7fb8f64f998d13eacf00ce6615805fcea3fee
- Token manager: 0x2cf845b49e1c4e5d657fbbf36e97b7b5b7b7b74b
- Validator: 0xdfd1922a449c164e270abe62e12088188e7d9d3e
- Fee amount: 1 ETH (0xde0b6b3a7640000)
Please verify that:
- The validator address matches the previously deployed Validator proxy
- The initial fee amount of 1 ETH is appropriate for the expected transaction volume
- The token manager address is properly configured
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md (1)
40-41
: Review high bit positions for flags.The following flags use high bit positions:
- SHOULD_UNWRAP: 1 << 65
- SEND_NATIVE_TO_RECEIVER: 1 << 66
- SHOULD_RESTAKE: 1 << 67
Verify that:
- The target platforms support uint256 for these high bit positions
- There's no risk of overflow when combining flags
- Gas costs for high bit operations are acceptable
Also applies to: 49-50, 58-59
address[] memory signers = vm.envAddress("VALIDATORS", ","); | ||
for (uint256 i = 0; i < signers.length; i++) { | ||
validator.addValidator(signers[i]); | ||
} |
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.
🛠️ Refactor suggestion
Add validation and error handling for validator addresses.
The current implementation lacks several important safety checks:
- No validation that addresses are not zero addresses
- No checks for duplicate validators
- No error handling for invalid addresses in the environment variable
Consider adding these safety checks:
address[] memory signers = vm.envAddress("VALIDATORS", ",");
for (uint256 i = 0; i < signers.length; i++) {
+ require(signers[i] != address(0), "Zero address not allowed");
+ require(!validator.isValidator(signers[i]), "Duplicate validator");
validator.addValidator(signers[i]);
}
📝 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.
address[] memory signers = vm.envAddress("VALIDATORS", ","); | |
for (uint256 i = 0; i < signers.length; i++) { | |
validator.addValidator(signers[i]); | |
} | |
address[] memory signers = vm.envAddress("VALIDATORS", ","); | |
for (uint256 i = 0; i < signers.length; i++) { | |
require(signers[i] != address(0), "Zero address not allowed"); | |
require(!validator.isValidator(signers[i]), "Duplicate validator"); | |
validator.addValidator(signers[i]); | |
} |
function addToken( | ||
address token, | ||
ExternalTokenUnmapped calldata externalToken_, | ||
bool paused | ||
) | ||
public | ||
virtual | ||
returns (bool success); | ||
``` |
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.
🛠️ Refactor suggestion
Document access control and validation requirements.
The token management functions (addToken, removeToken, etc.) have significant security implications but lack documentation about:
- Required access control
- Token validation requirements
- Potential risks and security considerations
Consider adding a "Security Considerations" section that details:
- Who can call these functions
- What validation is performed
- Potential risks of token mapping
Also applies to: 107-115, 199-204
function _wrap(uint256 amount) internal; | ||
``` |
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.
🛠️ Refactor suggestion
Enhance documentation for wrapping/unwrapping functionality.
The _wrap
and _unwrap
functions handle critical token conversions but lack important details:
- Relationship between AMB and SAMB tokens
- Potential failure scenarios
- Requirements for successful wrapping/unwrapping
Add documentation about:
- Token conversion ratios
- Error handling
- Edge cases (e.g., insufficient balance)
Also applies to: 274-275
function __Bridge_init( | ||
address authority_, | ||
address SAMB_, | ||
IValidation validator_, | ||
address payable feeReceiver_, | ||
uint256 nativeSendAmount_ | ||
) | ||
internal | ||
onlyInitializing; | ||
``` |
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.
🛠️ Refactor suggestion
Document initialization requirements and constraints.
The bridge initialization functions lack critical details about:
- Parameter validation requirements
- Order of initialization
- Upgrade considerations
Add documentation covering:
- Valid parameter ranges/constraints
- Required setup sequence
- Implications for contract upgrades
Also applies to: 44-51
function send( | ||
bytes32 recipient, | ||
uint256 chainTo, | ||
SendPayload calldata payload, | ||
bytes calldata payloadSignature | ||
) | ||
external | ||
payable | ||
override | ||
returns (FullReceipt memory receipt); | ||
``` |
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.
Document cross-chain security model and trust assumptions.
The cross-chain operations (send/claim) lack documentation about critical security aspects:
- Trust assumptions for validators
- Receipt validation process
- Double-spend prevention
Add comprehensive security documentation covering:
- Validator selection and trust model
- Receipt verification process
- Attack vectors and mitigations
- Recovery procedures for failed transfers
Also applies to: 771-779, 803-811
bridge-evm/test/Validator.t.sol
Outdated
function signPayload( | ||
BridgeTypes.SendPayload memory payload, | ||
Signer memory signer | ||
) | ||
internal | ||
pure | ||
returns (bytes memory signature) | ||
{ | ||
bytes32 digest = payload.toHash(); | ||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer.PK, digest); | ||
signature = abi.encodePacked(r, s, v); | ||
return signature; | ||
} |
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.
🛠️ Refactor suggestion
Consider adding signature malleability check.
The signPayload
function should verify that the signature is not malleable.
function signPayload(
BridgeTypes.SendPayload memory payload,
Signer memory signer
)
internal
pure
returns (bytes memory signature)
{
bytes32 digest = payload.toHash();
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer.PK, digest);
+ // Check for signature malleability
+ require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
+ "ECDSA: invalid signature 's' value");
signature = abi.encodePacked(r, s, v);
return signature;
}
📝 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.
function signPayload( | |
BridgeTypes.SendPayload memory payload, | |
Signer memory signer | |
) | |
internal | |
pure | |
returns (bytes memory signature) | |
{ | |
bytes32 digest = payload.toHash(); | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer.PK, digest); | |
signature = abi.encodePacked(r, s, v); | |
return signature; | |
} | |
function signPayload( | |
BridgeTypes.SendPayload memory payload, | |
Signer memory signer | |
) | |
internal | |
pure | |
returns (bytes memory signature) | |
{ | |
bytes32 digest = payload.toHash(); | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer.PK, digest); | |
// Check for signature malleability | |
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, | |
"ECDSA: invalid signature 's' value"); | |
signature = abi.encodePacked(r, s, v); | |
return signature; | |
} |
bridge-evm/test/Validator.t.sol
Outdated
function signReceipt(BridgeTypes.MiniReceipt memory receipt) | ||
internal | ||
returns (bytes memory signature) | ||
{ | ||
bytes32 digest = receipt.toHash(); | ||
for (uint256 i = 0; i < signers.length; i++) { | ||
validatorInstance.addValidator(signers[i].Address); | ||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].PK, digest); | ||
bytes memory signerSignature = abi.encodePacked(r, s, v); // note the order here is different from line above. | ||
signature = bytes.concat(signature, signerSignature); | ||
} | ||
return signature; | ||
} |
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.
🛠️ Refactor suggestion
Add validation for maximum number of signers.
The signReceipt
function should validate the maximum number of signers to prevent excessive gas consumption.
function signReceipt(BridgeTypes.MiniReceipt memory receipt)
internal
returns (bytes memory signature)
{
bytes32 digest = receipt.toHash();
+ require(signers.length <= 100, "Too many signers"); // Adjust limit as needed
for (uint256 i = 0; i < signers.length; i++) {
validatorInstance.addValidator(signers[i].Address);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].PK, digest);
bytes memory signerSignature = abi.encodePacked(r, s, v);
signature = bytes.concat(signature, signerSignature);
}
return signature;
}
📝 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.
function signReceipt(BridgeTypes.MiniReceipt memory receipt) | |
internal | |
returns (bytes memory signature) | |
{ | |
bytes32 digest = receipt.toHash(); | |
for (uint256 i = 0; i < signers.length; i++) { | |
validatorInstance.addValidator(signers[i].Address); | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].PK, digest); | |
bytes memory signerSignature = abi.encodePacked(r, s, v); // note the order here is different from line above. | |
signature = bytes.concat(signature, signerSignature); | |
} | |
return signature; | |
} | |
function signReceipt(BridgeTypes.MiniReceipt memory receipt) | |
internal | |
returns (bytes memory signature) | |
{ | |
bytes32 digest = receipt.toHash(); | |
require(signers.length <= 100, "Too many signers"); // Adjust limit as needed | |
for (uint256 i = 0; i < signers.length; i++) { | |
validatorInstance.addValidator(signers[i].Address); | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].PK, digest); | |
bytes memory signerSignature = abi.encodePacked(r, s, v); // note the order here is different from line above. | |
signature = bytes.concat(signature, signerSignature); | |
} | |
return signature; | |
} |
# IWrapped | ||
[Git Source](https://github.com/ambrosus/token-bridge/blob/2704f133ac810fd32e38846890ea517279600f52/contracts/interface/IWrapped.sol) | ||
|
||
**Inherits:** | ||
IERC20 | ||
|
||
|
||
## Functions | ||
### deposit | ||
|
||
Deposit tokens to the contract (a.k.a wrap tokens) | ||
|
||
*converts msg.value amount to ERC20 tokens with the same amount* | ||
|
||
|
||
```solidity | ||
function deposit() external payable; | ||
``` | ||
|
||
### withdraw | ||
|
||
Withdraw tokens from the contract (a.k.a unwrap tokens) | ||
|
||
*converts ERC20 tokens to native currency with the same amount* | ||
|
||
|
||
```solidity | ||
function withdraw(uint256 amount) external; | ||
``` | ||
**Parameters** | ||
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`amount`|`uint256`|amount of tokens to withdraw| | ||
|
||
|
||
## Events | ||
### Deposit | ||
|
||
```solidity | ||
event Deposit(address indexed dst, uint256 amount); | ||
``` | ||
|
||
### Withdrawal | ||
|
||
```solidity | ||
event Withdrawal(address indexed src, uint256 amount); | ||
``` |
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.
🛠️ Refactor suggestion
Add security considerations section.
The interface documentation should include security considerations regarding:
- Potential reentrancy risks during deposit/withdraw
- Importance of checking return values
- Implications of wrapping/unwrapping native currency
🧰 Tools
🪛 LanguageTool
[uncategorized] ~11-~11: The abbreviation/initialism is missing a period after the last letter.
Context: ...eposit Deposit tokens to the contract (a.k.a wrap tokens) *converts msg.value amoun...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~22-~22: The abbreviation/initialism is missing a period after the last letter.
Context: ...raw Withdraw tokens from the contract (a.k.a unwrap tokens) *converts ERC20 tokens ...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~34-~34: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...-|----|-----------| |amount
|uint256
|amount of tokens to withdraw| ## Events ### ...
(AMOUNTOF_TO_NUMBEROF)
🪛 markdownlint-cli2 (0.17.2)
13-13: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
24-24: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
30-30: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
### _update | ||
|
||
*Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` | ||
(or `to`) is the `bridge` address. (This is the only difference from the {ERC20} implementation.) | ||
Emits a {Transfer} event.* | ||
|
||
|
||
```solidity | ||
function _update(address from, address to, uint256 value) internal override; | ||
``` |
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.
🛠️ Refactor suggestion
Add security warnings for _update function.
The documentation should include warnings about:
- Potential risks of minting/burning operations
- Access control requirements
- Validation of bridge address
🧰 Tools
🪛 LanguageTool
[uncategorized] ~80-~80: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...ct| ### _update *Transfers a value
amount of tokens from from
to to
, or alter...
(AMOUNTOF_TO_NUMBEROF)
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: 9
♻️ Duplicate comments (3)
bridge-evm/script/DeployerBase.s.sol (2)
46-79
:⚠️ Potential issueFix sender check in
setAuthorityAdmin
.The function checks
adminCandidate
twice instead of verifying the sender's admin status.- (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + (bool isSenderAdmin,) = + authority.hasRole(authority.ADMIN_ROLE(), msg.sender);
81-101
:⚠️ Potential issueFix sender check in
removeAuthorityAdmin
.Similar to
setAuthorityAdmin
, this function also checksadminCandidate
instead of verifying the sender's admin status.- (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + (bool isSenderAdmin,) = + authority.hasRole(authority.ADMIN_ROLE(), msg.sender);bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol (1)
76-87
:⚠️ Potential issueMissing access control.
addToken
ispublic
and not protected by a modifier restricting calls to an owner or authority. This could be a security issue if arbitrary addresses can call it.
🧹 Nitpick comments (9)
bridge-evm/script/DeployerBase.s.sol (2)
26-30
: Add validation for private key.Consider adding validation to ensure the private key is not zero or empty.
function getDeployer() public returns (VmSafe.Wallet memory) { uint256 deployerPK = vm.envUint("PRIVATE_KEY"); + require(deployerPK != 0, "Invalid private key"); deployer = vm.createWallet(deployerPK); return deployer; }
180-220
: Consider emitting events for contract deployments.For better traceability, consider emitting events when contracts are deployed through getter functions.
+ event ContractDeployed(string name, address addr); function getAuthority() public returns (AccessManager) { (bool deployed, address authorityAddress) = checkDeployed("AccessManager"); if (deployed) { authority = AccessManager(authorityAddress); } else { authority = deployAuthority(); + emit ContractDeployed("AccessManager", address(authority)); } return authority; }bridge-evm/contracts/token/ERC20Bridged.sol (1)
108-120
: Emit events for blacklist changes
While you have a mechanism to blacklist addresses, consider emitting events on addition/removal to facilitate easier off-chain tracking and audits.function addBlacklist(address account) public restricted { BridgedERC20Storage storage $ = _getERC20AdditionalStorage(); $._blacklist[account] = true; + emit BlacklistAdded(account); } function removeBlacklist(address account) public restricted { BridgedERC20Storage storage $ = _getERC20AdditionalStorage(); delete $._blacklist[account]; + emit BlacklistRemoved(account); }bridge-evm/contracts/token/TokenBeacon.sol (2)
4-5
: Remove unused import
TheAccessManaged
import appears unused. If not necessary, consider removing it for clarity.
7-9
: Confirm ownership workflow
Currently, ownership logic in the constructor is minimal and relies on a custom variant ofUpgradeableBeacon
. Verify that the intended “owner” can control upgrades. Otherwise, consider adding additional access checks or restricting calls to update the beacon.bridge-evm/script/DeployTokenBeacon.s.sol (1)
7-9
: Remove unused imports
AccessManager
andStrings
are not referenced in this script, so consider cleaning them up.bridge-evm/test/bridge_tests/BridgeBase.t.sol (1)
327-327
: Address FIXME comment regarding mapped external token removal.The FIXME comment indicates that mapped external tokens cannot be removed. This limitation should be addressed or documented.
Would you like me to help implement a solution for removing mapped external tokens or create an issue to track this task?
bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol (2)
48-60
: Add storage slot validation.The storage location is hardcoded but lacks runtime validation to ensure it matches the expected namespace.
Add validation in the constructor:
function _getBridgeStorage() private pure returns (BridgeStorage storage $) { + bytes32 slot = keccak256( + abi.encode(uint256(keccak256("airdao.bridge.main.storage")) - 1) + ) & ~bytes32(uint256(0xff)); + require( + slot == BridgeStorageLocation, + "BridgeUpgradeable: invalid storage slot" + ); assembly { $.slot := BridgeStorageLocation } }
124-219
: Add events for token management operations.While the functions are properly restricted, they don't emit events for important state changes, making it difficult to track token management operations off-chain.
Consider adding events for token management operations:
+event TokenAdded(address indexed token, bytes32 indexed externalToken, bool paused); +event TokenRemoved(address indexed token); function addToken( address token, ExternalTokenUnmapped calldata externalToken_, bool paused ) public override restricted returns (bool success) { - return super.addToken(token, externalToken_, paused); + success = super.addToken(token, externalToken_, paused); + if (success) { + emit TokenAdded(token, externalToken_.externalTokenAddress, paused); + } + return success; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
bridge-evm/.gas-snapshot
(1 hunks)bridge-evm/contracts/Bridge.sol
(1 hunks)bridge-evm/contracts/token/ERC20Bridged.sol
(1 hunks)bridge-evm/contracts/token/TokenBeacon.sol
(1 hunks)bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol
(1 hunks)bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol
(1 hunks)bridge-evm/script/DeployBridge.s.sol
(1 hunks)bridge-evm/script/DeployTokenBeacon.s.sol
(1 hunks)bridge-evm/script/DeployerBase.s.sol
(1 hunks)bridge-evm/test/ERC20Bridged.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeBase.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeRestricted.t.sol
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- bridge-evm/script/DeployBridge.s.sol
- bridge-evm/test/ERC20Bridged.t.sol
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
🔇 Additional comments (13)
bridge-evm/.gas-snapshot (2)
1-111
: Excellent test coverage across core functionality!The test suite demonstrates:
- Comprehensive coverage of core bridge operations
- Extensive fuzz testing with 256 runs per test
- Strong focus on security with numerous revert cases
- Good mix of unit tests and property-based tests
82-84
: Good gas efficiency in payload and receipt hashing.The payload and receipt hashing operations show consistent and reasonable gas usage:
test_fuzz_payload2hash
: ~130k gastest_fuzz_fullReceipt2hash
: ~173k gastest_fuzz_miniReceipt2hash
: ~131k gasThe implementation demonstrates efficient hashing operations with stable gas consumption across different input sizes.
bridge-evm/script/DeployerBase.s.sol (1)
1-25
: LGTM! Contract setup and imports are well-structured.The contract properly imports required dependencies and declares necessary state variables.
bridge-evm/contracts/token/ERC20Bridged.sol (3)
63-65
: Validate nonzero bridge address
Please consider enforcing a non-zero address to prevent accidental deployments without a valid bridge.function __ERC20Bridged_init_unchained(uint8 decimals_, address bridge_) internal onlyInitializing { BridgedERC20Storage storage $ = _getERC20AdditionalStorage(); $._decimals = decimals_; + require(bridge_ != address(0), "Bridge address cannot be zero"); $._bridge = bridge_; }
128-152
: Bridging logic looks solid
Your mint/burn approach is well-structured: tokens sent from the bridge address are minted, and tokens sent to the bridge address are burned. The blacklist check ensures restricted addresses cannot interact.
141-142
: Verify custom error definition
You are usingERC20InvalidReceiver(address)
, but it is not declared within this contract. Confirm whether it comes from an inherited contract or if it needs to be defined here.❌ Verification inconclusive
🏁 Script executed:
#!/bin/bash ast-grep --pattern $'error ERC20InvalidReceiver($_);'Length of output: 54
Missing ERC20InvalidReceiver custom error declaration detected
The repository search did not locate any declaration for
ERC20InvalidReceiver(address)
, neither in this contract nor in any inherited files based on our available searches. This indicates that either the error is meant to be defined within the contract (or an imported one) and currently is missing, or the intended inheritance is incomplete. Please verify the design intent and add an appropriate definition if needed.bridge-evm/script/DeployTokenBeacon.s.sol (1)
13-24
: Deployment logic confirmed
The deployment flow and conditional redeployment checks look correct and align with Foundry best practices.bridge-evm/contracts/Bridge.sol (2)
1-7
: LGTM! Clean and minimal imports.The imports are well-organized and include only the necessary dependencies.
8-32
: LGTM! Well-structured upgradeable contract.The contract follows best practices for upgradeable contracts:
- Inherits from
BridgeUpgradeable
- Properly implements the
initialize
function with theinitializer
modifier- Well-documented parameters using NatSpec comments
- Correctly delegates initialization to the parent contract
bridge-evm/test/bridge_tests/BridgeRestricted.t.sol (4)
33-47
: LGTM! Comprehensive initialization test.The test properly verifies that the contract cannot be initialized twice, checking both validator and bridge instances.
49-58
: LGTM! Thorough fee receiver management tests.The tests cover both successful and unauthorized fee receiver changes, ensuring proper access control and event emissions.
Also applies to: 60-69
71-80
: LGTM! Complete native send amount management tests.The tests verify both successful and unauthorized native send amount changes, including event emissions and value updates.
Also applies to: 82-91
93-105
: LGTM! Robust validator management tests.The tests thoroughly check validator changes and access control, including event emissions and state updates.
Also applies to: 107-117
bridge-evm/.gas-snapshot
Outdated
BridgeTest:test_claim_withFullReceipt(uint256) (runs: 256, μ: 619789, ~: 620389) | ||
BridgeTest:test_claim_withMiniReceipt(uint256) (runs: 256, μ: 617692, ~: 618292) | ||
BridgeTest:test_claim_withSendNativeFlag(uint256) (runs: 256, μ: 663824, ~: 664424) | ||
BridgeTest:test_claim_wrapped(uint256) (runs: 256, μ: 458691, ~: 458691) | ||
BridgeTest:test_claim_wrapped_with_unwrap(uint256) (runs: 256, μ: 353067, ~: 353772) |
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.
🛠️ Refactor suggestion
Consider optimizing high gas usage in claim operations.
The claim operations are consuming significant gas:
test_claim_withFullReceipt
: ~620k gastest_claim_withMiniReceipt
: ~618k gastest_claim_withSendNativeFlag
: ~664k gas
Consider implementing the following optimizations:
- Use packed storage layouts to reduce storage operations
- Batch operations where possible
- Consider using minimal proxy pattern for bridged tokens
BridgeTest:test_sendingToBridge(bool,uint256) (runs: 256, μ: 490614, ~: 501839) | ||
BridgeTest:test_sendingToBridge_multiple(uint256) (runs: 256, μ: 1046389, ~: 1046389) |
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.
🛠️ Refactor suggestion
Optimize multiple bridge send operations.
The send operations are gas-intensive:
test_sendingToBridge_multiple
: ~1046k gas
This could potentially hit block gas limits on some networks.
Consider implementing batching mechanisms or splitting large transfers into smaller chunks to reduce gas costs and prevent hitting block gas limits.
bridge-evm/script/DeployerBase.s.sol
Outdated
|
||
function deployBridge() public returns (Bridge) { | ||
address wrappedToken = vm.envAddress("WRAPPED_TOKEN"); | ||
address payable feeReceiver = | ||
payable(vm.envOr("FEE_RECEIVER", address(0))); | ||
uint256 nativeSendAmount = vm.envOr("NATIVE_SEND_AMOUNT", uint256(0)); | ||
address payable proxy = payable( | ||
address( | ||
Upgrades.deployUUPSProxy( | ||
"Bridge.sol", | ||
abi.encodeCall( | ||
Bridge.initialize, | ||
( | ||
address(authority), | ||
address(tokenBeacon), | ||
wrappedToken, | ||
validator, | ||
feeReceiver, | ||
nativeSendAmount | ||
) | ||
) | ||
) | ||
) | ||
); | ||
bridge = Bridge(proxy); | ||
console.log("Bridge deployed at:", address(bridge)); | ||
console.log( | ||
" Implementation address:", | ||
Upgrades.getImplementationAddress(proxy) | ||
); | ||
return bridge; | ||
} |
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.
🛠️ Refactor suggestion
Add validation for dependent contracts in deployBridge
.
The function should verify that required contracts (authority, tokenBeacon, validator) are properly initialized before deployment.
function deployBridge() public returns (Bridge) {
+ require(address(authority) != address(0), "Authority not initialized");
+ require(address(tokenBeacon) != address(0), "TokenBeacon not initialized");
+ require(address(validator) != address(0), "Validator not initialized");
address wrappedToken = vm.envAddress("WRAPPED_TOKEN");
address payable feeReceiver =
payable(vm.envOr("FEE_RECEIVER", address(0)));
📝 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.
function deployBridge() public returns (Bridge) { | |
address wrappedToken = vm.envAddress("WRAPPED_TOKEN"); | |
address payable feeReceiver = | |
payable(vm.envOr("FEE_RECEIVER", address(0))); | |
uint256 nativeSendAmount = vm.envOr("NATIVE_SEND_AMOUNT", uint256(0)); | |
address payable proxy = payable( | |
address( | |
Upgrades.deployUUPSProxy( | |
"Bridge.sol", | |
abi.encodeCall( | |
Bridge.initialize, | |
( | |
address(authority), | |
address(tokenBeacon), | |
wrappedToken, | |
validator, | |
feeReceiver, | |
nativeSendAmount | |
) | |
) | |
) | |
) | |
); | |
bridge = Bridge(proxy); | |
console.log("Bridge deployed at:", address(bridge)); | |
console.log( | |
" Implementation address:", | |
Upgrades.getImplementationAddress(proxy) | |
); | |
return bridge; | |
} | |
function deployBridge() public returns (Bridge) { | |
require(address(authority) != address(0), "Authority not initialized"); | |
require(address(tokenBeacon) != address(0), "TokenBeacon not initialized"); | |
require(address(validator) != address(0), "Validator not initialized"); | |
address wrappedToken = vm.envAddress("WRAPPED_TOKEN"); | |
address payable feeReceiver = | |
payable(vm.envOr("FEE_RECEIVER", address(0))); | |
uint256 nativeSendAmount = vm.envOr("NATIVE_SEND_AMOUNT", uint256(0)); | |
address payable proxy = payable( | |
address( | |
Upgrades.deployUUPSProxy( | |
"Bridge.sol", | |
abi.encodeCall( | |
Bridge.initialize, | |
( | |
address(authority), | |
address(tokenBeacon), | |
wrappedToken, | |
validator, | |
feeReceiver, | |
nativeSendAmount | |
) | |
) | |
) | |
) | |
); | |
bridge = Bridge(proxy); | |
console.log("Bridge deployed at:", address(bridge)); | |
console.log( | |
" Implementation address:", | |
Upgrades.getImplementationAddress(proxy) | |
); | |
return bridge; | |
} |
function test_add_new_role_to_call_bridge() public { | ||
uint64 bridgeRoleID = 1; | ||
bytes4[] memory selectors = new bytes4[](3); | ||
selectors[0] = BridgeUpgradeable.setFeeReceiver.selector; | ||
selectors[1] = BridgeUpgradeable.setNativeSendAmount.selector; | ||
selectors[2] = BridgeUpgradeable.setValidator.selector; | ||
authority.setTargetFunctionRole( | ||
address(bridgeInstance), selectors, bridgeRoleID | ||
); | ||
authority.grantRole(bridgeRoleID, bob, 0); | ||
vm.startPrank(bob); | ||
bridgeInstance.setFeeReceiver(payable(alice)); | ||
assertEq(bridgeInstance.feeReceiver(), payable(alice)); | ||
bridgeInstance.setNativeSendAmount(2 ether); | ||
assertEq(bridgeInstance.nativeSendAmount(), 2 ether); | ||
bridgeInstance.setValidator(Validator(address(0x0))); | ||
ITokenManager.ExternalTokenUnmapped memory extToken = ITokenManager | ||
.ExternalTokenUnmapped({ | ||
externalTokenAddress: bytes32("SOLANA_TOKEN"), | ||
decimals: 6 | ||
}); | ||
vm.expectRevert( | ||
abi.encodeWithSelector( | ||
IAccessManaged.AccessManagedUnauthorized.selector, bob | ||
), | ||
7 | ||
); | ||
bridgeInstance.addToken(address(wrappedToken), extToken); | ||
bridgeInstance.removeToken(address(wrappedToken)); | ||
bridgeInstance.deployExternalTokenERC20( | ||
extToken, "Wrapped Solana", "wSOL", 18 | ||
); | ||
bridgeInstance.pauseToken(address(wrappedToken)); | ||
bridgeInstance.unpauseToken(address(wrappedToken)); | ||
bridgeInstance.mapExternalToken(extToken, address(wrappedToken)); | ||
bridgeInstance.unmapExternalToken(bytes32("SOLANA_TOKEN")); | ||
vm.stopPrank(); | ||
} |
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.
🛠️ Refactor suggestion
Add assertions for unauthorized token operations.
The test adds a new role for bridge operations but doesn't assert that the unauthorized token operations actually revert. The test should verify that the operations fail with the expected error.
Apply this diff to add assertions:
bridgeInstance.setValidator(Validator(address(0x0)));
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IAccessManaged.AccessManagedUnauthorized.selector, bob
+ )
+ );
bridgeInstance.addToken(address(wrappedToken), extToken);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IAccessManaged.AccessManagedUnauthorized.selector, bob
+ )
+ );
bridgeInstance.removeToken(address(wrappedToken));
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IAccessManaged.AccessManagedUnauthorized.selector, bob
+ )
+ );
bridgeInstance.deployExternalTokenERC20(
extToken, "Wrapped Solana", "wSOL", 18
);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IAccessManaged.AccessManagedUnauthorized.selector, bob
+ )
+ );
bridgeInstance.pauseToken(address(wrappedToken));
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IAccessManaged.AccessManagedUnauthorized.selector, bob
+ )
+ );
bridgeInstance.unpauseToken(address(wrappedToken));
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IAccessManaged.AccessManagedUnauthorized.selector, bob
+ )
+ );
bridgeInstance.mapExternalToken(extToken, address(wrappedToken));
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IAccessManaged.AccessManagedUnauthorized.selector, bob
+ )
+ );
bridgeInstance.unmapExternalToken(bytes32("SOLANA_TOKEN"));
Committable suggestion skipped: line range outside the PR's diff.
// authority set to 0x0 to premissionless token | ||
return _deployExternalTokenERC20(address(0), externalToken_, name, symbol, decimals); |
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.
Reconsider using zero address for permissionless tokens.
Setting the authority to address(0)
for permissionless tokens might lead to security issues as it bypasses access control. Consider implementing a more controlled approach for managing token permissions.
function __Bridge_init( | ||
address authority_, | ||
address tokenBeacon_, | ||
address SAMB_, | ||
IValidation validator_, | ||
address payable feeReceiver_, | ||
uint256 nativeSendAmount_ | ||
) | ||
internal | ||
onlyInitializing | ||
{ | ||
__AccessManaged_init(authority_); | ||
__Nonces_init(); | ||
__TokenManager_init(tokenBeacon_, address(this), SAMB_); | ||
__Bridge_init_unchained(validator_, feeReceiver_, nativeSendAmount_); | ||
} | ||
|
||
function __Bridge_init_unchained( | ||
IValidation validator_, | ||
address payable feeReceiver_, | ||
uint256 nativeSendAmount_ | ||
) | ||
internal | ||
onlyInitializing | ||
{ | ||
BridgeStorage storage $ = _getBridgeStorage(); | ||
$.validator = validator_; | ||
$.feeReceiver = feeReceiver_; | ||
$.nativeSendAmount = nativeSendAmount_; | ||
emit ValidatorChanged(msg.sender, address(validator_)); | ||
emit FeeReceiverChanged(msg.sender, feeReceiver_); | ||
emit NativeSendAmountChanged(msg.sender, nativeSendAmount_); | ||
} |
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.
Add zero-address validation in initialization.
The initialization functions don't validate critical addresses, which could lead to contract lockup if set to zero.
Add validation:
function __Bridge_init_unchained(
IValidation validator_,
address payable feeReceiver_,
uint256 nativeSendAmount_
)
internal
onlyInitializing
{
+ require(
+ address(validator_) != address(0),
+ "BridgeUpgradeable: validator is zero address"
+ );
+ require(
+ feeReceiver_ != address(0),
+ "BridgeUpgradeable: feeReceiver is zero address"
+ );
BridgeStorage storage $ = _getBridgeStorage();
$.validator = validator_;
$.feeReceiver = feeReceiver_;
$.nativeSendAmount = nativeSendAmount_;
emit ValidatorChanged(msg.sender, address(validator_));
emit FeeReceiverChanged(msg.sender, feeReceiver_);
emit NativeSendAmountChanged(msg.sender, nativeSendAmount_);
}
📝 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.
function __Bridge_init( | |
address authority_, | |
address tokenBeacon_, | |
address SAMB_, | |
IValidation validator_, | |
address payable feeReceiver_, | |
uint256 nativeSendAmount_ | |
) | |
internal | |
onlyInitializing | |
{ | |
__AccessManaged_init(authority_); | |
__Nonces_init(); | |
__TokenManager_init(tokenBeacon_, address(this), SAMB_); | |
__Bridge_init_unchained(validator_, feeReceiver_, nativeSendAmount_); | |
} | |
function __Bridge_init_unchained( | |
IValidation validator_, | |
address payable feeReceiver_, | |
uint256 nativeSendAmount_ | |
) | |
internal | |
onlyInitializing | |
{ | |
BridgeStorage storage $ = _getBridgeStorage(); | |
$.validator = validator_; | |
$.feeReceiver = feeReceiver_; | |
$.nativeSendAmount = nativeSendAmount_; | |
emit ValidatorChanged(msg.sender, address(validator_)); | |
emit FeeReceiverChanged(msg.sender, feeReceiver_); | |
emit NativeSendAmountChanged(msg.sender, nativeSendAmount_); | |
} | |
function __Bridge_init_unchained( | |
IValidation validator_, | |
address payable feeReceiver_, | |
uint256 nativeSendAmount_ | |
) | |
internal | |
onlyInitializing | |
{ | |
require( | |
address(validator_) != address(0), | |
"BridgeUpgradeable: validator is zero address" | |
); | |
require( | |
feeReceiver_ != address(0), | |
"BridgeUpgradeable: feeReceiver is zero address" | |
); | |
BridgeStorage storage $ = _getBridgeStorage(); | |
$.validator = validator_; | |
$.feeReceiver = feeReceiver_; | |
$.nativeSendAmount = nativeSendAmount_; | |
emit ValidatorChanged(msg.sender, address(validator_)); | |
emit FeeReceiverChanged(msg.sender, feeReceiver_); | |
emit NativeSendAmountChanged(msg.sender, nativeSendAmount_); | |
} |
function _sendFee(uint256 amount) private { | ||
(bool sent,) = feeReceiver().call{value: amount}(""); | ||
if (!sent) { | ||
revert SendFailed(); | ||
} | ||
} |
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.
Add balance checks for native currency transfers.
The _sendFee
function doesn't verify if the contract has sufficient native currency balance before the transfer.
Add balance validation:
function _sendFee(uint256 amount) private {
+ require(
+ address(this).balance >= amount,
+ "BridgeUpgradeable: insufficient native currency"
+ );
(bool sent,) = feeReceiver().call{value: amount}("");
if (!sent) {
revert SendFailed();
}
}
📝 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.
function _sendFee(uint256 amount) private { | |
(bool sent,) = feeReceiver().call{value: amount}(""); | |
if (!sent) { | |
revert SendFailed(); | |
} | |
} | |
function _sendFee(uint256 amount) private { | |
require( | |
address(this).balance >= amount, | |
"BridgeUpgradeable: insufficient native currency" | |
); | |
(bool sent,) = feeReceiver().call{value: amount}(""); | |
if (!sent) { | |
revert SendFailed(); | |
} | |
} |
abstract contract BridgeUpgradeable is | ||
IBridge, | ||
Initializable, | ||
AccessManagedUpgradeable, | ||
NoncesUpgradeable, | ||
TokenManagerUpgradeable | ||
{ |
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.
Add storage gaps for safe upgradeability.
The contract inherits from multiple upgradeable contracts but doesn't include a storage gap. This could lead to storage collision issues in future upgrades.
Add a storage gap at the end of the contract:
abstract contract BridgeUpgradeable is
IBridge,
Initializable,
AccessManagedUpgradeable,
NoncesUpgradeable,
TokenManagerUpgradeable
{
+ // gap for upgrade safety
+ uint256[50] private __gap;
📝 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.
abstract contract BridgeUpgradeable is | |
IBridge, | |
Initializable, | |
AccessManagedUpgradeable, | |
NoncesUpgradeable, | |
TokenManagerUpgradeable | |
{ | |
abstract contract BridgeUpgradeable is | |
IBridge, | |
Initializable, | |
AccessManagedUpgradeable, | |
NoncesUpgradeable, | |
TokenManagerUpgradeable | |
{ | |
// gap for upgrade safety | |
uint256[50] private __gap; |
function _transferClaim( | ||
uint256 flags, | ||
address token, | ||
uint256 amount, | ||
address receiver | ||
) | ||
private | ||
{ | ||
if (pausedTokens(token)) { | ||
revert TokenIsPaused(token); | ||
} | ||
bool unlocked = false; | ||
if (token == samb() && flags & BridgeFlags.SHOULD_UNWRAP != 0) { | ||
_unwrap(amount); | ||
(unlocked,) = payable(receiver).call{value: amount}(""); | ||
} else { | ||
unlocked = IERC20(token).transfer(receiver, amount); | ||
} | ||
if (!unlocked) { | ||
revert TransferFailed(); | ||
} | ||
BridgeStorage storage $ = _getBridgeStorage(); | ||
if (flags & BridgeFlags.SEND_NATIVE_TO_RECEIVER != 0) { | ||
(bool sent,) = payable(receiver).call{value: $.nativeSendAmount}(""); | ||
if (!sent) { | ||
revert SendFailed(); | ||
} | ||
} | ||
} |
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.
Add reentrancy protection for token transfers.
The _transferClaim
function performs external calls before state changes, making it vulnerable to reentrancy attacks.
Apply the checks-effects-interactions pattern:
function _transferClaim(
uint256 flags,
address token,
uint256 amount,
address receiver
)
private
{
if (pausedTokens(token)) {
revert TokenIsPaused(token);
}
+ BridgeStorage storage $ = _getBridgeStorage();
bool unlocked = false;
if (token == samb() && flags & BridgeFlags.SHOULD_UNWRAP != 0) {
_unwrap(amount);
(unlocked,) = payable(receiver).call{value: amount}("");
} else {
unlocked = IERC20(token).transfer(receiver, amount);
}
if (!unlocked) {
revert TransferFailed();
}
- BridgeStorage storage $ = _getBridgeStorage();
if (flags & BridgeFlags.SEND_NATIVE_TO_RECEIVER != 0) {
(bool sent,) = payable(receiver).call{value: $.nativeSendAmount}("");
if (!sent) {
revert SendFailed();
}
}
}
📝 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.
function _transferClaim( | |
uint256 flags, | |
address token, | |
uint256 amount, | |
address receiver | |
) | |
private | |
{ | |
if (pausedTokens(token)) { | |
revert TokenIsPaused(token); | |
} | |
bool unlocked = false; | |
if (token == samb() && flags & BridgeFlags.SHOULD_UNWRAP != 0) { | |
_unwrap(amount); | |
(unlocked,) = payable(receiver).call{value: amount}(""); | |
} else { | |
unlocked = IERC20(token).transfer(receiver, amount); | |
} | |
if (!unlocked) { | |
revert TransferFailed(); | |
} | |
BridgeStorage storage $ = _getBridgeStorage(); | |
if (flags & BridgeFlags.SEND_NATIVE_TO_RECEIVER != 0) { | |
(bool sent,) = payable(receiver).call{value: $.nativeSendAmount}(""); | |
if (!sent) { | |
revert SendFailed(); | |
} | |
} | |
} | |
function _transferClaim( | |
uint256 flags, | |
address token, | |
uint256 amount, | |
address receiver | |
) | |
private | |
{ | |
if (pausedTokens(token)) { | |
revert TokenIsPaused(token); | |
} | |
BridgeStorage storage $ = _getBridgeStorage(); | |
bool unlocked = false; | |
if (token == samb() && flags & BridgeFlags.SHOULD_UNWRAP != 0) { | |
_unwrap(amount); | |
(unlocked,) = payable(receiver).call{value: amount}(""); | |
} else { | |
unlocked = IERC20(token).transfer(receiver, amount); | |
} | |
if (!unlocked) { | |
revert TransferFailed(); | |
} | |
if (flags & BridgeFlags.SEND_NATIVE_TO_RECEIVER != 0) { | |
(bool sent,) = payable(receiver).call{value: $.nativeSendAmount}(""); | |
if (!sent) { | |
revert SendFailed(); | |
} | |
} | |
} |
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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: 13
🔭 Outside diff range comments (1)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md (1)
828-834
: 🛠️ Refactor suggestionDocument bridge security model.
The
BridgeStorage
struct and associated functions lack documentation about critical security aspects:
- Trust assumptions
- Validation process
- Recovery procedures
Add a "Security Considerations" section documenting:
- Trust model and assumptions
- Validation requirements
- Recovery procedures for various failure scenarios
🧹 Nitpick comments (34)
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md (3)
8-18
: Enhance deposit function documentation.Please add:
- Error conditions and revert scenarios
- Minimum/maximum deposit limits if any
- Gas considerations for the wrap operation
Also fix the abbreviation:
-Deposit tokens to the contract (a.k.a wrap tokens) +Deposit tokens to the contract (a.k.a. wrap tokens)🧰 Tools
🪛 LanguageTool
[uncategorized] ~11-~11: The abbreviation/initialism is missing a period after the last letter.
Context: ...eposit Deposit tokens to the contract (a.k.a wrap tokens) *converts msg.value amoun...(ABBREVIATION_PUNCTUATION)
20-35
: Enhance withdraw function documentation.Please add:
- Error conditions and revert scenarios (e.g., insufficient balance)
- Gas considerations for the unwrap operation
Also fix the grammar:
-Withdraw tokens from the contract (a.k.a unwrap tokens) +Withdraw tokens from the contract (a.k.a. unwrap tokens) -|`amount`|`uint256`|amount of tokens to withdraw| +|`amount`|`uint256`|number of tokens to withdraw|🧰 Tools
🪛 LanguageTool
[uncategorized] ~22-~22: The abbreviation/initialism is missing a period after the last letter.
Context: ...raw Withdraw tokens from the contract (a.k.a unwrap tokens) *converts ERC20 tokens ...(ABBREVIATION_PUNCTUATION)
[uncategorized] ~34-~34: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...-|----|-----------| |amount
|uint256
|amount of tokens to withdraw| ## Events ### ...(AMOUNTOF_TO_NUMBEROF)
37-48
: Add emission conditions to events documentation.Please document:
- When exactly each event is emitted
- The relationship between event parameters and function parameters
- Example values for better understanding
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md (3)
32-34
: Add descriptions for token address fields.The property table is missing descriptions for
tokenAddressFrom
andtokenAddressTo
fields.|`tokenAddressFrom`|`bytes32`|| |`tokenAddressTo`|`bytes32`|| +|`tokenAddressFrom`|`bytes32`|source token address| +|`tokenAddressTo`|`bytes32`|destination token address|
40-40
: Fix abbreviation format in documentation.The abbreviation "eg." should be "e.g." (with periods) in the data field descriptions.
-additional data of the transaction (eg. user nonce for Solana) +additional data of the transaction (e.g., user nonce for Solana)Also applies to: 70-70
🧰 Tools
🪛 LanguageTool
[uncategorized] ~40-~40: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### MiniReceip...(E_G)
93-96
: Add missing field descriptions.The property table is missing descriptions for
destChainId
andexternalTokenAddress
fields.-|`destChainId`|`uint256`|| +|`destChainId`|`uint256`|chain ID of the destination chain| |`tokenAddress`|`bytes32`|address of the token contract| -|`externalTokenAddress`|`bytes32`|| +|`externalTokenAddress`|`bytes32`|external token address on the destination chain|bridge-evm/.env.example (1)
5-5
: Replace hardcoded WRAPPED_TOKEN address with placeholder.For consistency with other example values, consider using a placeholder address instead of a potentially real address.
-WRAPPED_TOKEN=0x2Cf845b49e1c4E5D657fbBF36E97B7B5B7B7b74b +WRAPPED_TOKEN=0xDeaDBeefDeaDBeefDeaDBeefDeaDBeefDeaDBeef🧰 Tools
🪛 Gitleaks (8.21.2)
5-5: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
bridge-evm/docs/src/contracts/Bridge.sol/contract.Bridge.md (1)
31-31
: Add missing parameter description.The
tokenBeacon_
parameter lacks a description in the documentation.Add a description for the
tokenBeacon_
parameter in the Parameters table:|Name|Type|Description| |----|----|-----------| |`authority_`|`address`|address of the authority contract [AccessManager](https://docs.openzeppelin.com/contracts/5.x/access-control#access-management)| -|`tokenBeacon_`|`address`|| +|`tokenBeacon_`|`address`|address of the beacon contract used for creating upgradeable token contracts| |`SAMB_`|`address`|address of the Wrapped token contract|bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md (3)
1-5
: Add high-level overview and security considerations.The documentation would benefit from:
- A clear description of the library's purpose in the bridge system
- Security considerations for receipt handling
- Explanation of the relationship between
FullReceipt
andMiniReceipt
types
7-28
: EnhanceasMini
function documentation.Please add:
- Details about which fields are preserved/dropped during conversion
- Security implications of using mini receipts
- Example usage showing the conversion process
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
17-17: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
56-80
: Differentiate betweentoHash
functions.Please:
- Use unique headings for each
toHash
function- Explain when to use
FullReceipt
vsMiniReceipt
hashing- Document any performance or security trade-offs
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
56-56: Multiple headings with the same content
null(MD024, no-duplicate-heading)
69-69: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
75-75: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md (2)
143-143
: Improve grammar in function description.Change "Validate the send payload" to "Validate the payload to be sent" or simply "Validate the payload" for better clarity.
🧰 Tools
🪛 LanguageTool
[grammar] ~143-~143: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...(A_INFINITIVE)
85-138
: Consider consolidating duplicate validate function documentation.The documentation for both validate functions is identical except for the receipt type parameter. Consider consolidating them into a single section with a note about the overloaded versions to reduce duplication and improve maintainability.
-### validate - -Validate the transaction receipt - - -```solidity -function validate( - FullReceipt memory receipt, - bytes memory signature -) - external - view - returns (bool isValid); -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`receipt`|`FullReceipt`|transaction full receipt| -|`signature`|`bytes`|signature of the receipt. Must be signed by all validators| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|`isValid`|`bool`|true if the receipt is valid| - - -### validate - -Validate the transaction receipt - - -```solidity -function validate( - MiniReceipt memory receipt, - bytes memory signature -) - external - view - returns (bool isValid); -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`receipt`|`MiniReceipt`|transaction cropped receipt| -|`signature`|`bytes`|signature of the receipt. Must be signed by all validators| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|`isValid`|`bool`|true if the receipt is valid| +### validate + +Validate the transaction receipt. This function is overloaded to support both full and mini receipts. + +#### Full Receipt Validation +```solidity +function validate( + FullReceipt memory receipt, + bytes memory signature +) + external + view + returns (bool isValid); +``` + +#### Mini Receipt Validation +```solidity +function validate( + MiniReceipt memory receipt, + bytes memory signature +) + external + view + returns (bool isValid); +``` + +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`receipt`|`FullReceipt\|MiniReceipt`|transaction receipt (full or cropped)| +|`signature`|`bytes`|signature of the receipt. Must be signed by all validators| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`isValid`|`bool`|true if the receipt is valid|🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
99-99: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
113-113: Multiple headings with the same content
null(MD024, no-duplicate-heading)
127-127: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
134-134: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md (3)
1-4
: Add an overview section to explain the library's purpose.Consider adding an overview section at the beginning of the documentation to explain:
- The purpose and use cases of this library
- Version compatibility information
- Security considerations and potential risks
Example structure:
# AddressUtils A utility library for converting between different address representations in Ethereum smart contracts. ## Overview This library provides functions for converting between `bytes32` and `address` types, supporting both big-endian and little-endian byte orders. It's particularly useful when interfacing with external systems or implementing cross-chain functionality. ### Version Compatibility - Solidity: ^0.8.0 - OpenZeppelin: ^5.0.0 ### Security Considerations - Input validation is performed internally - No known vulnerabilities - Audited as part of the bridge system
13-26
: Document error cases and add usage examples.For each conversion function, consider documenting:
- Potential error cases and how they're handled
- Code examples showing actual usage in a contract
Example addition:
### Error Handling - Invalid input lengths are reverted - Zero addresses are allowed ### Usage Example ```solidity contract MyContract { using AddressUtils for bytes32; function example(bytes32 input) public pure returns (address) { return input.toAddressBE(); } }--- `103-126`: **Document OpenZeppelin dependency requirements.** Since this function uses OpenZeppelin's String library, consider documenting: - Required OpenZeppelin version - Any initialization requirements - Error cases from the underlying `parseAddress` function Example addition: ```markdown ### Dependencies - Requires OpenZeppelin Contracts ^5.0.0 - Inherits error cases from `Strings.parseAddress`: - Reverts if the input is not a valid hex address - Reverts if the input length is incorrect ### Usage Example ```solidity address converted = AddressUtils.toAddress("0x742d35Cc6634C0532925a3b844Bc454e4438f44e");
</blockquote></details> <details> <summary>bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md (4)</summary><blockquote> `12-14`: **Document the storage pattern and its significance.** The `VALIDATOR_STORAGE_POSITION` constant is crucial for the upgradeable storage pattern but lacks explanation. Consider adding documentation that explains: - Why this specific storage pattern is used - How it ensures storage safety during upgrades - The significance of the bytes32 value --- `60-61`: **Document the readyToValidate modifier implementation.** The `readyToValidate` modifier lacks documentation about: - Its purpose and when it's used - The conditions it checks - The failure scenarios --- `94-104`: **Add missing parameter documentation.** The `validator_` parameter lacks description in the documentation. Consider adding: - Parameter validation rules - Expected address format - Any restrictions on who can be a validator <details> <summary>🧰 Tools</summary> <details> <summary>🪛 markdownlint-cli2 (0.17.2)</summary> 100-100: Emphasis used instead of a heading null (MD036, no-emphasis-as-heading) </details> </details> --- `325-329`: **Document the ValidatorStorage struct fields.** Add documentation for each field in the ValidatorStorage struct: - `validators`: Purpose of the validator set, constraints - `payloadSigner`: Role and responsibilities - `feeValidityWindow`: Impact on validation process </blockquote></details> <details> <summary>bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md (5)</summary><blockquote> `81-82`: **Add missing parameter descriptions.** Several parameters lack descriptions in the documentation: - `externalToken_` in multiple functions - `authority` in `_deployExternalTokenERC20` Add descriptions to clarify the purpose and requirements of these parameters. Also applies to: 110-111, 150-151, 243-244, 314-315, 426-427, 453-454 --- `209-212`: **Enhance documentation for token bridging behavior.** The documentation should clarify: - The relationship between minting and burning operations - The flow of tokens across chains Add a section explaining the token bridging mechanism, including: - How tokens are locked/unlocked - When minting/burning occurs - Cross-chain token mapping Also applies to: 513-513 <details> <summary>🧰 Tools</summary> <details> <summary>🪛 LanguageTool</summary> [uncategorized] ~211-~211: Possible missing comma found. Context: ...e chain.* *This token will be used for bridging as minting and burning. For more detail... (AI_HYDRA_LEO_MISSING_COMMA) </details> </details> --- `517-522`: **Document struct field requirements.** The `ExternalToken` and `ExternalTokenUnmapped` structs lack field validation requirements: - Valid ranges for decimals - Format requirements for externalTokenAddress Add documentation specifying: - Valid ranges for each field - Format requirements - Relationships between fields Also applies to: 527-530 --- `12-14`: **Document storage slot selection methodology.** The `TokenManagerStorageLocation` constant uses a specific bytes32 value without explaining how it was generated or why this specific value was chosen. Add documentation explaining: - How the storage slot was calculated - Why this specific value was chosen - Potential collision considerations --- `593-601`: **Document storage upgrade considerations.** The `TokenManagerStorage` struct lacks documentation about: - Storage layout versioning - Upgrade safety considerations - Field ordering rationale Add documentation covering: - Storage versioning strategy - Field ordering principles - Safe upgrade patterns </blockquote></details> <details> <summary>bridge-evm/script/SetValidatorRelaySigner.s.sol (2)</summary><blockquote> `7-9`: **Remove unused import.** The `AccessManager` import is not used in the contract implementation. ```diff -import {AccessManager} from - "@openzeppelin/contracts/access/manager/AccessManager.sol";
19-20
: Consider emitting events for validator additions.For better transparency and monitoring, consider emitting events when validators are added.
require(signers[i] != address(0), "Zero address not allowed"); validator.addValidator(signers[i]); + emit ValidatorAdded(signers[i]);
Add the event definition at the contract level:
event ValidatorAdded(address indexed validator);bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md (2)
29-29
: Fix grammatical issues in function descriptions.Add the missing article "the" before "fee amount" in the function descriptions.
Apply this diff:
-It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokensLocked` event. +It transfers the tokens to the contract, and validates the fee amount that was sent and emits a `TokensLocked` event.Also applies to: 63-63
🧰 Tools
🪛 LanguageTool
[uncategorized] ~29-~29: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...(AI_HYDRA_LEO_MISSING_THE)
437-437
: Consider adding validation ranges for InvalidValueSent error.The
InvalidValueSent
error could be more helpful if it included information about valid ranges or conditions.Consider adding a comment to clarify the valid ranges or conditions, for example:
```solidity -error InvalidValueSent(uint256 value, uint256 expectedValue); +// @dev Reverts when the value sent doesn't match the required fee amount +// @param value The amount of native currency sent by the user +// @param expectedValue The required fee amount (must be > 0) +error InvalidValueSent(uint256 value, uint256 expectedValue);Also applies to: 438-438 </blockquote></details> <details> <summary>bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md (1)</summary><blockquote> `44-45`: **Fix grammatical error in documentation.** The documentation contains a grammatical error. The phrase "in exchange of" should be "in exchange for". ```diff -*Should send the additional native tokens to the receiver on the other chain in exchange of higher fee amount* +*Should send the additional native tokens to the receiver on the other chain in exchange for higher fee amount*
🧰 Tools
🪛 LanguageTool
[grammar] ~45-~45: The usual preposition to use after “in exchange” is “for”, not “of”. Did you mean “in exchange for”?
Context: ...kens to the receiver on the other chain in exchange of higher fee amount* ```solidity uint25...(IN_CHARGE_OF_FROM)
bridge-evm/docs/src/SUMMARY.md (3)
4-11
: Consider grouping related interfaces together.The interface section could be more intuitive if organized by functionality:
- Core Bridge: IBridge, IValidation, IValidatorV1
- Token Management: ITokenManager, IWrapped
- Types: BridgeTypes, BridgeFlags
19-23
: Consider moving NoncesUpgradeable to the upgradeable section.For better organization and consistency, consider moving
NoncesUpgradeable
to the upgradeable section since it follows the same pattern as other upgradeable contracts.
24-25
: Consider highlighting these as main entry points.The Bridge and Validator contracts are the primary entry points for users. Consider:
- Moving them to the top of the contracts section
- Adding a brief description of their roles
bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md (1)
295-295
: Improve documentation grammar and clarity.Several grammar issues affect documentation clarity:
- Missing articles before "admin" and "fee amount"
- Incorrect verb usage in "validate the send values"
Apply these corrections:
- "should be called by an admin"
- "validates the fee amount"
- "validate send values"
Also applies to: 516-516, 684-684, 719-719
🧰 Tools
🪛 LanguageTool
[uncategorized] ~295-~295: Possible missing article found.
Context: ...ion should be called by admin to deploy external token to the chain.* ```solidity func...(AI_HYDRA_LEO_MISSING_AN)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
bridge-evm/.env.example
(1 hunks)bridge-evm/.gas-snapshot
(1 hunks)bridge-evm/contracts/interface/IBridge.sol
(1 hunks)bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol
(1 hunks)bridge-evm/docs/src/SUMMARY.md
(1 hunks)bridge-evm/docs/src/contracts/Bridge.sol/contract.Bridge.md
(1 hunks)bridge-evm/docs/src/contracts/Validator.sol/contract.Validator.md
(1 hunks)bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
(1 hunks)bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
(1 hunks)bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
(1 hunks)bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
(1 hunks)bridge-evm/docs/src/contracts/token/README.md
(1 hunks)bridge-evm/docs/src/contracts/token/TokenBeacon.sol/contract.TokenBeacon.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md
(1 hunks)bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/utils/PayloadUtils.sol/library.PayloadUtils.md
(1 hunks)bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md
(1 hunks)bridge-evm/script/SetValidatorRelaySigner.s.sol
(1 hunks)bridge-evm/test/differential_testing/bytes2address.js
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- bridge-evm/test/differential_testing/bytes2address.js
- bridge-evm/docs/src/contracts/Validator.sol/contract.Validator.md
- bridge-evm/docs/src/contracts/token/README.md
- bridge-evm/docs/src/contracts/utils/PayloadUtils.sol/library.PayloadUtils.md
- bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md
- bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol
- bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md
🧰 Additional context used
🪛 LanguageTool
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
[uncategorized] ~11-~11: The abbreviation/initialism is missing a period after the last letter.
Context: ...eposit Deposit tokens to the contract (a.k.a wrap tokens) *converts msg.value amoun...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~22-~22: The abbreviation/initialism is missing a period after the last letter.
Context: ...raw Withdraw tokens from the contract (a.k.a unwrap tokens) *converts ERC20 tokens ...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~34-~34: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...-|----|-----------| |amount
|uint256
|amount of tokens to withdraw| ## Events ### ...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
[uncategorized] ~157-~157: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st| ### _update *Transfers a value
amount of tokens from from
to to
, or alter...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md
[uncategorized] ~211-~211: Possible missing comma found.
Context: ...e chain.* *This token will be used for bridging as minting and burning. For more detail...
(AI_HYDRA_LEO_MISSING_COMMA)
bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md
[uncategorized] ~224-~224: Possible missing article found.
Context: ...ion should be called by admin to deploy external token to the chain.* ```solidity func...
(AI_HYDRA_LEO_MISSING_AN)
[uncategorized] ~511-~511: Possible missing article found.
Context: ...ion should be called by admin to deploy external token to the chain.* *This token will ...
(AI_HYDRA_LEO_MISSING_AN)
[uncategorized] ~513-~513: Possible missing comma found.
Context: ...e chain.* *This token will be used for bridging as minting and burning. For more detail...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~513-~513: Possible missing comma found.
Context: ...idging as minting and burning. For more details see ERC20Bridged
contract.* ```soli...
(AI_HYDRA_LEO_MISSING_COMMA)
bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
[uncategorized] ~295-~295: Possible missing article found.
Context: ...ion should be called by admin to deploy external token to the chain.* ```solidity func...
(AI_HYDRA_LEO_MISSING_AN)
[grammar] ~516-~516: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ..._validateSendValues Guard for validate the send values ```solidity function _validate...
(A_INFINITIVE)
[uncategorized] ~631-~631: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...dress of the token| |amount
|uint256
|amount of tokens to send| |receiver
|`address...
(AMOUNTOF_TO_NUMBEROF)
[uncategorized] ~684-~684: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...
(AI_HYDRA_LEO_MISSING_THE)
[uncategorized] ~719-~719: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...
(AI_HYDRA_LEO_MISSING_THE)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
[uncategorized] ~40-~40: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### MiniReceip...
(E_G)
[uncategorized] ~65-~65: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st token address| |amountTo
|uint256
|amount of tokens sent| |chainFrom
|uint256
|...
(AMOUNTOF_TO_NUMBEROF)
[uncategorized] ~70-~70: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### SendPayloa...
(E_G)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
[grammar] ~45-~45: The usual preposition to use after “in exchange” is “for”, not “of”. Did you mean “in exchange for”?
Context: ...kens to the receiver on the other chain in exchange of higher fee amount* ```solidity uint25...
(IN_CHARGE_OF_FROM)
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
[uncategorized] ~29-~29: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...
(AI_HYDRA_LEO_MISSING_THE)
[uncategorized] ~63-~63: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...
(AI_HYDRA_LEO_MISSING_THE)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
[grammar] ~143-~143: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...
(A_INFINITIVE)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
[grammar] ~293-~293: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...
(A_INFINITIVE)
🪛 markdownlint-cli2 (0.17.2)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
47-47: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
71-71: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
86-86: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
92-92: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
113-113: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
121-121: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
128-128: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
141-141: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
148-148: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
168-168: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
192-192: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
198-198: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
224-224: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
233-233: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
248-248: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
254-254: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
269-269: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
275-275: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
290-290: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
296-296: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
312-312: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
326-326: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
341-341: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
355-355: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
372-372: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
386-386: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
400-400: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
423-423: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
437-437: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
451-451: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
465-465: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
479-479: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
493-493: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
507-507: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/Bridge.sol/contract.Bridge.md
26-26: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
43-43: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
51-51: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
58-58: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
81-81: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
93-93: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
116-116: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
123-123: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
130-130: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
146-146: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
153-153: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
171-171: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
177-177: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
184-184: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
195-195: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
201-201: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
208-208: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
216-216: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
222-222: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
237-237: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
252-252: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
267-267: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
282-282: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
297-297: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
312-312: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
346-346: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
363-363: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
378-378: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
402-402: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
440-440: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
19-19: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
25-25: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
42-42: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
48-48: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
63-63: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
78-78: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
99-99: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
113-113: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
127-127: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
134-134: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
155-155: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
162-162: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
178-178: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
193-193: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
209-209: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
75-75: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
81-81: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
100-100: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
125-125: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
131-131: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
150-150: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
156-156: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
181-181: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
196-196: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
211-211: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
247-247: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
254-254: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
261-261: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
277-277: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
284-284: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
307-307: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
314-314: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
43-43: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
49-49: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
56-56: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
69-69: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
75-75: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
101-101: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
🪛 Gitleaks (8.21.2)
bridge-evm/.env.example
5-5: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
🔇 Additional comments (26)
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md (1)
1-6
: Add security considerations section.The interface documentation should include security considerations regarding:
- Potential reentrancy risks during deposit/withdraw
- Importance of checking return values
- Implications of wrapping/unwrapping native currency
bridge-evm/contracts/interface/IBridge.sol (4)
8-26
: Well-structured error definitions with clear documentation!The error types are comprehensive and cover essential failure scenarios with descriptive messages.
28-53
: Well-defined events with proper indexing!The events are well-documented and follow consistent naming patterns. The use of indexed parameters will help with efficient event filtering.
77-77
: Fix event name in documentation.The documentation mentions emitting a
TokensLocked
event, but the actual event is namedTokenLocked
.-/// It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokensLocked` event. +/// It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokenLocked` event.
55-176
: Well-designed function interface with proper modifiers!The functions are well-documented and follow Solidity best practices. The use of view modifiers and clear parameter documentation enhances the interface's usability.
bridge-evm/.gas-snapshot (2)
11-13
: Optimize gas usage in claim operations.The claim operations are consuming significant gas:
test_claim_withFullReceipt
: ~640k gastest_claim_withMiniReceipt
: ~638k gastest_claim_withSendNativeFlag
: ~684k gas
60-61
: Optimize gas usage in multiple bridge send operations.The send operations are gas-intensive:
test_sendingToBridge_multiple
: ~1046k gasbridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md (1)
157-159
: Add security warnings for _update function.The documentation should include warnings about:
- Potential risks of minting/burning operations
- Access control requirements
- Validation of bridge address
🧰 Tools
🪛 LanguageTool
[uncategorized] ~157-~157: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st| ### _update *Transfers avalue
amount of tokens fromfrom
toto
, or alter...(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md (3)
1-6
: LGTM!The interface overview and inheritance documentation is clear and well-structured.
169-199
: LGTM!The events documentation is thorough and well-structured, with clear descriptions and properly documented parameters.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
178-178: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
193-193: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
200-214
: LGTM!The error documentation is clear and comprehensive, with proper description and parameter documentation.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
209-209: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md (1)
683-685
: Enhance fee documentation.The fee-related documentation lacks important details about:
- Fee calculation methodology
- Fee validation process
- Fee distribution mechanism
Add documentation about:
- How fees are calculated
- Fee validation criteria
- Fee distribution flow
- Handling of failed fee transfers
Also applies to: 718-720
bridge-evm/script/SetValidatorRelaySigner.s.sol (2)
1-3
: LGTM! Modern Solidity configuration.The pragma and license configurations are appropriate, using a recent Solidity version (0.8.20) and ABI coder v2.
17-21
: Add validation for duplicate validators.While zero address validation is implemented, the code still lacks checks for duplicate validators.
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md (1)
1-455
: LGTM! The interface documentation is well-structured and comprehensive.The documentation provides clear descriptions for all functions, events, and error types. It includes:
- Detailed function signatures with parameter descriptions
- Event definitions with indexed parameters
- Custom error types for better error handling
- Clear inheritance structure
🧰 Tools
🪛 LanguageTool
[uncategorized] ~29-~29: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...(AI_HYDRA_LEO_MISSING_THE)
[uncategorized] ~63-~63: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...(AI_HYDRA_LEO_MISSING_THE)
🪛 markdownlint-cli2 (0.17.2)
17-17: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
43-43: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
51-51: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
58-58: Multiple headings with the same content
null(MD024, no-duplicate-heading)
81-81: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
93-93: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
116-116: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
123-123: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
130-130: Multiple headings with the same content
null(MD024, no-duplicate-heading)
146-146: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
153-153: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
171-171: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
177-177: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
184-184: Multiple headings with the same content
null(MD024, no-duplicate-heading)
195-195: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
201-201: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
208-208: Multiple headings with the same content
null(MD024, no-duplicate-heading)
216-216: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
222-222: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
237-237: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
252-252: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
267-267: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
282-282: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
297-297: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
312-312: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
346-346: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
363-363: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
378-378: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
402-402: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
440-440: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md (3)
12-32
: LGTM! Well-documented flags with efficient bit positions.The first three flags are well-documented and use sequential bit positions (0, 1, 2), which is an efficient use of the lower bits.
1-8
: LGTM! Well-structured documentation.The documentation follows good practices with clear sections, consistent formatting, and concise descriptions for each flag.
39-59
:⚠️ Potential issueCritical: High bit positions may cause overflow issues.
The flags
SHOULD_UNWRAP
,SEND_NATIVE_TO_RECEIVER
, andSHOULD_RESTAKE
use bit positions 65, 66, and 67 respectively. This is problematic because:
- These positions exceed the safe bit range for many operations.
- There's an unexplained large gap between bit positions 2 and 65.
- This could lead to unexpected behavior or overflow issues.
Consider using lower, sequential bit positions. Here's the suggested change:
-uint256 constant SHOULD_UNWRAP = 1 << 65; -uint256 constant SEND_NATIVE_TO_RECEIVER = 1 << 66; -uint256 constant SHOULD_RESTAKE = 1 << 67; +uint256 constant SHOULD_UNWRAP = 1 << 3; +uint256 constant SEND_NATIVE_TO_RECEIVER = 1 << 4; +uint256 constant SHOULD_RESTAKE = 1 << 5;Likely an incorrect or invalid review comment.
🧰 Tools
🪛 LanguageTool
[grammar] ~45-~45: The usual preposition to use after “in exchange” is “for”, not “of”. Did you mean “in exchange for”?
Context: ...kens to the receiver on the other chain in exchange of higher fee amount* ```solidity uint25...(IN_CHARGE_OF_FROM)
bridge-evm/docs/src/SUMMARY.md (4)
1-3
: LGTM! Clear and well-structured documentation header.The documentation follows standard practices with a clear title and home page link.
12-14
: LGTM! Well-organized token-related contracts.Clear separation of token-specific implementations.
15-18
: Verify the upgrade pattern implementation.Please ensure that:
- Each upgradeable contract follows the UUPS or Transparent Proxy pattern
- Storage layouts are properly documented
- Upgrade functions are properly secured
❌ Verification inconclusive
🏁 Script executed:
#!/bin/bash # Search for upgrade-related patterns in the contracts rg -A 5 'UUPSUpgradeable|TransparentUpgradeableProxy' bridge-evm/ rg -A 5 '__gap|initializer' bridge-evm/Length of output: 3106
Let's gather more detailed information by searching for upgradeable implementations in the specific
contracts/upgradeable
directory to determine if they follow the required patterns.
🏁 Script executed:
#!/bin/bash # Search for key upgradeable patterns in the contracts/upgradeable folder rg -A 5 'UUPSUpgradeable|TransparentUpgradeableProxy' bridge-evm/contracts/upgradeable/ rg -A 5 'initializer|__gap' bridge-evm/contracts/upgradeable/Length of output: 153
Upgrade Pattern Verification – Action Required
Our searches indicate that the files listed in the upgradeable section (e.g.
BridgeUpgradeable.sol
,TokenManagerUpgradeable.sol
, andValidatorUpgradeable.sol
) in thecontracts/upgradeable
folder do not include any of the key upgradeability indicators such asUUPSUpgradeable
,TransparentUpgradeableProxy
,initializer
, or__gap
. This absence suggests that the upgrade pattern implementation may not follow the standard UUPS or Transparent Proxy patterns, at least not directly in these files.Next Steps for Verification:
- Manual Verification: Please manually inspect the implementation of these upgradeable contracts to confirm how upgradeability is handled. Check if they rely on inheritance from external upgradeability implementations or if proxy patterns are applied elsewhere in the codebase.
- Documentation & Security: Ensure that the storage layouts are clearly documented and that any upgrade functions are appropriately secured.
1-25
: Verify that all documentation links are valid.Please ensure all documentation files exist at the specified paths and contain the expected content.
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Check if all referenced documentation files exist while IFS= read -r line; do if [[ $line =~ \(([^)]+)\) ]]; then path="bridge-evm/docs/src/${BASH_REMATCH[1]}" if [[ ! -f "$path" ]]; then echo "Missing file: $path" fi fi done < bridge-evm/docs/src/SUMMARY.mdLength of output: 131
The above script re-verifies the documentation links using a PCRE-based grep extraction. Please run this script; if it produces no output, it confirms that all referenced documentation files exist and the links are valid.
Documentation Links Verified:
- No missing documentation files were reported from
bridge-evm/docs/src/SUMMARY.md
.
🏁 Script executed:
#!/bin/bash # Improved script to check that all documentation files listed in SUMMARY.md exist. grep -oP '\(\K[^)]+(?=\))' bridge-evm/docs/src/SUMMARY.md | while read -r doc_path; do full_path="bridge-evm/docs/src/$doc_path" if [ ! -f "$full_path" ]; then echo "Missing file: $full_path" fi doneLength of output: 4542
Documentation Links Confirmed Valid
All referenced documentation files inbridge-evm/docs/src/SUMMARY.md
exist and appear correctly linked.bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md (2)
67-75
: Document access control and validation requirements.The token management functions have significant security implications but lack documentation about:
- Required access control
- Token validation requirements
- Potential risks and security considerations
Also applies to: 199-204
261-262
: Enhance documentation for wrapping/unwrapping functionality.The
_wrap
and_unwrap
functions handle critical token conversions but lack important details:
- Relationship between AMB and SAMB tokens
- Potential failure scenarios
- Requirements for successful wrapping/unwrapping
Also applies to: 274-275
bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md (2)
602-603
: Enhance fee handling documentation.The fee-related functions lack important details about:
- Fee calculation methodology
- Fee validation process
- Fee distribution mechanism
766-774
: Document cross-chain security model and trust assumptions.The cross-chain operations lack documentation about critical security aspects:
- Trust assumptions for validators
- Receipt validation process
- Double-spend prevention
Also applies to: 798-806
# TokenBeacon | ||
[Git Source](https://github.com/ambrosus/token-bridge/blob/1106b61cbc37ad86299178c6d334722a2ad64d7d/contracts/token/TokenBeacon.sol) | ||
|
||
**Inherits:** | ||
UpgradeableBeacon | ||
|
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.
🛠️ Refactor suggestion
Documentation needs significant expansion.
The current documentation lacks essential sections that are crucial for developers:
- Contract description and purpose
- Security considerations for using beacon pattern
- Integration guidelines
- Events documentation
- Public/external methods documentation
Would you like me to provide a template for the expanded documentation?
**Inherits:** | ||
UpgradeableBeacon |
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.
🛠️ Refactor suggestion
Document UpgradeableBeacon inheritance implications.
The inheritance from UpgradeableBeacon
is a critical architectural choice that needs explanation:
- Purpose of using the beacon pattern
- Upgrade mechanisms and security considerations
- Role in the broader token bridge architecture
constructor( | ||
address owner_, | ||
address implementation_ | ||
) | ||
UpgradeableBeacon(implementation_, owner_); | ||
``` |
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.
🛠️ Refactor suggestion
Enhance constructor documentation.
The constructor documentation should include:
- Parameter descriptions and validation requirements
- Expected parameter formats (e.g., non-zero addresses)
- Example usage
- Initialization flow explanation
Example improvement:
### constructor
Initializes the TokenBeacon contract with an owner and implementation address.
Parameters:
- `owner_`: Address that will have upgrade rights (must be non-zero)
- `implementation_`: Address of the initial implementation contract (must be non-zero)
Requirements:
- Both addresses must be non-zero
- Implementation must be a valid contract
Example:
```solidity
TokenBeacon beacon = new TokenBeacon(
0x1234...5678, // Owner address
0x8765...4321 // Implementation address
);
<!-- This is an auto-generated comment by CodeRabbit -->
### toHash | ||
|
||
Shortcut to convert receipt to hash | ||
|
||
*using [toEthSignedMessageHash](https://docs.openzeppelin.com/contracts/5.x/api/utils#MessageHashUtils-toEthSignedMessageHash-bytes32-) from OpenZeppelin's MessageHashUtils* | ||
|
||
|
||
```solidity | ||
function toHash(BridgeTypes.FullReceipt memory receipt) | ||
internal | ||
pure | ||
returns (bytes32 hash); | ||
``` | ||
**Parameters** | ||
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`receipt`|`BridgeTypes.FullReceipt`|receipt to convert| | ||
|
||
**Returns** | ||
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`hash`|`bytes32`|converted| | ||
|
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.
🛠️ Refactor suggestion
Document security aspects of receipt hashing.
For this critical bridge functionality, please document:
- The complete hashing process
- Replay attack mitigations
- Cross-chain security considerations
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
43-43: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
49-49: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
### toEthSignedMessageHash | ||
|
||
Convert receipt to hash via toEthSignedMessageHash | ||
|
||
*using [toEthSignedMessageHash](https://docs.openzeppelin.com/contracts/5.x/api/utils#MessageHashUtils-toEthSignedMessageHash-bytes32-) from OpenZeppelin's MessageHashUtils* | ||
|
||
|
||
```solidity | ||
function toEthSignedMessageHash(BridgeTypes.MiniReceipt memory receipt) | ||
internal | ||
pure | ||
returns (bytes32 hash); | ||
``` | ||
**Parameters** | ||
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`receipt`|`BridgeTypes.MiniReceipt`|receipt to convert| | ||
|
||
**Returns** | ||
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`hash`|`bytes32`|converted| | ||
|
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.
🛠️ Refactor suggestion
Document EIP-191 signature scheme details.
For this Ethereum-specific hashing function, please document:
- Why EIP-191 personal sign is used
- The prefix added to the message (
\x19Ethereum Signed Message:\n32
) - How validators should verify these hashes
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
95-95: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
101-101: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
Outdated
Show resolved
Hide resolved
|
||
|
||
```solidity | ||
event TokenLocked(FullReceipt receipt); |
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.
💡 Verification agent
🧩 Analysis chain
Verify event names in documentation.
The event names in the code comments (TokensLocked
) don't match the actual event names (TokenLocked
). This inconsistency could lead to confusion.
Run the following script to verify the event names in the implementation:
Also applies to: 333-333
🏁 Script executed:
#!/bin/bash
# Description: Search for event declarations and their usage
ast-grep --pattern 'event TokenLocked($$$);'
ast-grep --pattern 'event TokensLocked($$$);'
ast-grep --pattern 'emit TokenLocked($$$);'
ast-grep --pattern 'emit TokensLocked($$$);'
Length of output: 187
I'm generating a new shell script to search for occurrences of both "TokenLocked" and "TokensLocked" within the documentation file to confirm their usage.
🏁 Script executed:
#!/bin/bash
echo "Searching for 'TokenLocked' in IBridge.md:"
rg "TokenLocked" bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
echo "Searching for 'TokensLocked' in IBridge.md:"
rg "TokensLocked" bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
Length of output: 668
Inconsistency Found in Event Naming
- The documentation file (
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
) defines the event asTokenLocked
(line 325) but later text describes and references aTokensLocked
event. - This name mismatch could indeed lead to confusion. Please update the documentation to consistently use one event name.
function __TokenManager_init( | ||
address tokenBeacon_, | ||
address bridge_, | ||
address SAMB | ||
) | ||
internal | ||
onlyInitializing; | ||
``` | ||
|
||
### __TokenManager_init_unchained | ||
|
||
|
||
```solidity | ||
function __TokenManager_init_unchained( | ||
address tokenBeacon_, | ||
address bridge_, | ||
address SAMB | ||
) | ||
internal | ||
onlyInitializing; | ||
``` |
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.
🛠️ Refactor suggestion
Document initialization requirements and constraints.
The initialization functions lack critical details about:
- Parameter validation requirements
- Order of initialization
- Upgrade considerations
Add documentation covering:
- Valid parameter ranges/constraints
- Required setup sequence
- Implications for contract upgrades
struct TokenManagerStorage { | ||
mapping(address => bool) bridgableTokens; | ||
mapping(bytes32 => ExternalToken) externalTokens; | ||
mapping(address => bool) unpausedTokens; | ||
address bridge; | ||
address SAMB; | ||
address tokenBeacon; | ||
} | ||
``` |
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.
🛠️ Refactor suggestion
Document storage layout implications.
The TokenManagerStorage
struct uses ERC-7201 for namespaced storage but lacks documentation about:
- Storage layout considerations
- Upgrade safety
- Potential collisions
Add documentation covering:
- Storage layout design
- Upgrade safety guarantees
- Storage slot calculation
function __Bridge_init( | ||
address authority_, | ||
address tokenBeacon_, | ||
address SAMB_, | ||
IValidation validator_, | ||
address payable feeReceiver_, | ||
uint256 nativeSendAmount_ | ||
) | ||
internal | ||
onlyInitializing; | ||
``` | ||
|
||
### __Bridge_init_unchained | ||
|
||
|
||
```solidity | ||
function __Bridge_init_unchained( | ||
IValidation validator_, | ||
address payable feeReceiver_, | ||
uint256 nativeSendAmount_ | ||
) | ||
internal | ||
onlyInitializing; | ||
``` |
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.
🛠️ Refactor suggestion
Document bridge initialization requirements.
The bridge initialization functions lack critical details about:
- Parameter validation requirements
- Initialization sequence
- Validator setup requirements
Add documentation covering:
- Valid parameter constraints
- Required initialization order
- Validator configuration requirements
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: 12
🔭 Outside diff range comments (1)
bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md (1)
1-108
:⚠️ Potential issueAdd comprehensive security documentation.
As this library is critical for bridge security, please add a dedicated security section documenting:
- Potential attack vectors (e.g., receipt forgery, replay attacks)
- Security measures implemented
- Integration guidelines for secure usage
- Audit status and findings
Would you like me to help draft a security documentation template?
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
17-17: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
43-43: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
49-49: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
56-56: Multiple headings with the same content
null(MD024, no-duplicate-heading)
69-69: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
75-75: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
101-101: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
♻️ Duplicate comments (2)
bridge-evm/script/DeployerBase.s.sol (2)
144-199
:⚠️ Potential issueFix critical security issue in admin role checks.
Both
setAuthorityAdmin
andremoveAuthorityAdmin
functions incorrectly check the admin candidate's role instead of the sender's role, which could lead to unauthorized access.Apply these fixes:
function setAuthorityAdmin(address adminCandidate) public returns (bool adminGranted) { (bool isAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); if (!isAdmin) { console.log("Address", adminCandidate, "is not an admin"); (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + authority.hasRole(authority.ADMIN_ROLE(), msg.sender); if (isSenderAdmin) { console.log("Sender can add the admin"); function removeAuthorityAdmin(address adminCandidate) public returns (bool adminRemoved) { (bool isAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); if (isAdmin) { (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + authority.hasRole(authority.ADMIN_ROLE(), msg.sender); if (isSenderAdmin) { authority.revokeRole(authority.ADMIN_ROLE(), adminCandidate);
285-322
:⚠️ Potential issueAdd validation for dependent contracts in Bridge deployment.
The
deployBridge
function should validate that required contracts are properly initialized before deployment.function deployBridge() public returns (Bridge) { + require(address(authority) != address(0), "Authority not initialized"); + require(address(tokenBeacon) != address(0), "TokenBeacon not initialized"); + require(address(validator) != address(0), "Validator not initialized"); address wrappedToken = vm.envAddress("WRAPPED_TOKEN"); address payable feeReceiver = payable(vm.envOr("FEE_RECEIVER", address(0)));
🧹 Nitpick comments (41)
bridge-evm/deployments/22040.json (2)
23-27
: Remove unnecessary empty contract entry.The last entry with empty contract name and zero addresses appears to be a placeholder. Consider removing it to maintain a cleaner configuration file.
{ "contractName": "Bridge", "implementationAddress": "0x6D10438D535b9d8d279ea6be187366c42026d37b", "proxyAddress": "0x9579d503193b31b5E2d41B4820dc3154268219c0" - }, - { - "contractName": "", - "implementationAddress": "0x0000000000000000000000000000000000000000", - "proxyAddress": "0x0000000000000000000000000000000000000000" }
1-29
: Add deployment metadata for better traceability.Consider enhancing the deployment configuration with additional metadata:
{ + "version": "1.0.0", + "network": { + "chainId": 22040, + "name": "your_network_name" + }, + "deployedAt": "timestamp", + "deployedBy": "address", "contracts": [ ... ] }bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md (1)
29-29
: Improve grammar in function descriptions.Add the article "the" before "fee amount" in the function descriptions.
Apply these changes:
-It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokensLocked` event. +It transfers the tokens to the contract, and validates the fee amount that was sent and emits a `TokensLocked` event.Also applies to: 63-63
🧰 Tools
🪛 LanguageTool
[uncategorized] ~29-~29: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...(AI_HYDRA_LEO_MISSING_THE)
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md (3)
9-18
: Enhance deposit function documentation.Please add the following details:
- Return value (if any)
- Failure scenarios and error handling
- Gas considerations for token wrapping
- Example usage
Also fix the abbreviation punctuation:
-Deposit tokens to the contract (a.k.a wrap tokens) +Deposit tokens to the contract (a.k.a. wrap tokens)🧰 Tools
🪛 LanguageTool
[uncategorized] ~11-~11: The abbreviation/initialism is missing a period after the last letter.
Context: ...eposit Deposit tokens to the contract (a.k.a wrap tokens) *converts msg.value amoun...(ABBREVIATION_PUNCTUATION)
🪛 markdownlint-cli2 (0.17.2)
13-13: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
20-34
: Enhance withdraw function documentation.Please add the following details:
- Return value (if any)
- Failure scenarios (e.g., insufficient balance)
- Gas considerations for token unwrapping
- Example usage
Apply these fixes:
-Withdraw tokens from the contract (a.k.a unwrap tokens) +Withdraw tokens from the contract (a.k.a. unwrap tokens) -|`amount`|`uint256`|amount of tokens to withdraw| +|`amount`|`uint256`|number of tokens to withdraw|🧰 Tools
🪛 LanguageTool
[uncategorized] ~22-~22: The abbreviation/initialism is missing a period after the last letter.
Context: ...raw Withdraw tokens from the contract (a.k.a unwrap tokens) *converts ERC20 tokens ...(ABBREVIATION_PUNCTUATION)
[uncategorized] ~34-~34: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...-|----|-----------| |amount
|uint256
|amount of tokens to withdraw| ## Events ### ...(AMOUNTOF_TO_NUMBEROF)
🪛 markdownlint-cli2 (0.17.2)
24-24: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
30-30: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
36-48
: Enhance events documentation.For both
Deposit
andWithdrawal
events, please add:
- When the event is emitted
- Parameter descriptions in a table format similar to function parameters
- Example event data structure
Example format for event parameters:
**Parameters** |Name|Type|Description|Indexed| |----|----|-----------|-------| |`dst`|`address`|destination address receiving the wrapped tokens|Yes| |`amount`|`uint256`|number of tokens being wrapped|No|bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md (1)
5-70
: Add access control documentation.The function documentation is comprehensive but lacks information about access control requirements. Consider adding a section for each function that specifies who can call these functions (e.g., admin only, anyone, etc.).
Example addition for
addValidator
:### addValidator Add a new validator to the list +**Access Control** +- Only callable by admin/owner + ```solidity🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
14-14: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
20-20: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
35-35: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
59-59: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md (1)
143-166
: Improve grammar in validatePayload documentation.Change "Validate the send payload" to "Validate the payload to be sent" or simply "Validate the payload".
🧰 Tools
🪛 LanguageTool
[grammar] ~143-~143: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...(A_INFINITIVE)
🪛 markdownlint-cli2 (0.17.2)
155-155: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
162-162: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md (3)
79-79
: Add missing parameter descriptions.Add descriptions for the
validator_
parameter in the following functions:
isValidator
: "Address to check for validator status"addValidator
: "Address to add as a validator"removeValidator
: "Address to remove from validators"Also applies to: 104-104, 129-129
252-252
: Add missing signature parameter descriptions.Add descriptions for the
combinedSignatures
parameter in bothvalidate
functions:
"Combined signatures from all validators, concatenated in ascending order of validator addresses"Also applies to: 282-282
325-330
: Add struct field descriptions.Add descriptions for the
ValidatorStorage
struct fields:struct ValidatorStorage { - EnumerableSet.AddressSet validators; - address payloadSigner; - uint256 feeValidityWindow; + EnumerableSet.AddressSet validators; // Set of authorized validator addresses + address payloadSigner; // Address authorized to sign payloads + uint256 feeValidityWindow; // Time window in seconds for fee validity }bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md (7)
1-8
: Add security considerations section.Consider adding a "Security Considerations" section to document potential security implications of nonce management, such as:
- Replay attack prevention
- Cross-chain transaction ordering
- Nonce exhaustion scenarios
10-16
: Enhance storage documentation.The storage implementation uses the ERC-7201 namespaced storage pattern, which is excellent for upgradeable contracts. Consider adding:
- A link to the ERC-7201 specification
- An explanation of how the storage slot is calculated
- Documentation about storage collision prevention
Also applies to: 134-144
41-96
: Differentiate overloaded function headings.The documentation has multiple sections with identical headings for overloaded functions. Consider:
- Adding the parameter type to each heading (e.g., "nonces (uint256)", "nonces (address)", "nonces (bytes32)")
- Including return value types in the function descriptions
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
50-50: Multiple headings with the same content
null(MD024, no-duplicate-heading)
59-59: Multiple headings with the same content
null(MD024, no-duplicate-heading)
78-78: Multiple headings with the same content
null(MD024, no-duplicate-heading)
88-88: Multiple headings with the same content
null(MD024, no-duplicate-heading)
98-123
: Improve _useCheckedNonce documentation.The documentation for
_useCheckedNonce
functions could be enhanced by:
- Explaining the revert conditions
- Providing usage examples
- Documenting the relationship with
InvalidAccountNonce
error🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
107-107: Multiple headings with the same content
null(MD024, no-duplicate-heading)
116-116: Multiple headings with the same content
null(MD024, no-duplicate-heading)
125-132
: Enhance error documentation.The
InvalidAccountNonce
error documentation could be improved by:
- Adding a code example showing when this error occurs
- Explaining how to handle this error in client code
- Documenting the expected vs actual nonce relationship
134-144
: Expand struct documentation.The
NoncesStorage
struct documentation could be enhanced by:
- Explaining the mapping key-value relationship
- Documenting the initial values
- Adding examples of how the storage is used
1-146
: Add standard documentation sections.Consider adding these standard documentation sections:
- Installation & Usage
- Testing & Verification
- Gas Considerations
- Upgrade Considerations
- License Information
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
50-50: Multiple headings with the same content
null(MD024, no-duplicate-heading)
59-59: Multiple headings with the same content
null(MD024, no-duplicate-heading)
78-78: Multiple headings with the same content
null(MD024, no-duplicate-heading)
88-88: Multiple headings with the same content
null(MD024, no-duplicate-heading)
107-107: Multiple headings with the same content
null(MD024, no-duplicate-heading)
116-116: Multiple headings with the same content
null(MD024, no-duplicate-heading)
bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md (3)
12-14
: Document storage slot calculation.The
ERC20AdditionalStorageLocation
constant uses a hardcoded storage slot. Please document:
- How this storage slot was calculated
- Why this specific value was chosen
- Reference to ERC7201 for namespaced storage pattern
176-181
: Expand blacklist error documentation.Please enhance the documentation to include:
- When this error is thrown
- How to handle this error
- Impact on user operations
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
176-176: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
185-195
: Document struct field constraints.For each field in
BridgedERC20Storage
, document:
- Valid value ranges
- Initialization requirements
- Update restrictions
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md (3)
6-41
: Enhance struct documentation for clarity and completeness.Several fields in the
FullReceipt
struct lack descriptions or could benefit from more detailed explanations:
tokenAddressFrom
: Add description for source token addresstokenAddressTo
: Add description for destination token addressamountFrom
: Add description for source token amountamountTo
: Add description for destination token amountAlso, fix the format of "e.g." in the
data
field description.Apply this diff to enhance the documentation:
|Name|Type|Description| |----|----|-----------| |`from`|`bytes32`|source address| |`to`|`bytes32`|destination address| -|`tokenAddressFrom`|`bytes32`|| -|`tokenAddressTo`|`bytes32`|| -|`amountFrom`|`uint256`|| -|`amountTo`|`uint256`|| +|`tokenAddressFrom`|`bytes32`|address of the token contract on the source chain| +|`tokenAddressTo`|`bytes32`|address of the token contract on the destination chain| +|`amountFrom`|`uint256`|amount of tokens to be locked on the source chain| +|`amountTo`|`uint256`|amount of tokens to be unlocked on the destination chain| |`chainFrom`|`uint256`|chain id of the source chain| |`chainTo`|`uint256`|chain id of the destination chain| |`eventId`|`uint256`|transaction number| |`flags`|`uint256`|flags for receiver| -|`data`|`bytes`|additional data of the transaction (eg. user nonce for Solana)| +|`data`|`bytes`|additional data of the transaction (e.g., user nonce for Solana)|🧰 Tools
🪛 LanguageTool
[uncategorized] ~40-~40: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### MiniReceip...(E_G)
🪛 markdownlint-cli2 (0.17.2)
26-26: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
42-71
: Improve struct documentation for clarity.The
MiniReceipt
struct documentation has minor issues:
- Fix the format of "e.g." in the
data
field description- Replace "amount of" with "number of" for countable tokens
Apply this diff to improve the documentation:
|Name|Type|Description| |----|----|-----------| |`to`|`bytes32`|destination address| |`tokenAddressTo`|`bytes32`|dest token address| -|`amountTo`|`uint256`|amount of tokens sent| +|`amountTo`|`uint256`|number of tokens sent| |`chainFrom`|`uint256`|chain id of the source chain| |`chainTo`|`uint256`|chain id of the destination chain| |`eventId`|`uint256`|transaction number| |`flags`|`uint256`|flags for receiver| -|`data`|`bytes`|additional data of the transaction (eg. user nonce for Solana)| +|`data`|`bytes`|additional data of the transaction (e.g., user nonce for Solana)|🧰 Tools
🪛 LanguageTool
[uncategorized] ~65-~65: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st token address| |amountTo
|uint256
|amount of tokens sent| |chainFrom
|uint256
|...(AMOUNTOF_TO_NUMBEROF)
[uncategorized] ~70-~70: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### SendPayloa...(E_G)
🪛 markdownlint-cli2 (0.17.2)
59-59: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
72-101
: Complete struct documentation with missing descriptions.The
SendPayload
struct documentation is missing descriptions for several fields and could benefit from more detailed explanations:
destChainId
: Add description for destination chain IDexternalTokenAddress
: Add description for external token addressflagData
: Add description for flag-specific dataApply this diff to complete the documentation:
|Name|Type|Description| |----|----|-----------| -|`destChainId`|`uint256`|| +|`destChainId`|`uint256`|chain ID of the destination chain| |`tokenAddress`|`bytes32`|address of the token contract| -|`externalTokenAddress`|`bytes32`|| +|`externalTokenAddress`|`bytes32`|address of the token contract on the destination chain| |`amountToSend`|`uint256`|amount of the tokens to be sent| |`feeAmount`|`uint256`|amount of the fee| |`timestamp`|`uint256`|timestamp of the fee was generated| |`flags`|`uint256`|flags of the sending operation| -|`flagData`|`bytes`|| +|`flagData`|`bytes`|additional data specific to the flags|🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
89-89: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/contracts/interface/IBridge.sol (1)
745-748
: Add missing parameter descriptions.The following parameters lack descriptions in the documentation:
_deadline
v
r
s
Add descriptions for the permit signature parameters:
|Name|Type|Description| |----|----|-----------| -|`_deadline`|`uint256`|| -|`v`|`uint8`|| -|`r`|`bytes32`|| -|`s`|`bytes32`|| +|`_deadline`|`uint256`|Timestamp after which the permit is invalid| +|`v`|`uint8`|v of the permit ECDSA signature| +|`r`|`bytes32`|r of the permit ECDSA signature| +|`s`|`bytes32`|s of the permit ECDSA signature|bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md (1)
45-45
: Fix grammatical error in documentation.The description contains a grammatical error in the preposition usage.
Apply this diff to fix the grammar:
-*Should send the additional native tokens to the receiver on the other chain in exchange of higher fee amount* +*Should send the additional native tokens to the receiver on the other chain in exchange for higher fee amount*🧰 Tools
🪛 LanguageTool
[grammar] ~45-~45: The usual preposition to use after “in exchange” is “for”, not “of”. Did you mean “in exchange for”?
Context: ...kens to the receiver on the other chain in exchange of higher fee amount* ```solidity uint25...(IN_CHARGE_OF_FROM)
🪛 markdownlint-cli2 (0.17.2)
45-45: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md (5)
1-4
: Add a clear library description and update source link.The documentation would benefit from:
- A clear description of the library's purpose and use cases
- Using a branch reference instead of a commit hash in the source link to keep it current
Add a description section after line 3:
# AddressUtils [Git Source](https://github.com/ambrosus/token-bridge/blob/main/contracts/utils/AddressUtils.sol) +## Overview + +The `AddressUtils` library provides utility functions for converting between `bytes32` and `address` types, supporting both big-endian and little-endian byte orders. This is particularly useful when working with cross-chain bridges where different chains may use different byte orders.
8-10
: Fix typo in function description and improve example readability.The description has a typo and the example could be more readable.
-Convert address to bytes32 using big-endian byte order +Convert bytes32 to address using big-endian byte order -*example: `0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCC` -> `0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc`* +*example:* +``` +Input: 0x1111 2222 3333 4444 5555 6666 7777 8888 9999 AAAA BBBB CCCC DDDD EEEE FFFF CC +Output: 0x7777 8888 9999 AaAa bBbb Cccc ddDd eeeE fFFf CcCc +```
31-34
: Improve example readability with consistent formatting.For consistency with the previous function's example, let's improve the readability.
-*example: `0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCC` -> `0x111122223333444455556666777788889999aAaa`* +*example:* +``` +Input: 0x1111 2222 3333 4444 5555 6666 7777 8888 9999 AAAA BBBB CCCC DDDD EEEE FFFF CC +Output: 0x1111 2222 3333 4444 5555 6666 7777 8888 9999 aAaa +```
54-56
: Add missing example and improve example readability.The first overload is missing an example, and the second overload's example could be more readable.
For the first overload (after line 56), add:
+*example:* +``` +// Big-endian (le = false) +Input: 0x1111 2222 3333 4444 5555 6666 7777 8888 9999 AAAA BBBB CCCC DDDD EEEE FFFF CC +Output: 0x7777 8888 9999 AaAa bBbb Cccc ddDd eeeE fFFf CcCc + +// Little-endian (le = true) +Input: 0x1111 2222 3333 4444 5555 6666 7777 8888 9999 AAAA BBBB CCCC DDDD EEEE FFFF CC +Output: 0x1111 2222 3333 4444 5555 6666 7777 8888 9999 aAaa +```For the second overload, replace the existing example with:
-*example: `0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCC` -> `0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc`* +*example:* +``` +Input: 0x1111 2222 3333 4444 5555 6666 7777 8888 9999 AAAA BBBB CCCC DDDD EEEE FFFF CC +Output: 0x7777 8888 9999 AaAa bBbb Cccc ddDd eeeE fFFf CcCc +```Also applies to: 82-85
105-108
: Add example for string conversion.An example would help users understand the expected string format.
Convert string to address *using [parseAddress](https://docs.openzeppelin.com/contracts/5.x/api/utils#Strings-parseAddress-string-) from OpenZeppelin's String library* +*example:* +``` +Input: "0x7777888899999999aaaabbbbccccddddeeeeffffcccc" +Output: 0x7777 8888 9999 9999 aaaa bbbb cccc dddd eeee ffff cccc +```bridge-evm/script/CreatePayloadSignature.s.sol (1)
9-22
: Enhance struct documentation for better clarity.While the field comments are helpful, consider:
- Clarifying the comment about alphabetical order - why is this important for parsing?
- Expanding documentation for
flagData
to explain potential future uses- Adding validation ranges or constraints for numeric fields
Example improvement:
struct SendPayloadJson { - // There is a additional struct because parser expects alphabetical order + /// @notice This struct matches the JSON structure required by the parser. + /// @dev Fields must be in alphabetical order due to parser requirements. uint256 amountToSend; // amount of the tokens to be sent uint256 destChainId; // chain id of the destination chain bytes32 externalTokenAddress; // address of the external token contract (in destination chain) uint256 feeAmount; // amount of the fee - bytes flagData; // additional data of the sending operation (unused for now) + bytes flagData; // additional data for future protocol extensions (e.g., permit data) uint256 flags; // flags of the sending operation (see BridgeTypes for valid values) uint256 timestamp; // timestamp of the fee was generated (must be within acceptable range) bytes32 tokenAddress; // address of the token contract in source chain }bridge-evm/foundry.toml (1)
2-8
: Fix spacing in file system permissions.The permissions follow the principle of least privilege and cover all necessary paths. However, there's an inconsistent spacing in the root directory permission.
- {access = "read", path = "./"} + { access = "read", path = "./" }bridge-evm/contracts/token/ERC20Bridged.sol (2)
140-153
: Emit events when blacklisting or un-blacklisting addresses.Currently, there is no event to indicate addresses being blacklisted or removed from the blacklist. Emitting events can be useful for off-chain indexing and transparency.
You could add events like so:
+event BlacklistAdded(address indexed account); +event BlacklistRemoved(address indexed account); function addBlacklist(address account) public restricted { BridgedERC20Storage storage $ = _getERC20AdditionalStorage(); $._blacklist[account] = true; + emit BlacklistAdded(account); } function removeBlacklist(address account) public restricted { BridgedERC20Storage storage $ = _getERC20AdditionalStorage(); delete $._blacklist[account]; + emit BlacklistRemoved(account); }
160-184
: Consider adding a reentrancy guard around bridging.Although this bridging logic only calls internal ERC20 operations, it’s often prudent to guard mint/burn paths with a
nonReentrant
modifier if future expansions might involve cross-contract calls or complex bridging flows.+import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; contract ERC20Bridged is Initializable, + ReentrancyGuardUpgradeable, AccessManagedUpgradeable, ERC20Upgradeable, ERC20PermitUpgradeable { ... function _update( address from, address to, uint256 value ) internal + nonReentrant override notInBlacklist(from) notInBlacklist(to) { ... }bridge-evm/script/Claim.s.sol (1)
9-24
: Consider consolidating repeated 'FullReceiptJson' definitions.You've introduced
FullReceiptJson
here, but other scripts also define a similar struct. Reusing a single shared definition in a common library or interface can reduce code duplication and avoid maintenance pitfalls if the fields need to be updated.bridge-evm/script/Send.s.sol (1)
14-24
: Consider unifying 'SendPayloadJson' definitions across scripts.Similar to the claim receipt struct, using a single, central definition for
SendPayloadJson
can avoid divergence if you need to adjust fields later on.bridge-evm/script/CreateClaimSignature.s.sol (1)
9-24
: Avoid duplicating 'FullReceiptJson' struct.As with
Claim.s.sol
, consider centralizing this struct if the fields remain consistent across all scripts. This simplifies code maintenance.bridge-evm/script/DeployerBase.s.sol (3)
75-81
: Remove commented-out code.This block of commented code should be removed as it's no longer needed and could cause confusion.
- // for (uint256 i = 0; i < deploymentsJson.length; i++) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, deploymentsJson[i])); - // if (i < deploymentsJson.length - 1) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, ",")); - // } - // } - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, "]"));
96-142
: Simplify nested conditions for better readability.The function can be refactored to reduce nesting and improve readability.
function checkDeployed(string memory contractName) public returns (bool deployed, address contractOrProxyAddress) { Deployment[] memory deployments = getDeployments(); for (uint256 i = 0; i < deployments.length; i++) { - if ( - Strings.equal( - deployments[i].contractName, - contractName - ) - ) { - if ( - deployments[i].proxyAddress - == address(0) - ) { - if ( - deployments[i].implementationAddress - == address(0) - ) { - console.log(contractName, "not deployed"); - return (false, address(0)); - } else { - console.log( - contractName, - "already deployed as implementation at", - deployments[i] - .implementationAddress - ); - return ( - true, - deployments[i] - .implementationAddress - ); - } - } else { - console.log( - contractName, - "already deployed as proxy at", - deployments[i].proxyAddress - ); - return - (true, deployments[i].proxyAddress); - } + if (!Strings.equal(deployments[i].contractName, contractName)) { + continue; + } + + if (deployments[i].proxyAddress != address(0)) { + console.log(contractName, "already deployed as proxy at", deployments[i].proxyAddress); + return (true, deployments[i].proxyAddress); + } + + if (deployments[i].implementationAddress != address(0)) { + console.log(contractName, "already deployed as implementation at", deployments[i].implementationAddress); + return (true, deployments[i].implementationAddress); } + + console.log(contractName, "not deployed"); + return (false, address(0)); } + return (false, address(0)); }
201-214
: Optimize deployment array handling.The current implementation of
addDeployment
is inefficient and could be simplified.function addDeployment(Deployment memory deployment) public { Deployment[] memory deployments = getDeployments(); - Deployment[] memory newDeployments = new Deployment[](deployments.length + 1); - newDeployments[deployments.length] = deployment; + bool found = false; + Deployment[] memory newDeployments = new Deployment[](deployments.length + (found ? 0 : 1)); for (uint256 i = 0; i < deployments.length; i++) { if(Strings.equal(deployments[i].contractName, deployment.contractName)) { - newDeployments[i] = deployments[i]; - delete newDeployments[deployments.length]; + newDeployments[i] = deployment; + found = true; } else { newDeployments[i] = deployments[i]; } } + if (!found) { + newDeployments[deployments.length] = deployment; + } writeDeployments(newDeployments); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (30)
bridge-evm/contracts/interface/IBridge.sol
(1 hunks)bridge-evm/contracts/token/ERC20Bridged.sol
(1 hunks)bridge-evm/deployments/22040.json
(1 hunks)bridge-evm/docs/src/contracts/Bridge.sol/contract.Bridge.md
(1 hunks)bridge-evm/docs/src/contracts/Validator.sol/contract.Validator.md
(1 hunks)bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
(1 hunks)bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
(1 hunks)bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md
(1 hunks)bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
(1 hunks)bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
(1 hunks)bridge-evm/docs/src/contracts/token/TokenBeacon.sol/contract.TokenBeacon.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md
(1 hunks)bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md
(1 hunks)bridge-evm/docs/src/contracts/utils/PayloadUtils.sol/library.PayloadUtils.md
(1 hunks)bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md
(1 hunks)bridge-evm/foundry.toml
(1 hunks)bridge-evm/payloads/test.json
(1 hunks)bridge-evm/receipts/test.json
(1 hunks)bridge-evm/script/Claim.s.sol
(1 hunks)bridge-evm/script/CreateClaimSignature.s.sol
(1 hunks)bridge-evm/script/CreatePayloadSignature.s.sol
(1 hunks)bridge-evm/script/DeployerBase.s.sol
(1 hunks)bridge-evm/script/Send.s.sol
(1 hunks)bridge-evm/test/ERC20Bridged.t.sol
(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- bridge-evm/receipts/test.json
- bridge-evm/payloads/test.json
🚧 Files skipped from review as they are similar to previous changes (5)
- bridge-evm/docs/src/contracts/token/TokenBeacon.sol/contract.TokenBeacon.md
- bridge-evm/docs/src/contracts/Bridge.sol/contract.Bridge.md
- bridge-evm/docs/src/contracts/Validator.sol/contract.Validator.md
- bridge-evm/docs/src/contracts/utils/PayloadUtils.sol/library.PayloadUtils.md
- bridge-evm/test/ERC20Bridged.t.sol
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
bridge-evm/docs/src/contracts/utils/AddressUtils.sol/library.AddressUtils.md
16-16: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
22-22: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
39-39: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
45-45: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
66-66: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
73-73: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
80-80: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
90-90: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
96-96: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
103-103: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
116-116: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
122-122: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
47-47: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
71-71: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
86-86: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
92-92: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
113-113: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
121-121: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
128-128: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
141-141: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
148-148: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
168-168: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
175-175: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
192-192: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
198-198: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
224-224: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
233-233: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
248-248: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
254-254: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
269-269: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
275-275: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
290-290: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
296-296: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
312-312: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
326-326: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
341-341: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
355-355: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
372-372: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
386-386: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
400-400: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
423-423: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
437-437: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
451-451: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
465-465: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
479-479: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
493-493: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
507-507: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
65-65: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
80-80: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
117-117: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
124-124: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
146-146: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
153-153: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
172-172: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
178-178: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
185-185: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
201-201: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
209-209: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
228-228: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
234-234: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
253-253: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
259-259: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
278-278: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
284-284: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
310-310: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
319-319: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
338-338: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
357-357: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
372-372: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
387-387: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
402-402: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
421-421: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
427-427: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
434-434: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
446-446: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
452-452: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
459-459: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
471-471: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
477-477: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
499-499: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
507-507: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
529-529: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
551-551: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
567-567: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
587-587: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
604-604: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
625-625: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
649-649: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
671-671: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
699-699: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
707-707: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
714-714: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
738-738: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
750-750: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
775-775: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
782-782: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
789-789: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
807-807: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
814-814: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
26-26: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
59-59: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
89-89: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
4-4: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
9-9: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
18-18: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
27-27: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
36-36: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
45-45: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
54-54: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
43-43: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
51-51: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
58-58: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
81-81: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
93-93: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
116-116: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
123-123: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
130-130: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
146-146: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
153-153: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
171-171: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
177-177: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
184-184: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
195-195: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
201-201: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
208-208: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
216-216: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
222-222: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
237-237: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
252-252: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
267-267: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
282-282: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
297-297: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
312-312: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
346-346: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
363-363: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
378-378: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
402-402: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
440-440: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
19-19: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
25-25: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
42-42: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
48-48: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
63-63: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
78-78: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
99-99: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
113-113: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
127-127: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
134-134: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
155-155: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
162-162: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
178-178: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
193-193: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
209-209: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md
14-14: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
20-20: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
35-35: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
41-41: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
59-59: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
65-65: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
81-81: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
13-13: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
24-24: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
30-30: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
85-85: Emphasis style
Expected: asterisk; Actual: underscore
(MD049, emphasis-style)
85-85: Emphasis style
Expected: asterisk; Actual: underscore
(MD049, emphasis-style)
93-93: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
109-109: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
127-127: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
133-133: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
142-142: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
148-148: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
176-176: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md
76-76: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
84-84: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
113-113: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
132-132: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
138-138: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
157-157: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
163-163: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
182-182: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
188-188: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
207-207: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
213-213: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
239-239: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
248-248: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
263-263: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
278-278: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
304-304: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
310-310: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
329-329: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
335-335: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
354-354: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
360-360: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
379-379: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
385-385: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
400-400: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
421-421: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
429-429: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
449-449: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
456-456: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
473-473: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
479-479: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
494-494: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
500-500: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
527-527: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
537-537: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
552-552: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
558-558: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
573-573: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
579-579: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/NoncesUpgradeable.sol/abstract.NoncesUpgradeable.md
50-50: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
59-59: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
78-78: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
88-88: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
107-107: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
116-116: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
43-43: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
49-49: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
56-56: Multiple headings with the same content
null
(MD024, no-duplicate-heading)
69-69: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
75-75: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
101-101: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
🪛 LanguageTool
bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md
[grammar] ~516-~516: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ..._validateSendValues Guard for validate the send values ```solidity function _validate...
(A_INFINITIVE)
[uncategorized] ~631-~631: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...dress of the token| |amount
|uint256
|amount of tokens to send| |receiver
|`address...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/interface.BridgeTypes.md
[uncategorized] ~40-~40: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### MiniReceip...
(E_G)
[uncategorized] ~65-~65: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st token address| |amountTo
|uint256
|amount of tokens sent| |chainFrom
|uint256
|...
(AMOUNTOF_TO_NUMBEROF)
[uncategorized] ~70-~70: The abbreviation “e.g.” (= for example) requires two periods.
Context: ...es`|additional data of the transaction (eg. user nonce for Solana)| ### SendPayloa...
(E_G)
bridge-evm/docs/src/contracts/interface/BridgeTypes.sol/library.BridgeFlags.md
[grammar] ~45-~45: The usual preposition to use after “in exchange” is “for”, not “of”. Did you mean “in exchange for”?
Context: ...kens to the receiver on the other chain in exchange of higher fee amount* ```solidity uint25...
(IN_CHARGE_OF_FROM)
bridge-evm/docs/src/contracts/interface/IBridge.sol/interface.IBridge.md
[uncategorized] ~29-~29: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...
(AI_HYDRA_LEO_MISSING_THE)
[uncategorized] ~63-~63: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...
(AI_HYDRA_LEO_MISSING_THE)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md
[grammar] ~143-~143: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...
(A_INFINITIVE)
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md
[uncategorized] ~11-~11: The abbreviation/initialism is missing a period after the last letter.
Context: ...eposit Deposit tokens to the contract (a.k.a wrap tokens) *converts msg.value amoun...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~22-~22: The abbreviation/initialism is missing a period after the last letter.
Context: ...raw Withdraw tokens from the contract (a.k.a unwrap tokens) *converts ERC20 tokens ...
(ABBREVIATION_PUNCTUATION)
[uncategorized] ~34-~34: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...-|----|-----------| |amount
|uint256
|amount of tokens to withdraw| ## Events ### ...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md
[uncategorized] ~157-~157: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st| ### _update *Transfers a value
amount of tokens from from
to to
, or alter...
(AMOUNTOF_TO_NUMBEROF)
bridge-evm/docs/src/contracts/upgradeable/ValidatorUpgradeable.sol/abstract.ValidatorUpgradeable.md
[grammar] ~293-~293: The verb ‘send’ does not usually follow articles like ‘the’. Check that ‘send’ is spelled correctly; using ‘send’ as a noun may be non-standard.
Context: ... valid| ### validatePayload Validate the send payload ```solidity function validate...
(A_INFINITIVE)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
🔇 Additional comments (32)
bridge-evm/deployments/22040.json (1)
3-7
: Verify AccessManager proxy configuration.The AccessManager contract has an implementation address but uses a zero proxy address. This could indicate either:
- A direct deployment without proxy
- An incomplete proxy deployment
- An intentional design choice
Please verify if this is the intended configuration.
bridge-evm/docs/src/contracts/interface/IWrapped.sol/interface.IWrapped.md (1)
1-6
: Add overview and security considerations sections.The interface documentation should include:
- Overview section explaining the purpose and role of this interface in the bridge system
- Security considerations regarding:
- Potential reentrancy risks during deposit/withdraw
- Importance of checking return values
- Implications of wrapping/unwrapping native currency
bridge-evm/docs/src/contracts/interface/IValidatorV1.sol/interface.IValidatorV1.md (2)
1-4
: LGTM!The interface name and Git source link are well-formatted and follow best practices.
72-100
: LGTM!The events documentation is well-structured and provides clear descriptions of when events are emitted and what data they contain.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
81-81: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
95-95: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/IValidation.sol/interface.IValidation.md (2)
11-29
: Document security implications of payload signer changes.The documentation for
setPayloadSigner
should include:
- Security implications of changing the signer
- Validation requirements for the new signer
- Impact on pending operations
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
19-19: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
25-25: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
87-138
: Clarify the differences between receipt types.The documentation should explain:
- The difference between
FullReceipt
andMiniReceipt
- When to use each receipt type
- The validation process for each type
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
99-99: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
106-106: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
113-113: Multiple headings with the same content
null(MD024, no-duplicate-heading)
127-127: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
134-134: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/utils/ReceiptUtils.sol/library.ReceiptUtils.md (2)
30-54
: Document receipt hashing process and security implications.For both
toHash
functions, please document:
- The complete hashing process
- Replay attack mitigations
- Cross-chain security considerations
Also applies to: 56-80
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
43-43: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
49-49: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
82-106
: Document EIP-191 signature scheme details.For this Ethereum-specific hashing function, please document:
- Why EIP-191 personal sign is used
- The prefix added to the message (
\x19Ethereum Signed Message:\n32
)- How validators should verify these hashes
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
95-95: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
101-101: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/interface/ITokenManager.sol/interface.ITokenManager.md (3)
67-75
: Document access control and security considerations.The token management functions lack critical security documentation:
- Required access control (who can call these functions)
- Token validation requirements
- Potential risks and security considerations
Also applies to: 107-115, 199-204
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
71-71: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
261-262
: Document wrapping/unwrapping functionality details.The
_wrap
and_unwrap
functions lack important details:
- Relationship between AMB and SAMB tokens
- Potential failure scenarios
- Requirements for successful wrapping/unwrapping
Also applies to: 274-275
32-52
: Document initialization requirements.The initialization functions lack critical details:
- Parameter validation requirements
- Order of initialization
- Upgrade considerations
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
41-41: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
47-47: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/docs/src/contracts/upgradeable/TokenManagerUpgradeable.sol/abstract.TokenManagerUpgradeable.md (1)
593-601
: Document storage layout implications.The
TokenManagerStorage
struct uses ERC-7201 for namespaced storage but lacks documentation about:
- Storage layout considerations
- Upgrade safety
- Potential collisions
bridge-evm/docs/src/contracts/token/ERC20Bridged.sol/contract.ERC20Bridged.md (1)
157-160
: Add security warnings for _update function.The documentation should include warnings about:
- Potential risks of minting/burning operations
- Access control requirements
- Validation of bridge address
🧰 Tools
🪛 LanguageTool
[uncategorized] ~157-~157: ‘Amount of’ should usually only be used with uncountable or mass nouns. Consider using “number” if this is not the case.
Context: ...st| ### _update *Transfers avalue
amount of tokens fromfrom
toto
, or alter...(AMOUNTOF_TO_NUMBEROF)
bridge-evm/contracts/interface/IBridge.sol (1)
60-62
: Fix event name mismatch in documentation.The function documentation mentions emitting a
TokensLocked
event, but the actual event is namedTokenLocked
.Apply this diff to fix the documentation:
-/// It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokensLocked` event. +/// It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokenLocked` event.bridge-evm/docs/src/contracts/upgradeable/BridgeUpgradeable.sol/abstract.BridgeUpgradeable.md (3)
25-52
: Document initialization requirements and constraints.The bridge initialization functions lack critical details about parameter validation requirements, initialization sequence, and upgrade considerations.
Add documentation covering:
- Valid parameter ranges/constraints
- Required setup sequence
- Implications for contract upgrades
679-712
: Document cross-chain security model and trust assumptions.The cross-chain operations (send/claim) lack documentation about critical security aspects.
Add comprehensive security documentation covering:
- Validator selection and trust model
- Receipt verification process
- Attack vectors and mitigations
- Recovery procedures for failed transfers
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
699-699: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
707-707: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
596-609
: Enhance fee handling documentation.The fee-related functions lack important details about the fee calculation methodology and distribution mechanism.
Add documentation about:
- How fees are calculated
- Fee validation criteria
- Fee distribution flow
- Handling of failed fee transfers
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
604-604: Emphasis used instead of a heading
null(MD036, no-emphasis-as-heading)
bridge-evm/script/CreatePayloadSignature.s.sol (1)
1-8
: LGTM! Well-structured file header and imports.The file uses a recent, secure Solidity version and appropriate imports.
bridge-evm/foundry.toml (3)
23-30
: LGTM! Well-defined formatting rules.The formatting configuration follows common Solidity conventions and includes comprehensive rules for code style consistency.
35-48
: LGTM! Comprehensive testing profiles.The coverage and CI profiles are well-configured with appropriate exclusions and settings for automated testing.
31-34
:❓ Verification inconclusive
LGTM! Secure RPC configuration.
The RPC endpoints are properly configured using environment variables, following security best practices.
Verify the environment variables setup:
🏁 Script executed:
#!/bin/bash # Check if the required environment variables are documented grep -E "AMBROSUS_(RPC_URL|TEST_RPC_URL|DEV_RPC_URL)" .env.exampleLength of output: 114
Action Required: Verify & Document Environment Variables
The RPC endpoints configuration in
bridge-evm/foundry.toml
appears secure since it utilizes environment variables effectively. However, the automated check for a.env.example
file indicated that it does not exist. Please manually verify whether the environment variables (AMBROSUS_RPC_URL
,AMBROSUS_TEST_RPC_URL
, andAMBROSUS_DEV_RPC_URL
) are documented elsewhere in the repository (for example in a README or a different configuration file) and consider adding a.env.example
file if documentation is lacking.bridge-evm/contracts/token/ERC20Bridged.sol (2)
95-98
: Validate non-zero bridge address.This is the same issue flagged in a previous review: the contract never checks whether
bridge_
is the zero address. A zero bridge address would render the bridging logic unusable and risky.Here’s a suggested fix:
function __ERC20Bridged_init_unchained( address authority_, string memory name_, string memory symbol_, uint8 decimals_, address bridge_ ) internal onlyInitializing { + require(bridge_ != address(0), "Bridge address cannot be zero"); BridgedERC20Storage storage $ = _getERC20AdditionalStorage(); $._decimals = decimals_; $._bridge = bridge_; }
185-187
: All other logic looks solid.The bridging mechanism, blacklist checks, and storage layout are well-structured. Good job overall.
bridge-evm/script/Claim.s.sol (2)
25-52
: Validate inputs before processing receipts.While your usage of
try-catch
handles file read and JSON parse errors, you might also want to check for unexpected values in fields (e.g., zero amounts, mismatched chain IDs) before constructing and returning the receipt. This can guard against malformed inputs and reduce potential vulnerabilities.
54-63
: Check for necessary checks on the signature.Your
run
function callsbridge.claim
with a signature, but you should ensure that the externalbridge.claim
method properly validates the signature, preventing unauthorized claims. Consider verifying that the passed signature corresponds to a trusted signer, if not already done.bridge-evm/script/Send.s.sol (2)
26-45
: Add additional validation on parsed fields.While the
try-catch
pattern is good for handling file I/O and JSON parsing errors, fields likedestChainId
oramountToSend
might also benefit from range checks or logical validations (e.g., ensuringamountToSend
is nonzero).
47-60
: Ensure correct fee usage and address conversions.
- The
feeAmount
is passed in the.send{value: payload.feeAmount}()
. Confirm that this is the required fee type (e.g., ETH or another currency).- The
payload.tokenAddress.toAddress()
conversion appears correct, but you may want to confirm that it handles 32-byte addresses consistently with your chain's formatting.bridge-evm/script/CreateClaimSignature.s.sol (2)
25-52
: Consider stricter screening for receipt fields.Similar to your other scripts, you might want to add checks (e.g., verifying
amountFrom
,chainFrom
, etc.) for correctness. This helps catch issues early before computing the hash or generating signatures.
54-65
: Ensure robust signer management.
- Your script reads signers via
envUint("SIGNERS", ",")
. Verify that you’re handling unexpected or missing environment values properly.- When aggregating signatures (
bytes.concat
), confirm that off-chain consumers of this signature know how to separate them back into individual r, s, v triplets.bridge-evm/script/DeployerBase.s.sol (3)
1-26
: LGTM! Well-structured contract setup.The contract follows best practices with clear imports and state variable declarations.
324-364
: LGTM! Well-implemented getter functions.The getter functions follow a consistent pattern and properly handle deployment checks.
366-367
: LGTM! Standard virtual function implementation.The empty virtual function follows the standard pattern for base contracts.
It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokensLocked` event. | ||
The function should be payable to receive the fee in native currency.* |
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 event name inconsistency.
The documentation refers to a TokensLocked
event, but the actual event name is TokenLocked
(defined on line 325).
Apply these changes:
-It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokensLocked` event.
+It transfers the tokens to the contract, and validates fee amount that was sent and emits a `TokenLocked` event.
Also applies to: 63-64
🧰 Tools
🪛 LanguageTool
[uncategorized] ~29-~29: Possible missing article found.
Context: ...e tokens to the contract, and validates fee amount that was sent and emits a `Token...
(AI_HYDRA_LEO_MISSING_THE)
## Errors | ||
### NoValidators | ||
Reverts if no validators are set | ||
|
||
|
||
```solidity | ||
error NoValidators(); | ||
``` | ||
|
||
### NoPayloadSigner | ||
Reverts if the payload signer is not set | ||
|
||
|
||
```solidity | ||
error NoPayloadSigner(); | ||
``` | ||
|
||
### NoFeeValidityWindow | ||
Reverts if the fee validity window is not set | ||
|
||
|
||
```solidity | ||
error NoFeeValidityWindow(); | ||
``` | ||
|
||
### InvalidSignatureLength | ||
Reverts if the signature length is invalid | ||
|
||
|
||
```solidity | ||
error InvalidSignatureLength(uint256 length); | ||
``` | ||
|
||
### SignatureCountMismatch | ||
Reverts if the number of signatures is invalid | ||
|
||
|
||
```solidity | ||
error SignatureCountMismatch(uint256 count, uint256 required); | ||
``` | ||
|
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.
🛠️ Refactor suggestion
Document missing functionality and error conditions.
The errors documentation suggests additional functionality that isn't covered in the functions section:
- Payload signing
- Fee validation
- Signature validation
Consider:
- Adding documentation for the functions that use these errors
- Specifying the conditions that trigger each error
Example addition for InvalidSignatureLength
:
### InvalidSignatureLength
-Reverts if the signature length is invalid
+Reverts when validating a signature that doesn't match the expected length (e.g., not 65 bytes for an ECDSA signature)
+
+**Usage**
+This error is thrown by the following functions:
+- `validatePayload(bytes memory payload, bytes[] memory signatures)`
+- `validateFee(uint256 fee, bytes[] memory signatures)`
```solidity
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`receipt`|`MiniReceipt`|transaction full receipt| |
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 incorrect receipt description.
Change "transaction full receipt" to "transaction mini receipt" for the MiniReceipt
parameter.
# ReceiptUtils | ||
[Git Source](https://github.com/ambrosus/token-bridge/blob/c9e5c0649869e1d0d7d463cf7e74634fda87430d/contracts/utils/ReceiptUtils.sol) | ||
|
||
|
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.
🛠️ Refactor suggestion
Add high-level documentation sections.
Please add the following sections at the beginning of the documentation:
- Overview - Explain the role of this library in the bridge architecture
- Security Model - Document the trust assumptions and security considerations
- Usage Guidelines - Provide guidance on proper integration
Convert full receipt to mini receipt | ||
|
||
|
||
```solidity | ||
function asMini(BridgeTypes.FullReceipt memory receipt) | ||
internal | ||
pure | ||
returns (BridgeTypes.MiniReceipt memory mini); | ||
``` | ||
**Parameters** | ||
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`receipt`|`BridgeTypes.FullReceipt`|receipt to convert| | ||
|
||
**Returns** | ||
|
||
|Name|Type|Description| | ||
|----|----|-----------| | ||
|`mini`|`BridgeTypes.MiniReceipt`|receipt converted| | ||
|
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.
🛠️ Refactor suggestion
Enhance asMini
function documentation.
Please document:
- Which fields are included/excluded in the mini receipt
- The purpose of having a mini receipt format
- When to use mini vs full receipts
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
17-17: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
23-23: Emphasis used instead of a heading
null
(MD036, no-emphasis-as-heading)
**Inherits:** | ||
Initializable, ERC20Upgradeable, AccessManagedUpgradeable, ERC20PermitUpgradeable | ||
|
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.
🛠️ Refactor suggestion
Document upgrade-related security considerations.
The contract inherits from multiple OpenZeppelin upgradeable contracts. Please add a security section to document:
- Upgrade process and authorization
- Storage layout considerations
- Potential risks during upgrades
Would you like me to help generate the security documentation section?
*Returns the address of the bridge contract. | ||
This address is used to mint and burn tokens.* |
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.
🛠️ Refactor suggestion
Enhance bridge address documentation.
The bridge address documentation should emphasize:
- The privileged role of the bridge
- Security implications of bridge address changes
- Validation requirements for the bridge address
function getPayload(string memory path) public view returns (BridgeTypes.SendPayload memory) { | ||
try vm.readFile(path) returns (string memory json) { | ||
bytes memory data = vm.parseJson(json); | ||
SendPayloadJson memory payloadJson = abi.decode(data, (SendPayloadJson)); | ||
BridgeTypes.SendPayload memory payload = BridgeTypes.SendPayload({ | ||
amountToSend: payloadJson.amountToSend, | ||
destChainId: payloadJson.destChainId, | ||
externalTokenAddress: payloadJson.externalTokenAddress, | ||
feeAmount: payloadJson.feeAmount, | ||
flags: payloadJson.flags, | ||
flagData: payloadJson.flagData, | ||
timestamp: payloadJson.timestamp, | ||
tokenAddress: payloadJson.tokenAddress | ||
}); | ||
return payload; | ||
} catch (bytes memory) { | ||
console.log("Error reading payload"); | ||
revert(); | ||
} | ||
} |
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.
🛠️ Refactor suggestion
Improve error handling and add input validation.
The current error handling is minimal and lacks specific error messages or validation:
- The generic error message doesn't help diagnose issues
- No validation of parsed values
- No checks for malformed JSON
Consider this improvement:
function getPayload(string memory path) public view returns (BridgeTypes.SendPayload memory) {
try vm.readFile(path) returns (string memory json) {
bytes memory data = vm.parseJson(json);
SendPayloadJson memory payloadJson = abi.decode(data, (SendPayloadJson));
+ // Validate parsed values
+ require(payloadJson.amountToSend > 0, "Invalid amount");
+ require(payloadJson.destChainId > 0, "Invalid chain ID");
+ require(payloadJson.timestamp > 0, "Invalid timestamp");
+ require(payloadJson.timestamp <= block.timestamp, "Future timestamp");
BridgeTypes.SendPayload memory payload = BridgeTypes.SendPayload({
amountToSend: payloadJson.amountToSend,
destChainId: payloadJson.destChainId,
externalTokenAddress: payloadJson.externalTokenAddress,
feeAmount: payloadJson.feeAmount,
flags: payloadJson.flags,
flagData: payloadJson.flagData,
timestamp: payloadJson.timestamp,
tokenAddress: payloadJson.tokenAddress
});
return payload;
- } catch (bytes memory) {
- console.log("Error reading payload");
+ } catch (bytes memory err) {
+ console.log("Failed to read payload from %s:", path);
+ console.logBytes(err);
revert();
}
}
📝 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.
function getPayload(string memory path) public view returns (BridgeTypes.SendPayload memory) { | |
try vm.readFile(path) returns (string memory json) { | |
bytes memory data = vm.parseJson(json); | |
SendPayloadJson memory payloadJson = abi.decode(data, (SendPayloadJson)); | |
BridgeTypes.SendPayload memory payload = BridgeTypes.SendPayload({ | |
amountToSend: payloadJson.amountToSend, | |
destChainId: payloadJson.destChainId, | |
externalTokenAddress: payloadJson.externalTokenAddress, | |
feeAmount: payloadJson.feeAmount, | |
flags: payloadJson.flags, | |
flagData: payloadJson.flagData, | |
timestamp: payloadJson.timestamp, | |
tokenAddress: payloadJson.tokenAddress | |
}); | |
return payload; | |
} catch (bytes memory) { | |
console.log("Error reading payload"); | |
revert(); | |
} | |
} | |
function getPayload(string memory path) public view returns (BridgeTypes.SendPayload memory) { | |
try vm.readFile(path) returns (string memory json) { | |
bytes memory data = vm.parseJson(json); | |
SendPayloadJson memory payloadJson = abi.decode(data, (SendPayloadJson)); | |
// Validate parsed values | |
require(payloadJson.amountToSend > 0, "Invalid amount"); | |
require(payloadJson.destChainId > 0, "Invalid chain ID"); | |
require(payloadJson.timestamp > 0, "Invalid timestamp"); | |
require(payloadJson.timestamp <= block.timestamp, "Future timestamp"); | |
BridgeTypes.SendPayload memory payload = BridgeTypes.SendPayload({ | |
amountToSend: payloadJson.amountToSend, | |
destChainId: payloadJson.destChainId, | |
externalTokenAddress: payloadJson.externalTokenAddress, | |
feeAmount: payloadJson.feeAmount, | |
flags: payloadJson.flags, | |
flagData: payloadJson.flagData, | |
timestamp: payloadJson.timestamp, | |
tokenAddress: payloadJson.tokenAddress | |
}); | |
return payload; | |
} catch (bytes memory err) { | |
console.log("Failed to read payload from %s:", path); | |
console.logBytes(err); | |
revert(); | |
} | |
} |
function run(string memory path) public { | ||
BridgeTypes.SendPayload memory payload = getPayload(path); | ||
bytes32 digest = payload.toHash(); | ||
uint256 signer = vm.envUint("PAYLOAD_SIGNER"); | ||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); | ||
bytes memory signature = abi.encodePacked(r, s, v); | ||
console.log(vm.toString(signature)); | ||
} |
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.
Add security measures for signature generation.
The current implementation has several security considerations:
- No access control on the public function
- Private key from environment variable needs careful handling
- No validation of signer address
Consider these improvements:
+ error InvalidSigner();
+ error SignerNotAuthorized();
+
function run(string memory path) public {
BridgeTypes.SendPayload memory payload = getPayload(path);
bytes32 digest = payload.toHash();
uint256 signer = vm.envUint("PAYLOAD_SIGNER");
+ // Validate signer
+ if (signer == 0) revert InvalidSigner();
+ address signerAddress = vm.addr(signer);
+ // Add authorization check (implement according to your security model)
+ if (!isAuthorizedSigner(signerAddress)) revert SignerNotAuthorized();
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest);
bytes memory signature = abi.encodePacked(r, s, v);
- console.log(vm.toString(signature));
+ // Log both signature and signer for verification
+ console.log("Signature:", vm.toString(signature));
+ console.log("Signer:", vm.toString(signerAddress));
}
+
+ function isAuthorizedSigner(address signer) internal view returns (bool) {
+ // Implement authorization logic
+ // Example: check against a list of authorized signers
+ return true; // TODO: implement proper authorization
+ }
📝 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.
function run(string memory path) public { | |
BridgeTypes.SendPayload memory payload = getPayload(path); | |
bytes32 digest = payload.toHash(); | |
uint256 signer = vm.envUint("PAYLOAD_SIGNER"); | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); | |
bytes memory signature = abi.encodePacked(r, s, v); | |
console.log(vm.toString(signature)); | |
} | |
error InvalidSigner(); | |
error SignerNotAuthorized(); | |
function run(string memory path) public { | |
BridgeTypes.SendPayload memory payload = getPayload(path); | |
bytes32 digest = payload.toHash(); | |
uint256 signer = vm.envUint("PAYLOAD_SIGNER"); | |
// Validate signer | |
if (signer == 0) revert InvalidSigner(); | |
address signerAddress = vm.addr(signer); | |
// Add authorization check (implement according to your security model) | |
if (!isAuthorizedSigner(signerAddress)) revert SignerNotAuthorized(); | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, digest); | |
bytes memory signature = abi.encodePacked(r, s, v); | |
// Log both signature and signer for verification | |
console.log("Signature:", vm.toString(signature)); | |
console.log("Signer:", vm.toString(signerAddress)); | |
} | |
function isAuthorizedSigner(address signer) internal view returns (bool) { | |
// Implement authorization logic | |
// Example: check against a list of authorized signers | |
return true; // TODO: implement proper authorization | |
} |
libs = ['node_modules', 'lib'] | ||
test = 'test' | ||
cache_path = 'cache' | ||
evm_version = 'istanbul' |
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.
💡 Verification agent
🧩 Analysis chain
Consider upgrading the EVM version.
The 'istanbul' EVM version might be outdated. Consider upgrading to a newer version like 'paris', 'shanghai', or 'cancun' to leverage the latest EVM features and optimizations.
🌐 Web query:
What is the latest EVM version supported by Foundry?
💡 Result:
Foundry v1.0 supports up to the Prague hardfork as its latest EVM version[4][2]. This includes experimental support for EIP-7702 (Contract Account Abstraction) through specific configuration:
# foundry.toml
evm_version = "prague"
Key implementation details:
- Requires explicit configuration via CLI (
--evm-version prague
) or config file[4] - Enables testing EIP-7702 transactions using Anvil with
--hardfork prague
[2] - Includes new cheatcodes for delegation patterns (
signDelegation
,attachDelegation
)[2]
The previous default EVM version was Cancun[4], which remains available for backward compatibility through explicit configuration:
evm_version = "cancun"
Developers working with Rootstock (RSK) can use Foundry's EVM compatibility since RSK maintains full EVM equivalence[3]. Forge compilation benchmarks show 2.1-5.2x faster performance compared to Hardhat when using these EVM configurations[2].
Citations:
- 1: https://hevm.dev
- 2: https://www.paradigm.xyz/2025/02/announcing-foundry-v1-0
- 3: https://dev.rootstock.io/developers/quickstart/foundry/
- 4: https://book.getfoundry.sh/reference/config/solidity-compiler
- 5: https://ethereum-blockchain-developer.com/2022-06-nft-truffle-hardhat-foundry/14-foundry-setup/
- 6: Name latest solc and evm version supported by anvil in readme foundry-rs/foundry#7921
- 7: https://www.paradigm.xyz/2021/12/introducing-the-foundry-ethereum-development-toolbox
- 8: https://memo.d.foundation/playground/01_literature/using-foundry-for-evm-smart-contract-developement/
- 9: https://book.getfoundry.sh
- 10: https://github.com/foundry-rs/foundry/blob/master/CHANGELOG.md
Upgrade EVM Version to "prague"
The current configuration uses evm_version = 'istanbul'
, which is outdated. Foundry v1.0 now supports the "prague" hardfork—the latest EVM version offering new features like experimental support for EIP-7702 and additional cheatcodes. To leverage these improvements, update the configuration accordingly. If backward compatibility is needed, you may also consider "cancun", but "prague" is recommended for accessing the newest enhancements.
- File:
bridge-evm/foundry.toml
- Line(s): 20
Change: Update fromtoevm_version = 'istanbul'
evm_version = 'prague'
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
♻️ Duplicate comments (3)
bridge-evm/script/DeployerBase.s.sol (3)
144-177
:⚠️ Potential issueFix the admin check in setAuthorityAdmin.
The function incorrectly checks
adminCandidate
instead ofmsg.sender
when verifying if the sender is an admin.function setAuthorityAdmin(address adminCandidate) public returns (bool adminGranted) { (bool isAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); if (!isAdmin) { console.log("Address", adminCandidate, "is not an admin"); (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + authority.hasRole(authority.ADMIN_ROLE(), msg.sender); if (isSenderAdmin) { // ... rest of the function
179-199
:⚠️ Potential issueFix the admin check in removeAuthorityAdmin.
The function has the same issue as setAuthorityAdmin, checking
adminCandidate
instead ofmsg.sender
.function removeAuthorityAdmin(address adminCandidate) public returns (bool adminRemoved) { (bool isAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); if (isAdmin) { (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + authority.hasRole(authority.ADMIN_ROLE(), msg.sender); if (isSenderAdmin) { // ... rest of the function
285-322
: 🛠️ Refactor suggestionAdd validation for dependent contracts in deployBridge.
The function should verify that required contracts are properly initialized before deployment.
function deployBridge() public returns (Bridge) { + require(address(authority) != address(0), "Authority not initialized"); + require(address(tokenBeacon) != address(0), "TokenBeacon not initialized"); + require(address(validator) != address(0), "Validator not initialized"); address wrappedToken = vm.envAddress("WRAPPED_TOKEN"); address payable feeReceiver = payable(vm.envOr("FEE_RECEIVER", address(0)));
🧹 Nitpick comments (3)
bridge-evm/script/DeployerBase.s.sol (3)
75-81
: Remove commented-out code.The commented code block is redundant as the functionality is now handled by
vm.serializeString
.- // for (uint256 i = 0; i < deploymentsJson.length; i++) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, deploymentsJson[i])); - // if (i < deploymentsJson.length - 1) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, ",")); - // } - // } - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, "]"));
46-48
: Extract path construction to a dedicated function.The deployment file path construction is duplicated. Consider extracting it to a dedicated function for better maintainability.
+ function getDeploymentsPath() internal view returns (string memory) { + string memory root = vm.projectRoot(); + return string.concat(root, "/deployments/", vm.toString(block.chainid), ".json"); + } function getDeployments() public returns (Deployment[] memory) { - string memory root = vm.projectRoot(); - string memory path = string.concat( - root, "/deployments/", vm.toString(block.chainid), ".json" - ); + string memory path = getDeploymentsPath(); // ... rest of the function } function writeDeployments(Deployment[] memory data) public { - string memory root = vm.projectRoot(); - string memory path = string.concat( - root, "/deployments/", vm.toString(block.chainid), ".json" - ); + string memory path = getDeploymentsPath(); // ... rest of the function }Also applies to: 88-90
96-142
: Simplify the deployment check logic for better readability.The nested if conditions make the code harder to follow. Consider restructuring with early returns.
function checkDeployed(string memory contractName) public returns (bool deployed, address contractOrProxyAddress) { Deployment[] memory deployments = getDeployments(); for (uint256 i = 0; i < deployments.length; i++) { - if ( - Strings.equal( - deployments[i].contractName, - contractName - ) - ) { - if ( - deployments[i].proxyAddress - == address(0) - ) { - if ( - deployments[i].implementationAddress - == address(0) - ) { - console.log(contractName, "not deployed"); - return (false, address(0)); - } else { - console.log( - contractName, - "already deployed as implementation at", - deployments[i] - .implementationAddress - ); - return ( - true, - deployments[i] - .implementationAddress - ); - } - } else { - console.log( - contractName, - "already deployed as proxy at", - deployments[i].proxyAddress - ); - return - (true, deployments[i].proxyAddress); - } + if (!Strings.equal(deployments[i].contractName, contractName)) { + continue; } + + if (deployments[i].proxyAddress != address(0)) { + console.log( + contractName, + "already deployed as proxy at", + deployments[i].proxyAddress + ); + return (true, deployments[i].proxyAddress); + } + + if (deployments[i].implementationAddress != address(0)) { + console.log( + contractName, + "already deployed as implementation at", + deployments[i].implementationAddress + ); + return (true, deployments[i].implementationAddress); + } + + console.log(contractName, "not deployed"); + return (false, address(0)); } + return (false, address(0)); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
bridge-evm/deployments/22040.json
(1 hunks)bridge-evm/script/DeployerBase.s.sol
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- bridge-evm/deployments/22040.json
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
🔇 Additional comments (2)
bridge-evm/script/DeployerBase.s.sol (2)
1-26
: LGTM! Well-structured contract with appropriate imports.The contract structure follows best practices with clear organization of imports and state variables.
366-366
: LGTM! Well-designed extension point.The empty virtual function provides a clean hook for derived contracts to implement their deployment logic.
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
♻️ Duplicate comments (2)
bridge-evm/script/DeployerBase.s.sol (2)
148-153
:⚠️ Potential issueDuplicate issue: Incorrect sender admin check.
As noted in a previous review, the code callsauthority.hasRole(authority.ADMIN_ROLE(), adminCandidate)
twice (line 149, line 151) instead of verifying the caller (e.g.,msg.sender
oraddress(this)
). This prevents confirming whether the caller is actually an admin.- (bool isSenderAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + (bool isSenderAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), msg.sender);
187-188
:⚠️ Potential issueDuplicate issue: Sender role check uses the candidate address.
Same as above, this incorrectly verifiesadminCandidate
again instead ofmsg.sender
, leading to a faulty admin authority check.- (bool isSenderAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + (bool isSenderAdmin,) = authority.hasRole(authority.ADMIN_ROLE(), msg.sender);
🧹 Nitpick comments (5)
bridge-evm/script/DeployerBase.s.sol (5)
3-3
: Remove unnecessarypragma abicoder v2
.
Since Solidity 0.8.x, usingpragma abicoder v2;
is the default behavior and no longer needed, so it's safe to remove this line to avoid confusion.-pragma abicoder v2;
59-63
: Rename misleading references to “apples.”
The function comment and loop references mention “the apples array” or “apple object,” but this function is serializing deployments. Please rename or remove these references for clarity and consistency.-// Function to serialize the apples array +// Function to serialize the deployments array ... -// Serialize each apple object +// Serialize each deployment object
74-81
: Remove or clarify commented code.
These lines are commented out and potentially obsolete. If they are no longer needed, remove them to keep the codebase clean; otherwise, add a clarifying comment to explain their purpose.- // for (uint256 i = 0; i < deploymentsJson.length; i++) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, deploymentsJson[i])); - // if (i < deploymentsJson.length - 1) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, ",")); - // } - // } - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, "]"));
190-191
: Fix the grammar in log message.
The console output “Admin revoked granted to” is confusing. Clarify by updating it to “Admin role revoked from.”- console.log("Admin revoked granted to", adminCandidate); + console.log("Admin role revoked from", adminCandidate);
203-213
: Refactor duplicate handling inaddDeployment
.
The current approach appends the new deployment and then potentially removes it if a duplicate is found. Consider a clearer pattern:
- Check if the contract name already exists.
- Overwrite or skip appending.
This simplifies the loop logic and improves readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
bridge-evm/deployments/22040.json
(1 hunks)bridge-evm/script/DeployerBase.s.sol
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- bridge-evm/deployments/22040.json
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
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: 1
🧹 Nitpick comments (8)
bridge-evm/test/bridge_tests/BridgeSolanaSend.t.sol (1)
31-31
: Consider modularizing code to reduce stack depth issues.The inline comment indicates a "huge mess" due to a stack too deep error, which is a common challenge in Solidity tests. For better maintainability and readability, consider breaking code blocks into smaller, dedicated helper functions or using structs to pass multiple parameters.
bridge-evm/test/BridgeSolana.t.sol (1)
35-46
: Extend handling for additional test selectors or fallback scenarios.The
beforeTestSetup
function currently only handles thetest_revertWhen_send_BadFeeReceiver
selector. For broader use, consider adding a default or fallback path if other tests require pre-invocation logic.bridge-evm/test/bridge_tests/BridgeSend.t.sol (6)
28-29
: Refactor to avoid “stack too deep” issues.The comment suggests complexity is becoming cumbersome. Consider splitting logic into smaller functions or using struct grouping to reduce local variable counts. This will also improve maintainability.
89-134
: Ensure preconditions for token lookups.
bridgeInstance.externalToken(payload.externalTokenAddress)
may revert if a token is not added. It might be valuable to test for this scenario and handle it gracefully, especially if partial setup steps are missed.I can provide a test snippet that verifies behavior when attempting to generate payloads for an unregistered token.
154-179
: Rename parameters for clarity inapproveOrPermit
.Currently,
isApprove
is used and then inverted in the call site (!isPermit
). Consider renaming it tousePermit
or similarly to reduce confusion and align with the typical boolean naming approach.- function approveOrPermit(bool isApprove, address token, Signer memory signer, ...) + function approveOrPermit(bool usePermit, address token, Signer memory signer, ...) { ... }
298-335
: Reduce duplicate logic acrosssend
overloads.You have two
send
functions with similar logic (one with permit params and one without). Extracting common parts into a private/internal helper can enhance readability and reduce future maintenance overhead.
409-409
: Typo in the signer name.“singer2” might be a typo. Consider renaming to “signer2” for consistency with the rest of the code.
- signer = getSigner("singer2"); + signer = getSigner("signer2");
363-365
: Consider replacing ternary with a clearer conditional.Using
? :
for branching between permit or approve calls is compact but less explicit. A simpleif (condition) { ... } else { ... }
block may enhance clarity.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
bridge-evm/contracts/BridgeSolana.sol
(1 hunks)bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol
(1 hunks)bridge-evm/test/BridgeSolana.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeSend.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeSolanaSend.t.sol
(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
🔇 Additional comments (11)
bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol (5)
60-92
: Add zero-address validation in initialization.This initialization code does not validate critical addresses (
validator_
andfeeReceiver_
). Using zero addresses can lock contract behavior or lead to misconfiguration.Apply this diff to ensure non-zero addresses:
function __Bridge_init_unchained( IValidation validator_, address payable feeReceiver_, uint256 nativeSendAmount_ ) internal onlyInitializing { + require( + address(validator_) != address(0), + "BridgeUpgradeable: validator is zero address" + ); + require( + feeReceiver_ != address(0), + "BridgeUpgradeable: feeReceiver is zero address" + ); BridgeStorage storage $ = _getBridgeStorage(); $.validator = validator_; $.feeReceiver = feeReceiver_; $.nativeSendAmount = nativeSendAmount_; emit ValidatorChanged(msg.sender, address(validator_)); emit FeeReceiverChanged(msg.sender, feeReceiver_); emit NativeSendAmountChanged(msg.sender, nativeSendAmount_); }
414-419
: Add balance checks for native currency transfers.This code does not confirm that the contract’s native currency balance is sufficient to cover the intended fee transfer, potentially causing a failed transaction or unexpected revert.
Apply this diff to validate sufficient balance:
function _sendFee(uint256 amount) private { + require( + address(this).balance >= amount, + "BridgeUpgradeable: insufficient native currency" + ); (bool sent,) = feeReceiver().call{value: amount}(""); if (!sent) { revert SendFailed(); } }
426-454
: Add reentrancy protection for token transfers.The
_transferClaim
function triggers external calls (e.g.,_unwrap
,.call
, andIERC20(token).transfer
) before or around state modifications, leaving it open to reentrant attacks if new logic is introduced in the future. Using the checks-effects-interactions pattern or a reentrancy guard can mitigate this.Here’s an example approach:
function _transferClaim( uint256 flags, address token, uint256 amount, address receiver ) private { + // Reentrancy guard or checks-effects-interactions approach if (pausedTokens(token)) { revert TokenIsPaused(token); } bool unlocked = false; if (token == samb() && flags & BridgeFlags.SHOULD_UNWRAP != 0) { _unwrap(amount); (unlocked,) = payable(receiver).call{value: amount}(""); } else { unlocked = IERC20(token).transfer(receiver, amount); } if (!unlocked) { revert TransferFailed(); } BridgeStorage storage $ = _getBridgeStorage(); if (flags & BridgeFlags.SEND_NATIVE_TO_RECEIVER != 0) { (bool sent,) = payable(receiver).call{value: $.nativeSendAmount}(""); if (!sent) { revert SendFailed(); } } }
611-611
: Add a storage gap for upgrade safety.Your contract inherits multiple upgradeable patterns but does not define a dedicated storage gap, which can result in storage collisions during future upgrades.
For example, at the end of the contract:
+ // gap for upgrade safety + uint256[50] private __gap;
479-479
:❓ Verification inconclusive
Verify the 65-bit flag shift for correctness.
Shifting the payload flags by 65 bits is unusual and may lead to unexpected behavior if incorrectly documented or tested. Please confirm that this shift aligns with the intended specification and that all bits are accounted for.
To verify, you could grep references to the flags usage and ensure that 65 bits is correct:
🏁 Script executed:
#!/bin/bash # Searching for the usage of the >> 65 shift and verifying consistent usage elsewhere rg -A 5 --literal "flags >> 65"Length of output: 445
Action: Verify the 65-Bit Shift Usage in Payload Flags
- The initial search command failed due to the incorrect use of the
--literal
flag. Please re-run the search using the correct option, for example:rg -F "flags >> 65" -C 5
- Manually review the code to ensure that shifting
payload.flags
by 65 bits is intentional and correctly implemented according to the flag specification.- Confirm that there are no unintended side effects and that all flag bits are appropriately accounted for.
bridge-evm/test/bridge_tests/BridgeSolanaSend.t.sol (2)
38-63
: Signature creation logic looks solid.The approach of creating a typed-data hash and using
vm.sign
is a standard Foundry pattern for forging ERC20 permit signatures. No issues observed.
65-90
: Validate large decimal differences for amount conversion.When
decimalsFrom
is significantly lower thandecimalsTo
, the multiplication could grow very large. Although Solidity 0.8 enforces safe arithmetic and will revert on overflow, confirm the maximum possible decimal difference to ensure it doesn't introduce unnecessary revert scenarios.Would you like a script to search for all caller usage of
_convertAmount
in the codebase to confirm safe usage?bridge-evm/contracts/BridgeSolana.sol (1)
31-34
: Confirm flag shifting and potentialtoUint64
overflow.
- The code shifts
payload.flags
by 65 bits: confirm that the data structure for flags accounts for these bits and that no critical bits are dropped.- The nonce is cast to
uint64
; verify that the system won't exceed 2^64 calls, or add safeguards if extremely high usage is anticipated.bridge-evm/test/BridgeSolana.t.sol (1)
48-109
: Overall setup logic looks good.Using coverage-based vs. standard deployment paths is a clean way to handle different environments, and the emitted events are tested thoroughly. No issues found.
bridge-evm/test/bridge_tests/BridgeSend.t.sol (2)
35-60
: Standard permit signing logic looks good.This approach follows typical Foundry/EIP-2612 patterns and is easy to maintain.
67-87
: Validate extreme decimal differences.While built-in overflow protection in Solidity 0.8 helps, large differences in decimals could still cause unintended reverts or extremely large multiplications. Consider additional checks to ensure safe decimal bounds or handle edge cases.
Would you like a shell script to search for tokens with unusual decimals in your tests or mock contracts?
address sender = payload.flags & BridgeFlags.SENDER_IS_TXORIGIN != 0 | ||
? tx.origin | ||
: msg.sender; |
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.
🛠️ Refactor suggestion
Avoid using tx.origin
for security reasons.
Relying on tx.origin
can enable phishing-like attacks and hamper composability. Typically, msg.sender
is the recommended approach. Unless you have a well-explained use case, consider removing or revising usage of tx.origin
.
Example adjustment:
-address sender = payload.flags & BridgeFlags.SENDER_IS_TXORIGIN != 0
- ? tx.origin
- : msg.sender;
+address sender = msg.sender;
📝 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.
address sender = payload.flags & BridgeFlags.SENDER_IS_TXORIGIN != 0 | |
? tx.origin | |
: msg.sender; | |
address sender = msg.sender; |
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: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
bridge-evm/contracts/BridgeSolana.sol
(1 hunks)bridge-evm/test/BridgeSolana.t.sol
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- bridge-evm/test/BridgeSolana.t.sol
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
🔇 Additional comments (2)
bridge-evm/contracts/BridgeSolana.sol (2)
53-53
:❓ Verification inconclusive
Validate the uint64 cast of nonce.
The nonce value is being cast to uint64 which might lead to truncation if the nonce grows too large.
🏁 Script executed:
#!/bin/bash # Search for nonce generation/management to understand potential values ast-grep --pattern $'function _useNonce($_) { $$$ }'Length of output: 55
Double-check nonce overflow handling
The automated script couldn't locate the implementation of
_useNonce
, so it's unclear whether the nonce value might ever exceed theuint64
range. Please manually verify:
- That
_useNonce
returns a value guaranteed to be within the 64-bit limit.- Whether any contract logic increments the nonce in a way that could potentially overflow
uint64
.This review comment remains a caution to ensure the casting does not introduce truncation issues if the nonce grows too large.
1-10
:✅ Verification successful
LGTM! Verify Solidity version compatibility.
The contract setup and imports look good. The use of SafeCast for type conversions and inheritance from BridgeUpgradeable are appropriate.
🌐 Web query:
What is the latest stable version of Solidity and what are its key features compared to 0.8.20?
💡 Result:
The latest stable version of Solidity is v0.8.28, released on October 9, 2024[1][8]. This version builds on previous releases with incremental improvements and new features.
Key Features of Solidity v0.8.28
- Transient Storage Support:
Full support for transient storage state variables of value types (tload
/tstore
), enabling temporary data storage tied to transaction execution (EIP-1153)[1][5].- Compiler Optimizations:
- Reduced memory usage by generating Yul AST JSON representations only when requested[1].
- Selective bytecode/IR generation for specific contracts via Standard JSON Interface[1].
- Bug Fixes:
- Resolved SMT logic errors in array assignments[1].
- Fixed Yul AST source location shifts in debug info[1].
Comparison with Solidity v0.8.20
Feature v0.8.20 (May 2023) v0.8.28 (Oct 2024) EVM Version Defaults to Shanghai ( PUSH0
support)[6]Maintains Cancun/Shanghai defaults[1][5] Gas Optimization Introduced storage layout optimizations[2] Enhanced via selective code generation[1] Transient Storage Limited inline assembly support (v0.8.24)[1] Full high-level language support (value types)[1][5] Compiler Pipeline Improved via-IR performance[6] Memory usage optimizations for large projects[1] New Opcodes MCOPY
optimization for bytecode size[5]Continued exploitation of MCOPY
/BLOBBASEFEE
[1][5]
Evolution Highlights
- v0.8.25 (March 2024): Integrated Dencun hard-fork features like blob transactions (EIP-4844) and refined
MCOPY
usage[1][5].- v0.8.27 (Sept 2024): Added legacy pipeline support for
require
with custom errors and IR compilation caching[5].For developers using v0.8.20, upgrading provides access to transient storage abstractions, refined compiler efficiency, and compatibility with Ethereum’s latest protocol upgrades[1][2][5].
Citations:
- 1: https://github.com/ethereum/solidity/releases
- 2: https://detectors.auditbase.com/solidity-0820-gas-optimization
- 3: https://forum.soliditylang.org/t/solidity-v0-8-20-was-just-released/1638
- 4: https://blog.oxor.io/exploring-the-bugs-and-features-of-solidity-compiler-versions-a-guide-for-smart-contract-fe04e852ea64
- 5: https://soliditylang.org/blog/category/releases/
- 6: https://soliditylang.org/blog/2023/05/10/solidity-0.8.20-release-announcement/
- 7: https://forum.openzeppelin.com/t/openzeppelin-requiring-solidity-0-8-20/38336
- 8: https://soliditylang.org/blog/2024/10/09/solidity-0.8.28-release-announcement/
- 9: https://forum.openzeppelin.com/t/quick-version-question/39887
- 10: https://docs.soliditylang.org
Solidity Version and Imports Verification
The contract setup and import statements in
bridge-evm/contracts/BridgeSolana.sol
are solid. The file correctly specifies the SPDX license, uses Solidity version ^0.8.20, and appropriately imports theIValidation
interface, OpenZeppelin’sSafeCast
library, and theBridgeUpgradeable
contract. These choices ensure secure type conversions and proper inheritance for bridge functionality.Additional Note:
While Solidity ^0.8.20 is stable and well-supported, the latest stable release is v0.8.28. This version offers benefits such as enhanced transient storage support, improved compiler optimizations, and various bug fixes. Although upgrading isn’t required for the current implementation, it may be worth considering to leverage these incremental improvements if the project timeline permits.Overall, the implementation is approved as-is.
/// Initialize the contract with the given parameters | ||
/// @param authority_ address of the authority contract [AccessManager](https://docs.openzeppelin.com/contracts/5.x/access-control#access-management) | ||
/// @param SAMB_ address of the Wrapped token contract | ||
/// @param validator_ address of the validator contract | ||
/// @param feeReceiver_ address of the fee receiver | ||
/// @param nativeSendAmount_ amount of native currency to send to the receiver in destination chain (here) if needed | ||
function initialize( | ||
address authority_, | ||
address tokenBeacon_, | ||
address SAMB_, | ||
IValidation validator_, | ||
address payable feeReceiver_, | ||
uint256 nativeSendAmount_ | ||
) | ||
public | ||
initializer | ||
{ | ||
__Bridge_init( | ||
authority_, tokenBeacon_, SAMB_, validator_, feeReceiver_, nativeSendAmount_ | ||
); | ||
} |
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.
🛠️ Refactor suggestion
Add input validation for critical parameters.
While the initialization is well-documented and properly uses the initializer modifier, it should validate the input parameters to prevent setting critical addresses to zero.
Add these checks before calling __Bridge_init
:
function initialize(
address authority_,
address tokenBeacon_,
address SAMB_,
IValidation validator_,
address payable feeReceiver_,
uint256 nativeSendAmount_
)
public
initializer
{
+ require(authority_ != address(0), "BridgeSolana: zero authority");
+ require(tokenBeacon_ != address(0), "BridgeSolana: zero token beacon");
+ require(SAMB_ != address(0), "BridgeSolana: zero SAMB");
+ require(address(validator_) != address(0), "BridgeSolana: zero validator");
+ require(feeReceiver_ != address(0), "BridgeSolana: zero fee receiver");
__Bridge_init(
authority_, tokenBeacon_, SAMB_, validator_, feeReceiver_, nativeSendAmount_
);
}
📝 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.
/// Initialize the contract with the given parameters | |
/// @param authority_ address of the authority contract [AccessManager](https://docs.openzeppelin.com/contracts/5.x/access-control#access-management) | |
/// @param SAMB_ address of the Wrapped token contract | |
/// @param validator_ address of the validator contract | |
/// @param feeReceiver_ address of the fee receiver | |
/// @param nativeSendAmount_ amount of native currency to send to the receiver in destination chain (here) if needed | |
function initialize( | |
address authority_, | |
address tokenBeacon_, | |
address SAMB_, | |
IValidation validator_, | |
address payable feeReceiver_, | |
uint256 nativeSendAmount_ | |
) | |
public | |
initializer | |
{ | |
__Bridge_init( | |
authority_, tokenBeacon_, SAMB_, validator_, feeReceiver_, nativeSendAmount_ | |
); | |
} | |
/// Initialize the contract with the given parameters | |
/// @param authority_ address of the authority contract [AccessManager](https://docs.openzeppelin.com/contracts/5.x/access-control#access-management) | |
/// @param SAMB_ address of the Wrapped token contract | |
/// @param validator_ address of the validator contract | |
/// @param feeReceiver_ address of the fee receiver | |
/// @param nativeSendAmount_ amount of native currency to send to the receiver in destination chain (here) if needed | |
function initialize( | |
address authority_, | |
address tokenBeacon_, | |
address SAMB_, | |
IValidation validator_, | |
address payable feeReceiver_, | |
uint256 nativeSendAmount_ | |
) | |
public | |
initializer | |
{ | |
require(authority_ != address(0), "BridgeSolana: zero authority"); | |
require(tokenBeacon_ != address(0), "BridgeSolana: zero token beacon"); | |
require(SAMB_ != address(0), "BridgeSolana: zero SAMB"); | |
require(address(validator_) != address(0), "BridgeSolana: zero validator"); | |
require(feeReceiver_ != address(0), "BridgeSolana: zero fee receiver"); | |
__Bridge_init( | |
authority_, tokenBeacon_, SAMB_, validator_, feeReceiver_, nativeSendAmount_ | |
); | |
} |
chainFrom: block.chainid, | ||
chainTo: payload.destChainId, | ||
eventId: _useNonce(address(this)), | ||
flags: payload.flags >> 65, // remove sender flags |
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.
💡 Verification agent
🧩 Analysis chain
Verify the flags bit manipulation.
The right shift by 65 bits (payload.flags >> 65
) might lose important flag data. Please document why exactly 65 bits are shifted and what flags are being removed.
🏁 Script executed:
#!/bin/bash
# Search for documentation or tests explaining the flags structure
rg -A 5 "flags.*>>" bridge-evm/
Length of output: 1698
Clarify the Flags Bit Manipulation
The expression payload.flags >> 65
is intended to remove the sender-specific flags, but the rationale for shifting exactly 65 bits remains unclear. Please add detailed documentation explaining:
- The bit allocation of the
flags
field (i.e., which bits represent sender flags and which represent other data). - Why exactly 65 bits are shifted off and how this operation ensures that no critical flag information is lost.
- Any implications this bit manipulation might have on receipt generation, especially since similar patterns appear in related files (e.g.,
BridgeUpgradeable.sol
andReceiptUtils.sol
).
function generateReceipt( | ||
address sender, | ||
bytes32 recipient, | ||
uint256 amountTo, | ||
SendPayload calldata payload, | ||
ExternalToken memory externalToken_ | ||
) internal override returns (FullReceipt memory){ | ||
FullReceipt memory _receipt = FullReceipt({ | ||
from: bytes32(uint256(uint160(sender))), | ||
to: recipient, | ||
tokenAddressFrom: payload.tokenAddress, | ||
tokenAddressTo: externalToken_.externalTokenAddress, | ||
amountFrom: payload.amountToSend, | ||
amountTo: amountTo, | ||
chainFrom: block.chainid, | ||
chainTo: payload.destChainId, | ||
eventId: _useNonce(address(this)), | ||
flags: payload.flags >> 65, // remove sender flags | ||
data: abi.encodePacked(_useNonce(recipient).toUint64()) | ||
}); | ||
return _receipt; | ||
} |
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.
🛠️ Refactor suggestion
Add validation for amountTo parameter.
The amountTo
parameter should be validated to ensure it's not zero and doesn't exceed any maximum limits.
Add these checks at the start of the function:
function generateReceipt(
address sender,
bytes32 recipient,
uint256 amountTo,
SendPayload calldata payload,
ExternalToken memory externalToken_
) internal override returns (FullReceipt memory) {
+ require(amountTo > 0, "BridgeSolana: zero amount");
+ require(amountTo <= type(uint256).max, "BridgeSolana: amount too large");
FullReceipt memory _receipt = FullReceipt({
📝 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.
function generateReceipt( | |
address sender, | |
bytes32 recipient, | |
uint256 amountTo, | |
SendPayload calldata payload, | |
ExternalToken memory externalToken_ | |
) internal override returns (FullReceipt memory){ | |
FullReceipt memory _receipt = FullReceipt({ | |
from: bytes32(uint256(uint160(sender))), | |
to: recipient, | |
tokenAddressFrom: payload.tokenAddress, | |
tokenAddressTo: externalToken_.externalTokenAddress, | |
amountFrom: payload.amountToSend, | |
amountTo: amountTo, | |
chainFrom: block.chainid, | |
chainTo: payload.destChainId, | |
eventId: _useNonce(address(this)), | |
flags: payload.flags >> 65, // remove sender flags | |
data: abi.encodePacked(_useNonce(recipient).toUint64()) | |
}); | |
return _receipt; | |
} | |
function generateReceipt( | |
address sender, | |
bytes32 recipient, | |
uint256 amountTo, | |
SendPayload calldata payload, | |
ExternalToken memory externalToken_ | |
) internal override returns (FullReceipt memory) { | |
require(amountTo > 0, "BridgeSolana: zero amount"); | |
require(amountTo <= type(uint256).max, "BridgeSolana: amount too large"); | |
FullReceipt memory _receipt = FullReceipt({ | |
from: bytes32(uint256(uint160(sender))), | |
to: recipient, | |
tokenAddressFrom: payload.tokenAddress, | |
tokenAddressTo: externalToken_.externalTokenAddress, | |
amountFrom: payload.amountToSend, | |
amountTo: amountTo, | |
chainFrom: block.chainid, | |
chainTo: payload.destChainId, | |
eventId: _useNonce(address(this)), | |
flags: payload.flags >> 65, // remove sender flags | |
data: abi.encodePacked(_useNonce(recipient).toUint64()) | |
}); | |
return _receipt; | |
} |
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: 8
♻️ Duplicate comments (5)
bridge-evm/script/DeployerBase.s.sol (3)
146-148
:⚠️ Potential issueFix incorrect admin role check.
The function checks the admin role against
adminCandidate
instead ofmsg.sender
, which could allow unauthorized access.- (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + (bool isSenderAdmin,) = + authority.hasRole(authority.ADMIN_ROLE(), msg.sender);
179-181
:⚠️ Potential issueFix incorrect admin role check in removeAuthorityAdmin.
Similar to setAuthorityAdmin, this function also checks the admin role against
adminCandidate
instead ofmsg.sender
.- (bool isSenderAdmin,) = - authority.hasRole(authority.ADMIN_ROLE(), adminCandidate); + (bool isSenderAdmin,) = + authority.hasRole(authority.ADMIN_ROLE(), msg.sender);
282-319
: 🛠️ Refactor suggestionAdd validation for dependent contracts in Bridge deployment.
The Bridge contract depends on other contracts that should be validated before deployment.
function deployBridge() public returns (Bridge) { + require(address(authority) != address(0), "Authority not initialized"); + require(address(tokenBeacon) != address(0), "TokenBeacon not initialized"); + require(address(validator) != address(0), "Validator not initialized"); address wrappedToken = vm.envAddress("WRAPPED_TOKEN");bridge-evm/test/Validator.t.sol (2)
354-362
:⚠️ Potential issueConsider adding signature malleability check.
The
signPayload
function should verify that the signature is not malleable to prevent potential security vulnerabilities.Apply this diff to add the signature malleability check:
function signPayload( BridgeTypes.SendPayload memory payload, Signer memory signer ) internal pure returns (bytes memory signature) { bytes32 digest = payload.toHash(); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer.PK, digest); + // Check for signature malleability + require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, + "ECDSA: invalid signature 's' value"); signature = abi.encodePacked(r, s, v); return signature; }
431-442
:⚠️ Potential issueAdd validation for maximum number of signers.
The
signReceipt
function should validate the maximum number of signers to prevent excessive gas consumption.Apply this diff to add the validation:
function signReceipt(BridgeTypes.MiniReceipt memory receipt) internal returns (bytes memory signature) { bytes32 digest = receipt.toHash(); + require(signers.length <= 100, "Too many signers"); // Adjust limit as needed for (uint256 i = 0; i < signers.length; i++) { validatorInstance.addValidator(signers[i].Address); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].PK, digest); bytes memory signerSignature = abi.encodePacked(r, s, v); signature = bytes.concat(signature, signerSignature); } return signature; }
🧹 Nitpick comments (39)
bridge-evm/test/bridge_tests/BridgeClaim.t.sol (3)
35-46
: Consider aligning signature component order with vm.sign output.The comment on line 42 indicates a different order of signature components (r,s,v) compared to vm.sign output (v,r,s). This mismatch could lead to confusion.
Consider either:
- Aligning the order with vm.sign:
- bytes memory signerSignature = abi.encodePacked(r, s, v); // note the order here is different from line above. + bytes memory signerSignature = abi.encodePacked(v, r, s); // matches vm.sign order
- Or clarifying why a different order is necessary:
- bytes memory signerSignature = abi.encodePacked(r, s, v); // note the order here is different from line above. + bytes memory signerSignature = abi.encodePacked(r, s, v); // order required by the bridge contract: (r,s,v)
48-82
: Add bounds checking for amount parameter.The
test_claim_withFullReceipt
andtest_claim_withMiniReceipt
functions accept an unboundedamount
parameter. Consider adding bounds to prevent overflow/underflow scenarios.Add parameter bounds:
function test_claim_withFullReceipt( uint256 amount + ) public returns (address) { + vm.assume(amount > 0 && amount < type(uint256).max);Also applies to: 84-119
48-408
: Add NatSpec documentation for test scenarios.The test functions would benefit from documentation explaining the test scenarios and expected outcomes.
Add NatSpec documentation:
+ /// @notice Tests claiming tokens with a full receipt + /// @param amount The amount of tokens to claim + /// @return The address of the deployed token function test_claim_withFullReceipt( uint256 amount ) public returns (address) {bridge-evm/test/Nonces.t.sol (3)
56-82
: Consider adding edge case tests to the fuzz testing.While the current fuzz testing is solid, consider adding tests for:
- Maximum uint256 values
- Zero address
- Common special values (e.g., type(uint256).max - 1)
function test_fuzz_useNonce( bytes32 keyBytes, uint256 keyUint, address owner ) public { vm.assume( - keyBytes != bytes32(keyUint) && keyUint != uint256(uint160(owner)) + keyBytes != bytes32(keyUint) && + keyUint != uint256(uint160(owner)) && + owner != address(0) ); + + // Test with maximum values + mockNonce.useNonce(type(uint256).max); + assertEq(mockNonce.nonces(type(uint256).max), 1); + uint256 currentNonceAddress = mockNonce.nonces(owner);
99-159
: Add overflow testing for nonce operations.The current tests verify basic incrementing behavior well, but should also verify behavior when nonces approach their maximum value.
function test_useNonce_by_address() public { + // Test overflow scenario + vm.mockCall( + address(mockNonce), + abi.encodeWithSelector(mockNonce.nonces.selector, alice), + abi.encode(type(uint256).max) + ); + mockNonce.useNonce(alice); + assertEq(mockNonce.nonces(alice), 0); + assertEq(mockNonce.nonces(alice), 0); mockNonce.useNonce(alice);
160-170
: Expand error handling test coverage.Consider adding tests for additional error scenarios:
- Multiple consecutive invalid nonce attempts
- Invalid nonce with different key types
- Boundary conditions (e.g., type(uint256).max)
function test_revertIf_useCheckedNonce_that_NotExpected() public { uint256 currentNonce = mockNonce.nonces(alice); vm.expectRevert( abi.encodeWithSelector( NoncesUpgradeable.InvalidAccountNonce.selector, uint256(uint160(alice)), currentNonce ) ); mockNonce.useCheckedNonce(alice, currentNonce + 1); + + // Test with maximum nonce value + vm.mockCall( + address(mockNonce), + abi.encodeWithSelector(mockNonce.nonces.selector, alice), + abi.encode(type(uint256).max) + ); + vm.expectRevert( + abi.encodeWithSelector( + NoncesUpgradeable.InvalidAccountNonce.selector, + uint256(uint160(alice)), + type(uint256).max + ) + ); + mockNonce.useCheckedNonce(alice, 0); }bridge-evm/script/DeployerBase.s.sol (3)
59-93
: Remove commented-out code.The function contains commented-out code that should be removed to maintain code cleanliness.
- // for (uint256 i = 0; i < deploymentsJson.length; i++) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, deploymentsJson[i])); - // if (i < deploymentsJson.length - 1) { - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, ",")); - // } - // } - // deploymentsJsonArray = string(abi.encodePacked(deploymentsJsonArray, "]"));
67-67
: Fix hardcoded string value.The hardcoded string "contracts" should be a constant to maintain consistency and avoid typos.
+ string constant CONTRACTS_KEY = "contracts"; - string memory deploymentJson = "contracts"; + string memory deploymentJson = CONTRACTS_KEY;
198-213
: Optimize deployment records update logic.The current implementation creates a new array and potentially wastes gas by copying all elements. Consider using a mapping for O(1) lookups and updates.
+ mapping(string => Deployment) private deployments; + function addDeployment(Deployment memory deployment) public { - Deployment[] memory deployments = getDeployments(); - Deployment[] memory newDeployments = - new Deployment[](deployments.length + 1); - newDeployments[deployments.length] = deployment; - for (uint256 i = 0; i < deployments.length; i++) { - if ( - Strings.equal( - deployments[i].contractName, deployment.contractName - ) - ) { - newDeployments[i] = deployments[i]; - delete newDeployments[deployments.length]; - } else { - newDeployments[i] = deployments[i]; - } - } - writeDeployments(newDeployments); + deployments[deployment.contractName] = deployment; + emit DeploymentUpdated(deployment.contractName, deployment.proxyAddress, deployment.implementationAddress); }bridge-evm/contracts/utils/PayloadUtils.sol (1)
12-21
: Consider removing the wrapper function.The
toHash
function is a simple wrapper aroundtoEthSignedMessageHash
. Consider removing it to reduce code surface area since it doesn't add significant value beyond being a shortcut.bridge-evm/test/bridge_tests/BridgeBase.t.sol (3)
58-62
: Consider using themakeAddr
function for test addresses.Instead of hardcoding test addresses, consider using Forge's
makeAddr
function for consistency with how you're creating signer addresses. This would also provide more meaningful addresses in test traces.- address alice = address(0xA11ce); - address bob = address(0xB0b); - address chris = address(0xC14); - address deadBeef = address(0xDeadBeef); + address alice = makeAddr("alice"); + address bob = makeAddr("bob"); + address chris = makeAddr("chris"); + address deadBeef = makeAddr("deadBeef");
91-201
: Consider refactoring to reduce code duplication in proxy deployments.The proxy deployment logic is duplicated between coverage and non-coverage paths. Consider extracting the common initialization parameters and using a helper function.
+ function deployProxy( + address implementation, + string memory contractName, + bytes memory initData + ) internal returns (address) { + if (isCoverage()) { + return address( + UnsafeUpgrades.deployUUPSProxy( + implementation, + initData + ) + ); + } + return address( + Upgrades.deployUUPSProxy( + contractName, + initData + ) + ); + } function setUpValidator( address authorityAddress, address[] memory validators, address pldSigner, uint256 feeValidityWindow ) public virtual returns (Validator) { - address proxy; + bytes memory initData = abi.encodeCall( + Validator.initialize, + (authorityAddress, validators, pldSigner, feeValidityWindow) + ); // Event checks... - if (isCoverage()) { - address validator = address(new Validator()); - proxy = address( - UnsafeUpgrades.deployUUPSProxy( - validator, - abi.encodeCall(...) - ) - ); - } else { - proxy = address( - Upgrades.deployUUPSProxy( - "Validator.sol", - abi.encodeCall(...) - ) - ); - } + address implementation = isCoverage() ? address(new Validator()) : address(0); + address proxy = deployProxy(implementation, "Validator.sol", initData); validatorInstance = Validator(proxy); return validatorInstance; }
207-213
: Consider using a more efficient way to generate signer addresses.The current implementation concatenates strings for each signer. Consider using a simpler format that doesn't require string concatenation.
- (address signer, uint256 signerPk) = makeAddrAndKey( - string.concat("relayer", Strings.toString(i + 1)) - ); + (address signer, uint256 signerPk) = makeAddrAndKey( + string(abi.encodePacked("relayer", i + 1)) + );bridge-evm/script/Send.s.sol (4)
3-3
: Consider removing unnecessary ABIv2 pragma.
Solidity 0.8.0 and later versions include the functionalities of ABI coder v2 by default, sopragma abicoder v2;
is no longer necessary.-pragma abicoder v2;
15-16
: Clarify the alphabetical order requirement.
The comment “There is a additional struct because parser expects alphabetical order” may confuse future maintainers. It would be more helpful to elaborate why alphabetical ordering is needed in the JSON parsing context.
59-63
: Explain or parameterize the hard-coded message ID.
The value0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC
appears to be a placeholder. Consider making this an explicit input parameter or adding a comment explaining its significance in bridging operations.
52-67
: Validate bridging logic and revert handling.
While broadcasting transactions and callingbridge.send{value: payload.feeAmount}
, be sure to handle potential token and fee reverts. If thebridge
contract reverts, it will exit silently here. Consider logging or re-verifying post-call results to confirm a successful transfer.bridge-evm/test/ReceiptUtils.t.sol (2)
14-28
: Optimize hex conversion using OpenZeppelin utilities.The current implementation is inefficient as it creates a new buffer and performs expensive string operations in a loop. Consider using OpenZeppelin's
Strings.toHexString
with thememory
keyword for bytes arrays.- function iToHex( - bytes memory buffer - ) public pure returns (string memory) { - // Fixed buffer size for hexadecimal convertion - bytes memory converted = new bytes(buffer.length * 2); - - bytes memory _base = "0123456789abcdef"; - - for (uint256 i = 0; i < buffer.length; i++) { - converted[i * 2] = _base[uint8(buffer[i]) / _base.length]; - converted[i * 2 + 1] = _base[uint8(buffer[i]) % _base.length]; - } - - return string(abi.encodePacked("0x", converted)); - } + function iToHex(bytes memory buffer) public pure returns (string memory) { + return Strings.toHexString(uint256(bytes32(buffer)), buffer.length); + }
82-123
: Reduce code duplication in receipt tests.The mini receipt test duplicates much of the FFI setup and execution logic from the full receipt test.
Extract common FFI logic to a helper function:
+ function executeReceiptHash( + string memory receiptType, + string[] memory params + ) private returns (bytes32) { + string[] memory runJsInputs = new string[](params.length + 3); + runJsInputs[0] = "node"; + runJsInputs[1] = JS_RECEIPT_HASH_PATH; + runJsInputs[2] = receiptType; + for (uint i = 0; i < params.length; i++) { + runJsInputs[i + 3] = params[i]; + } + + bytes memory jsResult; + try vm.ffi(runJsInputs) returns (bytes memory result) { + jsResult = result; + } catch { + fail("JavaScript execution failed"); + } + return abi.decode(jsResult, (bytes32)); + }Then update both test functions to use it:
function test_fuzz_miniReceipt2hash( // ... params ... ) public { - string[] memory runJsInputs = new string[](11); BridgeTypes.MiniReceipt memory receipt = BridgeTypes.MiniReceipt({ // ... setup ... }); - // Build ffi command string - runJsInputs[0] = "node"; - runJsInputs[1] = "./test/differential_testing/receipt2hash.js"; - runJsInputs[2] = "--mini"; + string[] memory params = new string[](8); + params[0] = Strings.toHexString(uint256(to), 32); + // ... fill other params ... + + bytes32 jsGenerated = executeReceiptHash("--mini", params); - // Run command and capture output - bytes memory jsResult = vm.ffi(runJsInputs); - bytes32 jsGenerated = abi.decode(jsResult, (bytes32)); bytes32 expectedHash = ReceiptUtils.toHash(receipt); assertEq(expectedHash, jsGenerated); }bridge-evm/contracts/token/ERC20Bridged.sol (1)
157-176
: Consider emitting dedicated bridging events.
When tokens are minted or burned due to bridging, it might be helpful to emit specific events likeBridgeMint
andBridgeBurn
. This can enhance traceability when analyzing logs, distinguishing normal ERC20 transfers from bridging operations.Would you like me to propose an event-based approach that clarifies when tokens are bridged in or out?
bridge-evm/contracts/interface/ITokenManager.sol (2)
3-3
: Consider removing the explicitpragma abicoder v2
.Solidity v0.8.20 uses ABI coder v2 by default. This line is no longer strictly necessary.
85-132
: Clarify usage scenario for the overloadedaddToken
methods.There are two versions of
addToken
—one with apaused
parameter and one without. While overloading is acceptable, consider adding more descriptive docstrings indicating when each version should be used to ensure clarity and maintainability.bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol (3)
61-68
: Consider adding a zero-address safeguard inisBridgable
.If
token.toAddress()
results in the zero address (e.g., due to an invalid input), it may lead to unexpected bridging logic or skip necessary checks. A revert for zero addresses could help prevent misuse.
198-226
: Review ordering and grouping of emitted events.The
_addToken
function emitsTokenMapped
thenTokenAdded
. To make downstream event handling more predictable, ensure the sequence of emitted events is clearly defined. You may also clarify the event flow in docs.
286-286
: Address theFIXME
regarding removing mapped external tokens.There is a note indicating incomplete logic when removing tokens that remain mapped. Consider implementing or clarifying whether removal should revert if any mapping still exists, or whether the mapping should be automatically cleaned up.
bridge-evm/test/bridge_tests/BridgeSolanaSend.t.sol (5)
31-31
: Remove unnecessary comment.The comment "Huge mess cuz Stack too deep error" is not professional and doesn't provide meaningful information. Consider documenting the actual reason for the abstraction or remove the comment.
-// Huge mess cuz Stack too deep error
38-59
: Enhance permit signing function with additional validation.The
signPermit
function should validate input parameters to prevent potential issues:
- Check for zero addresses in owner and spender
- Ensure deadline is not in the past
- Validate token address is not zero
function signPermit( address token, address owner, address spender, uint256 value, uint256 nonce, uint256 deadline, uint256 PK ) public view returns (uint8 v, bytes32 r, bytes32 s) { + require(token != address(0), "Invalid token address"); + require(owner != address(0), "Invalid owner address"); + require(spender != address(0), "Invalid spender address"); + require(deadline > block.timestamp, "Deadline must be in future"); + SigUtils.Permit memory permit = SigUtils.Permit({ owner: owner, spender: spender, value: value, nonce: nonce, deadline: deadline });
61-82
: Improve documentation and add validation for _convertAmount function.The function needs:
- Input validation for zero address
- Better documentation of the conversion logic
- Handling of potential overflow cases
/// Convert the amount based on token decimals /// @param tokenFrom address of the token /// @param amount amount to convert /// @param decimalsTo token decimals +/// @dev Converts amount between different decimal places, handling both scaling up and down +/// @dev For scaling up: amount * 10^(decimalsTo - decimalsFrom) +/// @dev For scaling down: amount / 10^(decimalsFrom - decimalsTo) /// @return convertedAmount converted amount function _convertAmount( address tokenFrom, uint256 amount, uint8 decimalsTo ) private view returns (uint256 convertedAmount) { + require(tokenFrom != address(0), "Invalid token address"); + IERC20Metadata token = IERC20Metadata(tokenFrom); uint8 decimalsFrom = token.decimals(); + + // Prevent overflow when scaling up + require(decimalsTo <= 77, "Decimals too large"); // 256 - 77 > 2^128 + if (decimalsFrom < decimalsTo) { // Ex.: 1234567890 with 3 decimals to 6 decimals => 1234567_890 * 10 ** (6 - 3) = 1234567_890000 + uint256 scale = 10 ** uint256(decimalsTo - decimalsFrom); + require(amount <= type(uint256).max / scale, "Amount too large to scale up"); return amount * (10 ** uint256(decimalsTo - decimalsFrom)); } else if (decimalsFrom > decimalsTo) { // Ex.: 1234567890 with 6 decimals to 3 decimals => 1234_567890 / 10 ** (6 - 3) = 1234_567 return amount / (10 ** uint256(decimalsFrom - decimalsTo)); } else { return amount; } }
84-129
: Enhance generateSendingValues with additional validation and documentation.The function should:
- Validate input parameters
- Add comprehensive documentation
- Handle potential edge cases
+/// @notice Generates payload and receipt for sending tokens across chains +/// @dev Handles both native and ERC20 token transfers +/// @param token The address of the token to send +/// @param amountToSend The amount of tokens to send +/// @param feeAmount The fee amount in native currency +/// @param flags Additional flags for the transfer +/// @param sender The address initiating the transfer +/// @param recipient The recipient address on the destination chain +/// @param chainDest The destination chain identifier +/// @return payload The generated send payload +/// @return receipt The generated transfer receipt +/// @return payloadSignature The signature for the payload function generateSendingValues( address token, uint256 amountToSend, uint256 feeAmount, uint256 flags, address sender, bytes32 recipient, uint256 chainDest ) public view returns ( BridgeTypes.SendPayload memory payload, BridgeTypes.FullReceipt memory receipt, bytes memory payloadSignature ) { + require(token != address(0), "Invalid token address"); + require(sender != address(0), "Invalid sender address"); + require(recipient != bytes32(0), "Invalid recipient"); + require(chainDest != block.chainid, "Invalid destination chain"); + payload = BridgeTypes.SendPayload({ destChainId: chainDest, tokenAddress: bytes32(uint256(uint160(token))),
433-454
: Improve test case for native token sending.The test case should:
- Test with multiple amounts
- Verify wrapped token balance
- Add assertions for events
function test_sendingToBridge_native( uint256 amountToSend ) public { vm.assume(amountToSend > 0 && amountToSend < 1000 ether); Signer memory signer = prepareSendNative(amountToSend); + + // Record initial balances + uint256 initialWrappedBalance = wrappedToken.balanceOf(address(bridgeInstance)); + uint256 destinationChain = uint256(bytes32("SOLANA")); uint256 feeAmount = 1000 wei; ( BridgeTypes.SendPayload memory payload, BridgeTypes.FullReceipt memory receipt, bytes memory payloadSignature ) = generateSendingValues( address(wrappedToken), amountToSend, feeAmount, BridgeFlags.SHOULD_WRAP, signer.Address, bytes32("SOLANA_ADDRESS"), destinationChain ); + + // Expect TokenWrapped event + vm.expectEmit(address(wrappedToken)); + emit IWETH9.Deposit(address(bridgeInstance), amountToSend); + sendNative(signer, payload, receipt, payloadSignature); + + // Verify wrapped token balance increased + assertEq( + wrappedToken.balanceOf(address(bridgeInstance)), + initialWrappedBalance + amountToSend, + "Wrapped token balance mismatch" + ); }bridge-evm/contracts/utils/AddressUtils.sol (2)
14-18
: Add error handling for zero values.The address conversion functions should handle zero values explicitly to prevent silent failures.
Apply this diff:
function toAddressBE( bytes32 value ) internal pure returns (address converted) { + require(value != 0, "AddressUtils: zero value"); return address(uint160(uint256(value))); } function toAddressLE( bytes32 value ) internal pure returns (address converted) { + require(value != 0, "AddressUtils: zero value"); return address(uint160(bytes20(value))); }Also applies to: 24-28
55-59
: Add validation for empty strings.The string to address conversion should validate that the input string is not empty.
Apply this diff:
function toAddress( string memory _address ) public pure returns (address converted) { + require(bytes(_address).length > 0, "AddressUtils: empty string"); return _address.parseAddress(); }
bridge-evm/test/AddressUtils.t.sol (1)
20-91
: Add test cases for edge cases.The fuzz tests should include specific test cases for edge values like zero addresses and invalid strings.
Add these test cases:
+ function test_zero_address() public { + bytes32 zero = bytes32(0); + vm.expectRevert("AddressUtils: zero value"); + AddressUtils.toAddressBE(zero); + vm.expectRevert("AddressUtils: zero value"); + AddressUtils.toAddressLE(zero); + } + + function test_empty_string() public { + string memory empty = ""; + vm.expectRevert("AddressUtils: empty string"); + AddressUtils.toAddress(empty); + }bridge-evm/script/CreateClaimSignature.s.sol (1)
49-57
: Improve error handling messages.The error messages should include the specific error details for better debugging.
Apply this diff:
} catch (bytes memory error) { - console.log("Error reading receipt"); + console.log("Error reading receipt from file:", path); console.log(vm.toString(error)); revert(); } catch Error(string memory reason) { - console.log("Error reading receipt"); + console.log("Error parsing receipt from file:", path); console.log(reason); revert(); }bridge-evm/test/bridge_tests/TokenManager.t.sol (1)
27-43
: Add validation for decimals parameter.The function should validate that the decimals parameter is within reasonable bounds for ERC20 tokens.
Apply this diff to add validation:
function addToken( address token, bytes32 externalTokenAddress, uint8 decimals ) public { + require(decimals <= 18, "Decimals must be <= 18"); // Standard ERC20 max decimals ITokenManager.ExternalTokenUnmapped memory externalToken = ITokenManager .ExternalTokenUnmapped({ externalTokenAddress: externalTokenAddress, decimals: decimals }); vm.expectEmit(address(bridgeInstance)); emit ITokenManager.TokenAdded(token); bridgeInstance.addToken(token, externalToken); assertEq(bridgeInstance.bridgableTokens(token), true); assertEq(bridgeInstance.external2token(externalTokenAddress), token); assertEq(bridgeInstance.pausedTokens(token), true); }
bridge-evm/test/bridge_tests/BridgeSend.t.sol (2)
25-28
: Refactor to eliminate “stack too deep” code smell.
The comment “// Huge mess cuz Stack too deep error” indicates potential over-complexity. Consider breaking large functions into smaller helpers or refactoring variable usage to improve readability and maintainability.
168-212
: Reduce duplication acrossprepareSend
andprepareSendNative
.
Multiple overloads share most logic (time warp, token addition, balances, deals). Consider consolidating these into a single, configurable helper to reduce boilerplate and ease maintenance.Also applies to: 214-228
bridge-evm/test/Validator.t.sol (2)
214-223
: Consider parameterizing test data.The hardcoded test data in
payloadCommon
andreceiptCommon
could be made more maintainable by extracting it into helper functions or constants.Consider refactoring to use helper functions that generate test data with customizable parameters:
+ function createTestPayload( + uint256 destChainId, + address tokenAddress, + bytes32 externalTokenAddress, + uint256 amountToSend, + uint256 feeAmount + ) internal view returns (BridgeTypes.SendPayload memory) { + return BridgeTypes.SendPayload({ + destChainId: destChainId, + tokenAddress: bytes32(uint256(uint160(tokenAddress))), + externalTokenAddress: externalTokenAddress, + amountToSend: amountToSend, + feeAmount: feeAmount, + timestamp: block.timestamp, + flags: 0, + flagData: bytes("SOME_USEFUL_DATA") + }); + }Also applies to: 225-237
380-390
: Simplify assembly block usage.The duplicate assembly blocks for signature component extraction could be simplified into a single helper function.
Consider refactoring to use a helper function:
+ function extractSignatureComponents(bytes memory signature) + internal + pure + returns (uint8 v, bytes32 r, bytes32 s) + { + assembly ("memory-safe") { + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + v := byte(0, mload(add(signature, 0x60))) + } + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (39)
bridge-evm/contracts/Bridge.sol
(1 hunks)bridge-evm/contracts/BridgeSolana.sol
(1 hunks)bridge-evm/contracts/Validator.sol
(1 hunks)bridge-evm/contracts/interface/IBridge.sol
(1 hunks)bridge-evm/contracts/interface/ITokenManager.sol
(1 hunks)bridge-evm/contracts/interface/IValidation.sol
(1 hunks)bridge-evm/contracts/interface/IValidatorV1.sol
(1 hunks)bridge-evm/contracts/interface/IWrapped.sol
(1 hunks)bridge-evm/contracts/token/ERC20Bridged.sol
(1 hunks)bridge-evm/contracts/token/TokenBeacon.sol
(1 hunks)bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol
(1 hunks)bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol
(1 hunks)bridge-evm/contracts/upgradeable/ValidatorUpgradeable.sol
(1 hunks)bridge-evm/contracts/utils/AddressUtils.sol
(1 hunks)bridge-evm/contracts/utils/NoncesUpgradeable.sol
(1 hunks)bridge-evm/contracts/utils/PayloadUtils.sol
(1 hunks)bridge-evm/contracts/utils/ReceiptUtils.sol
(1 hunks)bridge-evm/foundry.toml
(1 hunks)bridge-evm/script/Claim.s.sol
(1 hunks)bridge-evm/script/CreateClaimSignature.s.sol
(1 hunks)bridge-evm/script/CreatePayloadSignature.s.sol
(1 hunks)bridge-evm/script/DeployerBase.s.sol
(1 hunks)bridge-evm/script/Send.s.sol
(1 hunks)bridge-evm/test/AddressUtils.t.sol
(1 hunks)bridge-evm/test/Bridge.t.sol
(1 hunks)bridge-evm/test/BridgeSolana.t.sol
(1 hunks)bridge-evm/test/ERC20Bridged.t.sol
(1 hunks)bridge-evm/test/Nonces.t.sol
(1 hunks)bridge-evm/test/PayloadUtils.t.sol
(1 hunks)bridge-evm/test/ReceiptUtils.t.sol
(1 hunks)bridge-evm/test/SigUtils.sol
(1 hunks)bridge-evm/test/Validator.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeBase.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeClaim.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeSend.t.sol
(1 hunks)bridge-evm/test/bridge_tests/BridgeSolanaSend.t.sol
(1 hunks)bridge-evm/test/bridge_tests/TokenManager.t.sol
(1 hunks)bridge-evm/test/mocks/MockNonce.sol
(1 hunks)bridge-evm/test/mocks/sAMB.sol
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (18)
- bridge-evm/contracts/token/TokenBeacon.sol
- bridge-evm/test/mocks/sAMB.sol
- bridge-evm/test/Bridge.t.sol
- bridge-evm/contracts/interface/IWrapped.sol
- bridge-evm/foundry.toml
- bridge-evm/script/Claim.s.sol
- bridge-evm/test/SigUtils.sol
- bridge-evm/contracts/utils/ReceiptUtils.sol
- bridge-evm/script/CreatePayloadSignature.s.sol
- bridge-evm/test/mocks/MockNonce.sol
- bridge-evm/contracts/interface/IValidatorV1.sol
- bridge-evm/test/PayloadUtils.t.sol
- bridge-evm/test/BridgeSolana.t.sol
- bridge-evm/test/ERC20Bridged.t.sol
- bridge-evm/contracts/interface/IValidation.sol
- bridge-evm/contracts/upgradeable/ValidatorUpgradeable.sol
- bridge-evm/contracts/utils/NoncesUpgradeable.sol
- bridge-evm/contracts/interface/IBridge.sol
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Foundry project
🔇 Additional comments (35)
bridge-evm/test/bridge_tests/BridgeClaim.t.sol (2)
1-34
: Well-structured test contract setup!The contract follows best practices with:
- Latest stable Solidity version
- Proper organization of imports
- Efficient use of OpenZeppelin contracts and data structures
269-305
: LGTM! Thorough test for wrapped token unwrapping.The test properly verifies:
- Token wrapping and unwrapping
- Balance changes
- Event emissions
- Claim status
bridge-evm/test/Nonces.t.sol (2)
1-54
: LGTM! Well-structured test setup with proper initialization.The contract setup demonstrates good practices:
- Clear separation of test data
- Proper handling of upgradeable contracts
- Smart coverage mode detection
84-97
: LGTM! Clear and focused initial state verification.The tests effectively verify zero initialization for all key types.
bridge-evm/script/DeployerBase.s.sol (4)
1-26
: LGTM! Well-structured contract with appropriate imports.The contract structure follows best practices with clear organization of imports and state variables.
109-138
: LGTM! Robust deployment checking implementation.The function thoroughly checks deployment status and handles different deployment scenarios (implementation-only, proxy, or not deployed).
321-361
: LGTM! Well-implemented contract retrieval functions.The functions follow a consistent pattern and properly handle both existing and new deployments.
363-363
: LGTM! Appropriate virtual function implementation.The empty virtual function allows derived contracts to implement their own deployment logic.
bridge-evm/contracts/utils/PayloadUtils.sol (2)
1-8
: LGTM! Well-structured file header with appropriate imports.The file uses the latest stable Solidity version and correctly imports the required dependencies.
9-11
: LGTM! Good use of library pattern and type extension.The library pattern is well-suited for these utility functions, and the
using
directive correctly extendsbytes32
with MessageHashUtils functionality.bridge-evm/test/bridge_tests/BridgeBase.t.sol (2)
1-34
: LGTM! Well-organized imports and appropriate Solidity version.The file uses a recent Solidity version and has logically grouped imports from external libraries and local contracts.
74-89
: LGTM! Well-structured setup functions.The setup functions are consistently implemented, properly scoped, and allow for flexibility through the
virtual
modifier.bridge-evm/script/Send.s.sol (1)
57-57
: Validate the token contract address.
The function converts a 32-byte value to a 20-byte address viatoAddress()
. Ensure that the top 12 bytes are zeroed or that the address is properly encoded to avoid runtime errors or unexpected behavior with non-standard addresses.bridge-evm/test/ReceiptUtils.t.sol (1)
1-12
: LGTM! Contract setup and imports are well-structured.The file has appropriate license, pragma version, and necessary imports for testing.
bridge-evm/contracts/token/ERC20Bridged.sol (1)
87-89
: Enforce a non-zero bridge address.
The_bridge
field is initialized without checking ifbridge_
is the zero address. Deploying with a zero bridge address could lead to minting and burning inconsistencies.You might consider adding a check:
+ require(bridge_ != address(0), "Bridge address cannot be zero"); BridgedERC20Storage storage $ = _getERC20AdditionalStorage(); $._decimals = decimals_; $._bridge = bridge_;
bridge-evm/contracts/interface/ITokenManager.sol (1)
1-185
: All other interface changes appear well-defined.No additional concerns noted. The event declarations, errors, and function signatures comprehensively cover token-bridging scenarios.
bridge-evm/contracts/upgradeable/TokenManagerUpgradeable.sol (1)
14-356
: Overall contract design is solid.The approach to bridging, upgradability, and state management is cohesive. Apart from the minor points noted, no significant issues stand out.
bridge-evm/contracts/upgradeable/BridgeUpgradeable.sol (5)
26-32
: Add storage gap to prevent potential upgrade collisions.As previously noted in older review comments, including a storage gap helps avoid storage layout conflicts in future versions of upgradeable contracts.
79-86
: Validate critical addresses in initialization.A past review suggested requiring
validator_
andfeeReceiver_
to be non-zero before setting them. Leaving them unverified risks a contract lockup if set toaddress(0)
.
395-418
: Add reentrancy safeguards for token transfers.This logic was highlighted before. Moving or wrapping tokens and sending fees in the same function without a reentrancy guard can be exploitable. Consider using checks-effects-interactions or a dedicated reentrancy guard.
420-429
: Check for sufficient balance before sending the fee.Similar to a past comment, confirm the contract holds enough native currency to cover the fee. Otherwise, the
.call{value: amount}
could fail.
1-539
: Bridging logic is comprehensive.Beyond repetition of prior suggestions, the implementation encapsulates chain-to-chain bridging well. Good abstraction of shared logic into reusable internal functions.
bridge-evm/contracts/BridgeSolana.sol (3)
19-35
: Add input validation for critical parameters.While the initialization is well-documented, it should validate the input parameters to prevent setting critical addresses to zero.
Apply this diff to add validation:
function initialize( address authority_, address tokenBeacon_, address SAMB_, IValidation validator_, address payable feeReceiver_, uint256 nativeSendAmount_ ) public initializer { + require(authority_ != address(0), "BridgeSolana: zero authority"); + require(tokenBeacon_ != address(0), "BridgeSolana: zero token beacon"); + require(SAMB_ != address(0), "BridgeSolana: zero SAMB"); + require(address(validator_) != address(0), "BridgeSolana: zero validator"); + require(feeReceiver_ != address(0), "BridgeSolana: zero fee receiver"); __Bridge_init( authority_, tokenBeacon_, SAMB_, validator_, feeReceiver_, nativeSendAmount_ ); }
56-56
: Clarify the Flags Bit ManipulationThe expression
payload.flags >> 65
needs documentation explaining the bit allocation and rationale for shifting exactly 65 bits.#!/bin/bash # Search for documentation explaining the flags structure rg -A 5 "flags.*>>" bridge-evm/
39-60
: Add validation for amountTo parameter.The
amountTo
parameter should be validated to ensure it's not zero and doesn't exceed any maximum limits.Apply this diff:
function generateReceipt( address sender, bytes32 recipient, uint256 amountTo, SendPayload calldata payload, ExternalToken memory externalToken_ ) internal override returns (FullReceipt memory) { + require(amountTo > 0, "BridgeSolana: zero amount"); + require(amountTo <= type(uint256).max, "BridgeSolana: amount too large"); FullReceipt memory _receipt = FullReceipt({bridge-evm/test/AddressUtils.t.sol (1)
12-18
: Add safety checks to the assembly block.The assembly code directly loads memory without bounds checking.
Apply this diff:
function bytesToAddress( bytes memory bys ) private pure returns (address addr) { + require(bys.length >= 20, "AddressUtils: insufficient length"); assembly { + // Ensure we have enough bytes to read + if lt(mload(bys), 20) { + revert(0, 0) + } addr := mload(add(bys, 20)) } }bridge-evm/test/bridge_tests/TokenManager.t.sol (4)
45-69
: Add validation for decimals parameter.The function should validate that the decimals parameter is within reasonable bounds for ERC20 tokens.
Apply this diff to add validation:
function addToken( address token, bytes32 externalTokenAddress, uint8 decimals, bool paused ) public { + require(decimals <= 18, "Decimals must be <= 18"); // Standard ERC20 max decimals ITokenManager.ExternalTokenUnmapped memory externalToken = ITokenManager .ExternalTokenUnmapped({ externalTokenAddress: externalTokenAddress, decimals: decimals }); vm.expectEmit(address(bridgeInstance)); emit ITokenManager.TokenAdded(token); vm.expectEmit(address(bridgeInstance)); if (paused) { emit ITokenManager.TokenPaused(token); } else { emit ITokenManager.TokenUnpaused(token); } bridgeInstance.addToken(token, externalToken, paused); assertEq(bridgeInstance.bridgableTokens(token), true); assertEq(bridgeInstance.external2token(externalTokenAddress), token); assertEq(bridgeInstance.pausedTokens(token), paused); }
145-152
: Add bounds for decimals in fuzz test.The fuzz test for
addToken
should include reasonable bounds for the decimals parameter.Apply this diff to add bounds:
function test_fuzz_addToken( address token, bytes32 externalTokenAddress, uint8 decimals ) public { vm.assume(token != address(0)); + vm.assume(decimals <= 18); // Standard ERC20 max decimals addToken(token, externalTokenAddress, decimals); }
354-362
: Add signature malleability check.The function should verify that the signature is not malleable.
Apply this diff to add the check:
function signPayload( BridgeTypes.SendPayload memory payload, Signer memory signer ) internal pure returns (bytes memory signature) { bytes32 digest = payload.toHash(); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer.PK, digest); + // Check for signature malleability + require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, + "ECDSA: invalid signature 's' value"); signature = abi.encodePacked(r, s, v); return signature; }
431-442
: Add validation for maximum number of signers.The function should validate the maximum number of signers to prevent excessive gas consumption.
Apply this diff to add validation:
function signReceipt( BridgeTypes.MiniReceipt memory receipt ) internal returns (bytes memory signature) { bytes32 digest = receipt.toHash(); + require(signers.length <= 100, "Too many signers"); // Adjust limit as needed for (uint256 i = 0; i < signers.length; i++) { validatorInstance.addValidator(signers[i].Address); (uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].PK, digest); bytes memory signerSignature = abi.encodePacked(r, s, v); signature = bytes.concat(signature, signerSignature); } return signature; }
bridge-evm/test/bridge_tests/BridgeSend.t.sol (4)
1-3
: Overall file initialization looks good.
No issues identified at the top boilerplate.
63-79
: Verify largeamount
handling to avoid potential overflow.
WhendecimalsFrom < decimalsTo
,amount
is multiplied by10 ** (decimalsTo - decimalsFrom)
, which may overflow for very large values if permitted in your tests. Since Solidity 0.8+ reverts on overflow, this might be acceptable, but ensure it’s fully tested.
230-445
: Thorough bridging logic checks.
These functions comprehensively cover token/fee balances and the event emission flow for sending tokens and native currency. Good use of assertions to validate state transitions.
447-706
: Robust negative testing.
The revert scenarios thoroughly exercise invalid amounts, wrong native fees, incorrect flags, paused tokens, unsuccessful transfers, and more. This extensive coverage significantly reduces regression risk.bridge-evm/test/Validator.t.sol (1)
1-541
: LGTM! Comprehensive test coverage.The test file provides thorough coverage of the Validator contract's functionality, including:
- Validator management (add/remove)
- Payload and receipt validation
- Error cases and edge conditions
- Authority checks
function toEthSignedMessageHash( | ||
BridgeTypes.SendPayload memory payload | ||
) internal pure returns (bytes32 hash) { | ||
bytes32 messageHash = keccak256( | ||
abi.encode( | ||
payload.destChainId, | ||
payload.tokenAddress, | ||
payload.externalTokenAddress, | ||
payload.amountToSend, | ||
payload.feeAmount, | ||
payload.timestamp, | ||
payload.flags, | ||
payload.flagData | ||
) | ||
); | ||
return messageHash.toEthSignedMessageHash(); | ||
} |
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.
💡 Verification agent
🧩 Analysis chain
Document field order importance and verify consistent usage.
The function correctly implements the hashing logic, but consider:
- Add a comment explicitly stating that the field order in
abi.encode
is critical for hash consistency and must match across all implementations. - Ensure this hashing implementation is consistently used across the bridge system.
Let's verify the consistent usage of this hashing implementation:
🏁 Script executed:
#!/bin/bash
# Search for other implementations of payload hashing
rg -A 5 "keccak256.*abi\.encode.*destChainId.*tokenAddress.*externalTokenAddress"
# Search for tests verifying hash consistency
rg -A 5 "test.*payload.*hash"
Length of output: 1307
Ensure Field Order Documentation & Maintain Consistent Hashing
The hashing logic in toEthSignedMessageHash
is correct and its usage is confirmed in tests (see bridge-evm/test/PayloadUtils.t.sol
). However, the function would benefit from inline documentation that explicitly states that the order of fields in the abi.encode
call is critical for hash consistency.
- Add a clear comment above or within the
abi.encode
block inbridge-evm/contracts/utils/PayloadUtils.sol
(lines 27-43) noting that the field order must not be changed to maintain hash consistency. - Verify that all implementations and tests (e.g., those in
bridge-evm/test/PayloadUtils.t.sol
) adhere to this ordering.
function setFeeReceiver( | ||
address payable receiver | ||
) public { | ||
bridgeInstance.setFeeReceiver(receiver); | ||
} |
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.
🛠️ Refactor suggestion
Add event verification for fee receiver change.
The setFeeReceiver
function should verify that the FeeReceiverChanged
event is emitted.
function setFeeReceiver(
address payable receiver
) public {
+ vm.expectEmit();
+ emit IBridge.FeeReceiverChanged(address(this), receiver);
bridgeInstance.setFeeReceiver(receiver);
}
📝 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.
function setFeeReceiver( | |
address payable receiver | |
) public { | |
bridgeInstance.setFeeReceiver(receiver); | |
} | |
function setFeeReceiver( | |
address payable receiver | |
) public { | |
vm.expectEmit(); | |
emit IBridge.FeeReceiverChanged(address(this), receiver); | |
bridgeInstance.setFeeReceiver(receiver); | |
} |
function getPayload( | ||
string memory path | ||
) public view returns (BridgeTypes.SendPayload memory) { | ||
try vm.readFile(path) returns (string memory json) { | ||
bytes memory data = vm.parseJson(json); | ||
SendPayloadJson memory payloadJson = | ||
abi.decode(data, (SendPayloadJson)); | ||
BridgeTypes.SendPayload memory payload = BridgeTypes.SendPayload({ | ||
amountToSend: payloadJson.amountToSend, | ||
destChainId: payloadJson.destChainId, | ||
externalTokenAddress: payloadJson.externalTokenAddress, | ||
feeAmount: payloadJson.feeAmount, | ||
flags: payloadJson.flags, | ||
flagData: payloadJson.flagData, | ||
timestamp: payloadJson.timestamp, | ||
tokenAddress: payloadJson.tokenAddress | ||
}); | ||
return payload; | ||
} catch (bytes memory) { | ||
console.log("Error reading payload"); | ||
revert(); | ||
} | ||
} |
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.
🛠️ Refactor suggestion
Provide a descriptive revert reason.
Catching errors from vm.readFile
and vm.parseJson
and reverting without a descriptive reason obscures the cause of failure, making it harder to debug. A more informative revert message would be beneficial.
} catch (bytes memory) {
- console.log("Error reading payload");
- revert();
+ revert("Payload file read or parse error. Check file path or JSON formatting.");
}
📝 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.
function getPayload( | |
string memory path | |
) public view returns (BridgeTypes.SendPayload memory) { | |
try vm.readFile(path) returns (string memory json) { | |
bytes memory data = vm.parseJson(json); | |
SendPayloadJson memory payloadJson = | |
abi.decode(data, (SendPayloadJson)); | |
BridgeTypes.SendPayload memory payload = BridgeTypes.SendPayload({ | |
amountToSend: payloadJson.amountToSend, | |
destChainId: payloadJson.destChainId, | |
externalTokenAddress: payloadJson.externalTokenAddress, | |
feeAmount: payloadJson.feeAmount, | |
flags: payloadJson.flags, | |
flagData: payloadJson.flagData, | |
timestamp: payloadJson.timestamp, | |
tokenAddress: payloadJson.tokenAddress | |
}); | |
return payload; | |
} catch (bytes memory) { | |
console.log("Error reading payload"); | |
revert(); | |
} | |
} | |
function getPayload( | |
string memory path | |
) public view returns (BridgeTypes.SendPayload memory) { | |
try vm.readFile(path) returns (string memory json) { | |
bytes memory data = vm.parseJson(json); | |
SendPayloadJson memory payloadJson = | |
abi.decode(data, (SendPayloadJson)); | |
BridgeTypes.SendPayload memory payload = BridgeTypes.SendPayload({ | |
amountToSend: payloadJson.amountToSend, | |
destChainId: payloadJson.destChainId, | |
externalTokenAddress: payloadJson.externalTokenAddress, | |
feeAmount: payloadJson.feeAmount, | |
flags: payloadJson.flags, | |
flagData: payloadJson.flagData, | |
timestamp: payloadJson.timestamp, | |
tokenAddress: payloadJson.tokenAddress | |
}); | |
return payload; | |
} catch (bytes memory) { | |
revert("Payload file read or parse error. Check file path or JSON formatting."); | |
} | |
} |
function test_fuzz_fullReceipt2hash( | ||
bytes32 from, // source address (bytes32 because of cross-chain compatibility) | ||
bytes32 to, // destination address (bytes32 because of cross-chain compatibility) | ||
bytes32 tokenAddressFrom, // source token address (bytes32 because of cross-chain compatibility) | ||
bytes32 tokenAddressTo, // destination token address (bytes32 because of cross-chain compatibility) | ||
uint256 amountFrom, // amount of tokens sent | ||
uint256 amountTo, // amount of tokens received | ||
uint256 chainFrom, // chain id of the source chain | ||
uint256 chainTo, // chain id of the destination chain | ||
uint256 eventId, // transaction number | ||
uint256 flags, // flags for receiver | ||
bytes memory data // additional data of the transaction (eg. user nonce for Solana) | ||
) public { | ||
string[] memory runJsInputs = new string[](14); | ||
BridgeTypes.FullReceipt memory receipt = BridgeTypes.FullReceipt({ | ||
from: from, | ||
to: to, | ||
tokenAddressFrom: tokenAddressFrom, | ||
tokenAddressTo: tokenAddressTo, | ||
amountFrom: amountFrom, | ||
amountTo: amountTo, | ||
chainFrom: chainFrom, | ||
chainTo: chainTo, | ||
eventId: eventId, | ||
flags: flags, | ||
data: data | ||
}); | ||
|
||
// Build ffi command string | ||
runJsInputs[0] = "node"; | ||
runJsInputs[1] = "./test/differential_testing/receipt2hash.js"; | ||
runJsInputs[2] = "--full"; | ||
runJsInputs[3] = Strings.toHexString(uint256(from), 32); | ||
runJsInputs[4] = Strings.toHexString(uint256(to), 32); | ||
runJsInputs[5] = Strings.toHexString(uint256(tokenAddressFrom), 32); | ||
runJsInputs[6] = Strings.toHexString(uint256(tokenAddressTo), 32); | ||
runJsInputs[7] = Strings.toHexString(amountFrom, 32); | ||
runJsInputs[8] = Strings.toHexString(amountTo, 32); | ||
runJsInputs[9] = Strings.toHexString(chainFrom, 32); | ||
runJsInputs[10] = Strings.toHexString(chainTo, 32); | ||
runJsInputs[11] = Strings.toHexString(eventId, 32); | ||
runJsInputs[12] = Strings.toHexString(flags, 32); | ||
runJsInputs[13] = iToHex(data); | ||
|
||
// Run command and capture output | ||
bytes memory jsResult = vm.ffi(runJsInputs); | ||
bytes32 jsGenerated = abi.decode(jsResult, (bytes32)); | ||
|
||
bytes32 expectedHash = ReceiptUtils.toHash(receipt); | ||
assertEq(expectedHash, jsGenerated); | ||
} |
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.
🛠️ Refactor suggestion
Add input validation and error handling for FFI calls.
The test lacks bounds checking for inputs and error handling for external JavaScript execution.
- Add input validation:
function test_fuzz_fullReceipt2hash(
bytes32 from,
bytes32 to,
bytes32 tokenAddressFrom,
bytes32 tokenAddressTo,
uint256 amountFrom,
uint256 amountTo,
uint256 chainFrom,
uint256 chainTo,
uint256 eventId,
uint256 flags,
bytes memory data
) public {
+ // Validate inputs
+ require(data.length <= 1024, "Data too large");
+ require(amountFrom <= type(uint256).max, "Amount from overflow");
+ require(amountTo <= type(uint256).max, "Amount to overflow");
- Add error handling for FFI:
// Run command and capture output
- bytes memory jsResult = vm.ffi(runJsInputs);
+ bytes memory jsResult;
+ try vm.ffi(runJsInputs) returns (bytes memory result) {
+ jsResult = result;
+ } catch {
+ fail("JavaScript execution failed");
+ }
- Extract JS path to constant:
+ string constant JS_RECEIPT_HASH_PATH = "./test/differential_testing/receipt2hash.js";
+
function test_fuzz_fullReceipt2hash(
// ...
) public {
// ...
runJsInputs[0] = "node";
- runJsInputs[1] = "./test/differential_testing/receipt2hash.js";
+ runJsInputs[1] = JS_RECEIPT_HASH_PATH;
📝 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.
function test_fuzz_fullReceipt2hash( | |
bytes32 from, // source address (bytes32 because of cross-chain compatibility) | |
bytes32 to, // destination address (bytes32 because of cross-chain compatibility) | |
bytes32 tokenAddressFrom, // source token address (bytes32 because of cross-chain compatibility) | |
bytes32 tokenAddressTo, // destination token address (bytes32 because of cross-chain compatibility) | |
uint256 amountFrom, // amount of tokens sent | |
uint256 amountTo, // amount of tokens received | |
uint256 chainFrom, // chain id of the source chain | |
uint256 chainTo, // chain id of the destination chain | |
uint256 eventId, // transaction number | |
uint256 flags, // flags for receiver | |
bytes memory data // additional data of the transaction (eg. user nonce for Solana) | |
) public { | |
string[] memory runJsInputs = new string[](14); | |
BridgeTypes.FullReceipt memory receipt = BridgeTypes.FullReceipt({ | |
from: from, | |
to: to, | |
tokenAddressFrom: tokenAddressFrom, | |
tokenAddressTo: tokenAddressTo, | |
amountFrom: amountFrom, | |
amountTo: amountTo, | |
chainFrom: chainFrom, | |
chainTo: chainTo, | |
eventId: eventId, | |
flags: flags, | |
data: data | |
}); | |
// Build ffi command string | |
runJsInputs[0] = "node"; | |
runJsInputs[1] = "./test/differential_testing/receipt2hash.js"; | |
runJsInputs[2] = "--full"; | |
runJsInputs[3] = Strings.toHexString(uint256(from), 32); | |
runJsInputs[4] = Strings.toHexString(uint256(to), 32); | |
runJsInputs[5] = Strings.toHexString(uint256(tokenAddressFrom), 32); | |
runJsInputs[6] = Strings.toHexString(uint256(tokenAddressTo), 32); | |
runJsInputs[7] = Strings.toHexString(amountFrom, 32); | |
runJsInputs[8] = Strings.toHexString(amountTo, 32); | |
runJsInputs[9] = Strings.toHexString(chainFrom, 32); | |
runJsInputs[10] = Strings.toHexString(chainTo, 32); | |
runJsInputs[11] = Strings.toHexString(eventId, 32); | |
runJsInputs[12] = Strings.toHexString(flags, 32); | |
runJsInputs[13] = iToHex(data); | |
// Run command and capture output | |
bytes memory jsResult = vm.ffi(runJsInputs); | |
bytes32 jsGenerated = abi.decode(jsResult, (bytes32)); | |
bytes32 expectedHash = ReceiptUtils.toHash(receipt); | |
assertEq(expectedHash, jsGenerated); | |
} | |
string constant JS_RECEIPT_HASH_PATH = "./test/differential_testing/receipt2hash.js"; | |
function test_fuzz_fullReceipt2hash( | |
bytes32 from, // source address (bytes32 because of cross-chain compatibility) | |
bytes32 to, // destination address (bytes32 because of cross-chain compatibility) | |
bytes32 tokenAddressFrom, // source token address (bytes32 because of cross-chain compatibility) | |
bytes32 tokenAddressTo, // destination token address (bytes32 because of cross-chain compatibility) | |
uint256 amountFrom, // amount of tokens sent | |
uint256 amountTo, // amount of tokens received | |
uint256 chainFrom, // chain id of the source chain | |
uint256 chainTo, // chain id of the destination chain | |
uint256 eventId, // transaction number | |
uint256 flags, // flags for receiver | |
bytes memory data // additional data of the transaction (eg. user nonce for Solana) | |
) public { | |
+ // Validate inputs | |
+ require(data.length <= 1024, "Data too large"); | |
+ require(amountFrom <= type(uint256).max, "Amount from overflow"); | |
+ require(amountTo <= type(uint256).max, "Amount to overflow"); | |
string[] memory runJsInputs = new string[](14); | |
BridgeTypes.FullReceipt memory receipt = BridgeTypes.FullReceipt({ | |
from: from, | |
to: to, | |
tokenAddressFrom: tokenAddressFrom, | |
tokenAddressTo: tokenAddressTo, | |
amountFrom: amountFrom, | |
amountTo: amountTo, | |
chainFrom: chainFrom, | |
chainTo: chainTo, | |
eventId: eventId, | |
flags: flags, | |
data: data | |
}); | |
// Build ffi command string | |
runJsInputs[0] = "node"; | |
- runJsInputs[1] = "./test/differential_testing/receipt2hash.js"; | |
+ runJsInputs[1] = JS_RECEIPT_HASH_PATH; | |
runJsInputs[2] = "--full"; | |
runJsInputs[3] = Strings.toHexString(uint256(from), 32); | |
runJsInputs[4] = Strings.toHexString(uint256(to), 32); | |
runJsInputs[5] = Strings.toHexString(uint256(tokenAddressFrom), 32); | |
runJsInputs[6] = Strings.toHexString(uint256(tokenAddressTo), 32); | |
runJsInputs[7] = Strings.toHexString(amountFrom, 32); | |
runJsInputs[8] = Strings.toHexString(amountTo, 32); | |
runJsInputs[9] = Strings.toHexString(chainFrom, 32); | |
runJsInputs[10] = Strings.toHexString(chainTo, 32); | |
runJsInputs[11] = Strings.toHexString(eventId, 32); | |
runJsInputs[12] = Strings.toHexString(flags, 32); | |
runJsInputs[13] = iToHex(data); | |
// Run command and capture output | |
- bytes memory jsResult = vm.ffi(runJsInputs); | |
+ bytes memory jsResult; | |
+ try vm.ffi(runJsInputs) returns (bytes memory result) { | |
+ jsResult = result; | |
+ } catch { | |
+ fail("JavaScript execution failed"); | |
+ } | |
bytes32 jsGenerated = abi.decode(jsResult, (bytes32)); | |
bytes32 expectedHash = ReceiptUtils.toHash(receipt); | |
assertEq(expectedHash, jsGenerated); | |
} |
function initialize( | ||
address authority_, | ||
address[] calldata validators_, | ||
address payloadSigner_, | ||
uint256 feeValidityWindow_ | ||
) public initializer { | ||
__Validator_init( | ||
authority_, validators_, payloadSigner_, feeValidityWindow_ | ||
); | ||
} |
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.
🛠️ Refactor suggestion
Add validation for initialization parameters.
The initialize
function should validate its input parameters to ensure they are valid:
- Check for zero addresses
- Validate array length
- Ensure fee validity window is reasonable
function initialize(
address authority_,
address[] calldata validators_,
address payloadSigner_,
uint256 feeValidityWindow_
) public initializer {
+ require(authority_ != address(0), "Invalid authority address");
+ require(payloadSigner_ != address(0), "Invalid payload signer address");
+ require(validators_.length > 0, "No validators provided");
+ require(feeValidityWindow_ > 0 && feeValidityWindow_ <= 7 days, "Invalid fee validity window");
+
+ for(uint256 i = 0; i < validators_.length; i++) {
+ require(validators_[i] != address(0), "Invalid validator address");
+ }
+
__Validator_init(
authority_, validators_, payloadSigner_, feeValidityWindow_
);
}
📝 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.
function initialize( | |
address authority_, | |
address[] calldata validators_, | |
address payloadSigner_, | |
uint256 feeValidityWindow_ | |
) public initializer { | |
__Validator_init( | |
authority_, validators_, payloadSigner_, feeValidityWindow_ | |
); | |
} | |
function initialize( | |
address authority_, | |
address[] calldata validators_, | |
address payloadSigner_, | |
uint256 feeValidityWindow_ | |
) public initializer { | |
require(authority_ != address(0), "Invalid authority address"); | |
require(payloadSigner_ != address(0), "Invalid payload signer address"); | |
require(validators_.length > 0, "No validators provided"); | |
require(feeValidityWindow_ > 0 && feeValidityWindow_ <= 7 days, "Invalid fee validity window"); | |
for(uint256 i = 0; i < validators_.length; i++) { | |
require(validators_[i] != address(0), "Invalid validator address"); | |
} | |
__Validator_init( | |
authority_, validators_, payloadSigner_, feeValidityWindow_ | |
); | |
} |
function initialize( | ||
address authority_, | ||
address tokenBeacon_, | ||
address SAMB_, | ||
IValidation validator_, | ||
address payable feeReceiver_, | ||
uint256 nativeSendAmount_ | ||
) public initializer { | ||
__Bridge_init( | ||
authority_, | ||
tokenBeacon_, | ||
SAMB_, | ||
validator_, | ||
feeReceiver_, | ||
nativeSendAmount_ | ||
); | ||
emit TokensLocked(to, token, amount, txHash); | ||
} | ||
|
||
function unlockTokens( | ||
string calldata to, | ||
string calldata token, | ||
uint256 amount, | ||
bytes32 txHash, | ||
bytes[] memory signature | ||
) external { | ||
if (log[txHash]) revert UnlockError("txHash exist"); | ||
bytes32 messageHash = keccak256(abi.encode(to, token, amount, txHash)); | ||
if (signature.length == 0 || validators.length == 0) | ||
revert SignatureError(messageHash, ""); | ||
|
||
for (uint256 i = 0; i < validators.length; i++) { | ||
if (validators[i] != recoverSigner(messageHash, signature[i])) | ||
revert SignatureError(messageHash, signature[i]); | ||
} | ||
|
||
log[txHash] = true; | ||
ERC20(tokens[token]).transfer(stringToAddress(to), amount); | ||
emit TokenUnlocked(to, token, amount, txHash); | ||
} |
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.
🛠️ Refactor suggestion
Add validation for initialization parameters and improve documentation.
The initialize
function should:
- Validate input parameters
- Add comprehensive documentation for each parameter
- Include validation for the native send amount
+/// Initialize the contract with the given parameters
+/// @param authority_ Address of the authority contract for access control
+/// @param tokenBeacon_ Address of the beacon contract for token upgrades
+/// @param SAMB_ Address of the Wrapped token contract (SAMB)
+/// @param validator_ Address of the validator contract for transaction validation
+/// @param feeReceiver_ Address that receives transaction fees
+/// @param nativeSendAmount_ Amount of native currency for destination chain operations
+/// @dev All addresses must be non-zero and the native send amount must be reasonable
function initialize(
address authority_,
address tokenBeacon_,
address SAMB_,
IValidation validator_,
address payable feeReceiver_,
uint256 nativeSendAmount_
) public initializer {
+ require(authority_ != address(0), "Invalid authority address");
+ require(tokenBeacon_ != address(0), "Invalid token beacon address");
+ require(SAMB_ != address(0), "Invalid SAMB address");
+ require(address(validator_) != address(0), "Invalid validator address");
+ require(feeReceiver_ != address(0), "Invalid fee receiver address");
+ require(nativeSendAmount_ > 0 && nativeSendAmount_ <= 1 ether, "Invalid native send amount");
+
__Bridge_init(
authority_,
tokenBeacon_,
SAMB_,
validator_,
feeReceiver_,
nativeSendAmount_
);
}
📝 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.
function initialize( | |
address authority_, | |
address tokenBeacon_, | |
address SAMB_, | |
IValidation validator_, | |
address payable feeReceiver_, | |
uint256 nativeSendAmount_ | |
) public initializer { | |
__Bridge_init( | |
authority_, | |
tokenBeacon_, | |
SAMB_, | |
validator_, | |
feeReceiver_, | |
nativeSendAmount_ | |
); | |
emit TokensLocked(to, token, amount, txHash); | |
} | |
function unlockTokens( | |
string calldata to, | |
string calldata token, | |
uint256 amount, | |
bytes32 txHash, | |
bytes[] memory signature | |
) external { | |
if (log[txHash]) revert UnlockError("txHash exist"); | |
bytes32 messageHash = keccak256(abi.encode(to, token, amount, txHash)); | |
if (signature.length == 0 || validators.length == 0) | |
revert SignatureError(messageHash, ""); | |
for (uint256 i = 0; i < validators.length; i++) { | |
if (validators[i] != recoverSigner(messageHash, signature[i])) | |
revert SignatureError(messageHash, signature[i]); | |
} | |
log[txHash] = true; | |
ERC20(tokens[token]).transfer(stringToAddress(to), amount); | |
emit TokenUnlocked(to, token, amount, txHash); | |
} | |
/// Initialize the contract with the given parameters | |
/// @param authority_ Address of the authority contract for access control | |
/// @param tokenBeacon_ Address of the beacon contract for token upgrades | |
/// @param SAMB_ Address of the Wrapped token contract (SAMB) | |
/// @param validator_ Address of the validator contract for transaction validation | |
/// @param feeReceiver_ Address that receives transaction fees | |
/// @param nativeSendAmount_ Amount of native currency for destination chain operations | |
/// @dev All addresses must be non-zero and the native send amount must be reasonable | |
function initialize( | |
address authority_, | |
address tokenBeacon_, | |
address SAMB_, | |
IValidation validator_, | |
address payable feeReceiver_, | |
uint256 nativeSendAmount_ | |
) public initializer { | |
require(authority_ != address(0), "Invalid authority address"); | |
require(tokenBeacon_ != address(0), "Invalid token beacon address"); | |
require(SAMB_ != address(0), "Invalid SAMB address"); | |
require(address(validator_) != address(0), "Invalid validator address"); | |
require(feeReceiver_ != address(0), "Invalid fee receiver address"); | |
require(nativeSendAmount_ > 0 && nativeSendAmount_ <= 1 ether, "Invalid native send amount"); | |
__Bridge_init( | |
authority_, | |
tokenBeacon_, | |
SAMB_, | |
validator_, | |
feeReceiver_, | |
nativeSendAmount_ | |
); | |
} |
uint256[] memory signers = vm.envUint("SIGNERS", ","); | ||
bytes memory signatures; | ||
for (uint256 i = 0; i < signers.length; i++) { | ||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i], digest); | ||
bytes memory signerSignature = abi.encodePacked(r, s, v); | ||
signatures = bytes.concat(signatures, signerSignature); | ||
} |
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.
🛠️ Refactor suggestion
Add validation for empty signers array.
The signature generation should validate that there are signers available.
Apply this diff:
uint256[] memory signers = vm.envUint("SIGNERS", ",");
+ require(signers.length > 0, "CreateClaimSignature: no signers");
bytes memory signatures;
for (uint256 i = 0; i < signers.length; i++) {
📝 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.
uint256[] memory signers = vm.envUint("SIGNERS", ","); | |
bytes memory signatures; | |
for (uint256 i = 0; i < signers.length; i++) { | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i], digest); | |
bytes memory signerSignature = abi.encodePacked(r, s, v); | |
signatures = bytes.concat(signatures, signerSignature); | |
} | |
uint256[] memory signers = vm.envUint("SIGNERS", ","); | |
require(signers.length > 0, "CreateClaimSignature: no signers"); | |
bytes memory signatures; | |
for (uint256 i = 0; i < signers.length; i++) { | |
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i], digest); | |
bytes memory signerSignature = abi.encodePacked(r, s, v); | |
signatures = bytes.concat(signatures, signerSignature); | |
} |
for (uint256 i = 0; i < signers.length; i++) { | ||
validatorInstance.addValidator(signers[i].Address); | ||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].PK, digest); | ||
bytes memory signerSignature = abi.encodePacked(r, s, v); // note the order here is different from line above. |
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.
🛠️ Refactor suggestion
Inconsistent signature component ordering.
The comment "note the order here is different from line above" appears multiple times, indicating potential confusion about signature component ordering. Consider standardizing the order across all signature operations.
Apply this diff to standardize the signature component ordering:
- bytes memory signerSignature = abi.encodePacked(r, s, v); // note the order here is different from line above.
+ bytes memory signerSignature = abi.encodePacked(v, r, s); // standardized order: v, r, s
Also applies to: 467-467
Summary by CodeRabbit
New Features
TokenBeacon
contract for managing upgradeable token implementations.BridgeSolana
and related functionality for bridging to the Solana blockchain.DeployBridge
,DeployValidator
, andDeployTokenBeacon
.Documentation
Testing & Build Improvements
BridgeSolana
andTokenManager
.