-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #97 from valory-xyz/audit_reaction
refactor and test and chore: audit reaction
- Loading branch information
Showing
12 changed files
with
260 additions
and
48 deletions.
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
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); | ||
} | ||
|
@@ -94,14 +93,17 @@ contract FxERC20ChildTunnel is FxBaseChildTunnel { | |
revert ZeroValue(); | ||
} | ||
|
||
// Deposit tokens on an L2 bridge contract (lock) | ||
IERC20(childToken).transferFrom(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); | ||
|
||
// Deposit tokens on an L2 bridge contract (lock) | ||
bool success = IERC20(childToken).transferFrom(msg.sender, address(this), amount); | ||
if (!success) { | ||
revert TransferFailed(childToken, msg.sender, address(this), amount); | ||
} | ||
|
||
emit FxDepositERC20(childToken, rootToken, 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 |
---|---|---|
|
@@ -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
55 changes: 55 additions & 0 deletions
55
scripts/deployment/bridges/polygon/deploy_04_set_root_tunnel.js
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,55 @@ | ||
/*global process*/ | ||
|
||
const { ethers } = require("hardhat"); | ||
const { LedgerSigner } = require("@anders-t/ethers-ledger"); | ||
|
||
async function main() { | ||
const fs = require("fs"); | ||
const globalsFile = "globals.json"; | ||
const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); | ||
let parsedData = JSON.parse(dataFromJSON); | ||
const useLedger = parsedData.useLedger; | ||
const derivationPath = parsedData.derivationPath; | ||
const providerName = parsedData.providerName; | ||
const fxERC20ChildTunnelAddress = parsedData.fxERC20ChildTunnelAddress; | ||
const fxERC20RootTunnelAddress = parsedData.fxERC20RootTunnelAddress; | ||
let EOA; | ||
|
||
let provider; | ||
if (providerName == "polygon") { | ||
provider = await ethers.providers.getDefaultProvider("matic"); | ||
} else { | ||
const mumbaiURL = "https://polygon-mumbai.g.alchemy.com/v2/" + process.env.ALCHEMY_API_KEY_MUMBAI; | ||
provider = new ethers.providers.JsonRpcProvider(mumbaiURL); | ||
} | ||
const signers = await ethers.getSigners(); | ||
|
||
if (useLedger) { | ||
EOA = new LedgerSigner(provider, derivationPath); | ||
} else { | ||
EOA = signers[0]; | ||
} | ||
// EOA address | ||
const deployer = await EOA.getAddress(); | ||
console.log("EOA is:", deployer); | ||
|
||
// Transaction signing and execution | ||
console.log("4. FxERC20ChildTunnel to set root tunnel to FxERC20RootTunnel"); | ||
const fxERC20ChildTunnel = await ethers.getContractAt("FxERC20ChildTunnel", fxERC20ChildTunnelAddress); | ||
console.log("You are signing the following transaction: FxERC20ChildTunnel.connect(EOA).setFxRootTunnel(FxERC20RootTunnel)"); | ||
const gasPriceInGwei = "230"; | ||
const gasPrice = ethers.utils.parseUnits(gasPriceInGwei, "gwei"); | ||
const result = await fxERC20ChildTunnel.setFxRootTunnel(fxERC20RootTunnelAddress, { gasPrice }); | ||
|
||
// Transaction details | ||
console.log("Contract deployment: FxERC20ChildTunnel"); | ||
console.log("Contract address:", fxERC20ChildTunnel.address); | ||
console.log("Transaction:", result.hash); | ||
} | ||
|
||
main() | ||
.then(() => process.exit(0)) | ||
.catch((error) => { | ||
console.error(error); | ||
process.exit(1); | ||
}); |
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.