-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor and test and chore: audit reaction #97
Merged
Merged
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,13 @@ error ZeroAddress(); | |
/// @dev Zero value when it has to be different from zero. | ||
error ZeroValue(); | ||
|
||
/// @dev Failure of a transfer. | ||
/// @param token Address of a token. | ||
/// @param from Address `from`. | ||
/// @param to Address `to`. | ||
/// @param amount Token amount. | ||
error TransferFailed(address token, address from, address to, uint256 amount); | ||
|
||
/// @title FxERC20ChildTunnel - Smart contract for the L2 token management part | ||
/// @author Aleksandr Kuperman - <[email protected]> | ||
/// @author Andrey Lebedev - <[email protected]> | ||
|
@@ -57,30 +64,22 @@ contract FxERC20ChildTunnel is FxBaseChildTunnel { | |
} | ||
|
||
/// @dev Receives the token message from L1 and transfers L2 tokens to a specified address. | ||
/// @notice Reentrancy is not possible as tokens are verified before the contract deployment. | ||
/// @param sender FxERC20RootTunnel contract address from L1. | ||
/// @param message Incoming bridge message. | ||
function _processMessageFromRoot( | ||
uint256 /* stateId */, | ||
address sender, | ||
bytes memory message | ||
) internal override validateSender(sender) { | ||
// Decode incoming message from root: (address, address, uint96) | ||
address from; | ||
address to; | ||
// The token amount is limited to be no bigger than 2^96 - 1 | ||
uint96 amount; | ||
// solhint-disable-next-line no-inline-assembly | ||
assembly { | ||
// Offset 20 bytes for the address from (160 bits) | ||
from := mload(add(message, 20)) | ||
// Offset 20 bytes for the address to (160 bits) | ||
to := mload(add(message, 40)) | ||
// Offset 12 bytes of amount (96 bits) | ||
amount := mload(add(message, 52)) | ||
} | ||
// Decode incoming message from root: (address, address, uint256) | ||
(address from, address to, uint256 amount) = abi.decode(message, (address, address, uint256)); | ||
|
||
// Transfer decoded amount of tokens to a specified address | ||
IERC20(childToken).transfer(to, amount); | ||
bool success = IERC20(childToken).transfer(to, amount); | ||
if (!success) { | ||
revert TransferFailed(childToken, address(this), to, amount); | ||
} | ||
|
||
emit FxWithdrawERC20(rootToken, childToken, from, to, amount); | ||
} | ||
|
@@ -95,10 +94,13 @@ contract FxERC20ChildTunnel is FxBaseChildTunnel { | |
} | ||
|
||
// Deposit tokens on an L2 bridge contract (lock) | ||
IERC20(childToken).transferFrom(msg.sender, address(this), amount); | ||
bool success = IERC20(childToken).transferFrom(msg.sender, address(this), amount); | ||
if (!success) { | ||
revert TransferFailed(rootToken, msg.sender, address(this), amount); | ||
} | ||
|
||
// Encode message for root: (address, address, uint96) | ||
bytes memory message = abi.encodePacked(msg.sender, to, uint96(amount)); | ||
// Encode message for root: (address, address, uint256) | ||
bytes memory message = abi.encode(msg.sender, to, amount); | ||
// Send message to root | ||
_sendMessageToRoot(message); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,13 @@ error ZeroAddress(); | |
/// @dev Zero value when it has to be different from zero. | ||
error ZeroValue(); | ||
|
||
/// @dev Failure of a transfer. | ||
/// @param token Address of a token. | ||
/// @param from Address `from`. | ||
/// @param to Address `to`. | ||
/// @param amount Token amount. | ||
error TransferFailed(address token, address from, address to, uint256 amount); | ||
|
||
/// @title FxERC20RootTunnel - Smart contract for the L1 token management part | ||
/// @author Aleksandr Kuperman - <[email protected]> | ||
/// @author Andrey Lebedev - <[email protected]> | ||
|
@@ -63,20 +70,8 @@ contract FxERC20RootTunnel is FxBaseRootTunnel { | |
/// @dev Receives the token message from L2 and transfers bridged tokens to a specified address. | ||
/// @param message Incoming bridge message. | ||
function _processMessageFromChild(bytes memory message) internal override { | ||
// Decode incoming message from child: (address, address, uint96) | ||
address from; | ||
address to; | ||
// The token amount is limited to be no bigger than 2^96 - 1 | ||
uint96 amount; | ||
// solhint-disable-next-line no-inline-assembly | ||
assembly { | ||
// Offset 20 bytes for the address from (160 bits) | ||
from := mload(add(message, 20)) | ||
// Offset 20 bytes for the address to (160 bits) | ||
to := mload(add(message, 40)) | ||
// Offset 12 bytes of amount (96 bits) | ||
amount := mload(add(message, 52)) | ||
} | ||
// Decode incoming message from child: (address, address, uint256) | ||
(address from, address to, uint256 amount) = abi.decode(message, (address, address, uint256)); | ||
|
||
// Mints bridged amount of tokens to a specified address | ||
IERC20(rootToken).mint(to, amount); | ||
|
@@ -85,6 +80,7 @@ contract FxERC20RootTunnel is FxBaseRootTunnel { | |
} | ||
|
||
/// @dev Withdraws bridged tokens from L1 to get their original tokens on L1 by a specified address. | ||
/// @notice Reentrancy is not possible as tokens are verified before the contract deployment. | ||
/// @param to Destination address on L2. | ||
/// @param amount Token amount to be withdrawn. | ||
function _withdraw(address to, uint256 amount) internal { | ||
|
@@ -93,17 +89,20 @@ contract FxERC20RootTunnel is FxBaseRootTunnel { | |
revert ZeroValue(); | ||
} | ||
|
||
// Encode message for child: (address, address, uint256) | ||
bytes memory message = abi.encode(msg.sender, to, amount); | ||
// Send message to child | ||
_sendMessageToChild(message); | ||
|
||
// Transfer tokens from sender to this contract address | ||
IERC20(rootToken).transferFrom(msg.sender, address(this), amount); | ||
bool success = IERC20(rootToken).transferFrom(msg.sender, address(this), amount); | ||
if (!success) { | ||
revert TransferFailed(rootToken, msg.sender, address(this), amount); | ||
} | ||
|
||
// Burn bridged tokens | ||
IERC20(rootToken).burn(amount); | ||
|
||
// Encode message for child: (address, address, uint96) | ||
bytes memory message = abi.encodePacked(msg.sender, to, uint96(amount)); | ||
// Send message to child | ||
_sendMessageToChild(message); | ||
|
||
emit FxWithdrawERC20(rootToken, childToken, msg.sender, to, amount); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.21; | ||
|
||
import {ERC20} from "../../lib/solmate/src/tokens/ERC20.sol"; | ||
|
||
/// @dev Only `owner` has a privilege, but the `sender` was provided. | ||
/// @param sender Sender address. | ||
/// @param owner Required sender address as an owner. | ||
error OwnerOnly(address sender, address owner); | ||
|
||
/// @dev Provided zero address. | ||
error ZeroAddress(); | ||
|
||
|
||
/// @title BrokenERC20 - Smart contract for an ERC20 token with a broken functionality | ||
contract BrokenERC20 is ERC20 { | ||
|
||
constructor() ERC20("Broken ERC20", "BRERC20", 18) | ||
{} | ||
|
||
/// @dev Mints tokens. | ||
/// @param account Account address. | ||
/// @param amount Token amount. | ||
function mint(address account, uint256 amount) external { | ||
_mint(account, amount); | ||
} | ||
|
||
/// @dev Burns tokens. | ||
/// @param amount Token amount to burn. | ||
function burn(uint256 amount) external { | ||
_burn(msg.sender, amount); | ||
} | ||
|
||
/// @dev Broken transfer function. | ||
function transfer(address, uint256) public virtual override returns (bool) { | ||
return false; | ||
} | ||
|
||
/// @dev Broken transferFrom function. | ||
function transferFrom(address, address, uint256) public virtual override returns (bool) { | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
revert TransferFailed(childToken, msg.sender, address(this), 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.
Not moved transferFrom to end-of-function by CEI