Skip to content

Commit

Permalink
feat: Use EIP1153 (transient storage) for re-entrancy checks (#324)
Browse files Browse the repository at this point in the history
- closes #145
- update solidity compiler version to `0.8.24`
  • Loading branch information
viraj124 authored Oct 22, 2024
1 parent f77346c commit c337d51
Show file tree
Hide file tree
Showing 34 changed files with 141 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/wild-lizards-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fuel-bridge/solidity-contracts': minor
---

add transient storage version of the reentrancy guard
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
// solhint-disable not-rely-on-time
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import {verifyBinaryTree} from "../lib/VerifyBinaryTree/VerifyBinaryTree.sol";
import {FuelChainState} from "./FuelChainState.sol";
import {FuelBlockHeader, FuelBlockHeaderLib} from "./types/FuelBlockHeader.sol";
import {FuelBlockHeaderLite, FuelBlockHeaderLiteLib} from "./types/FuelBlockHeaderLite.sol";
import {CryptographyLib} from "../lib/Cryptography.sol";
import {CommonPredicates} from "../lib/CommonPredicates.sol";
import {ReentrancyGuardTransientUpgradable} from "../security/ReentrancyGuardTransientUpgradable.sol";

/// @notice Structure for proving an element in a merkle tree
struct MerkleProof {
Expand All @@ -35,7 +35,7 @@ contract FuelMessagePortal is
Initializable,
PausableUpgradeable,
AccessControlUpgradeable,
ReentrancyGuardUpgradeable,
ReentrancyGuardTransientUpgradable,
UUPSUpgradeable
{
using FuelBlockHeaderLib for FuelBlockHeader;
Expand Down Expand Up @@ -123,7 +123,7 @@ contract FuelMessagePortal is
function initializerV1(FuelChainState fuelChainState) internal virtual onlyInitializing {
__Pausable_init();
__AccessControl_init();
__ReentrancyGuard_init();
__ReentrancyGuardTransient_init();
__UUPSUpgradeable_init();

//grant initial roles
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {FuelMessagePortalV3} from "./v3/FuelMessagePortalV3.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import "../../FuelMessagePortal.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import "../v2/FuelMessagePortalV2.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {CryptographyLib} from "../../lib/Cryptography.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {CryptographyLib} from "../../lib/Cryptography.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache 2.0

pragma solidity 0.8.9;
pragma solidity 0.8.24;

/// @notice Common predicates for Fuel inputs
library CommonPredicates {
Expand Down
2 changes: 1 addition & 1 deletion packages/solidity-contracts/contracts/lib/Cryptography.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

/// @notice This is the Fuel protocol cryptography library.
library CryptographyLib {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {FuelMessagePortal} from "../fuelchain/FuelMessagePortal.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {FuelMessagePortal} from "../fuelchain/FuelMessagePortal.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

abstract contract FuelBridgeBase {
/// @notice Finalizes the withdrawal process from the Fuel side gateway contract
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

/// @custom:deprecation THIS CONTRACT IS DEPRECATED
abstract contract FuelBridgeBaseV2 {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import "./FuelERC20Gateway.sol";
import "../FuelBridgeBase/FuelBridgeBaseV2.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import "./FuelERC721Gateway.sol";
import "../FuelBridgeBase/FuelBridgeBaseV2.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

/**
* @dev Variant of {ReentrancyGuard} that uses transient storage.
* Modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol
* For detailed context on reentrancy guard check https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/ReentrancyGuardUpgradeable.sol
* For detailed context on EIP1153(Transient Storage) check https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1153.md
*
*/
abstract contract ReentrancyGuardTransientUpgradable is Initializable {
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();

uint256 private constant _NOT_ENTERED = 0;
uint256 private constant _ENTERED = 1;

// @notice acts as the storage slot in transient storage
// avoiding the use of a namespace storage slot, to avoid storage collisions with upgrades
uint256 _status;

function __ReentrancyGuardTransient_init() internal onlyInitializing {
__ReentrancyGuardTransient_init_unchained();
}

function __ReentrancyGuardTransient_init_unchained() internal onlyInitializing {}

/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}

function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_get() != _NOT_ENTERED) revert ReentrancyGuardReentrantCall();

// Any calls to nonReentrant after this point will fail
_set(_ENTERED);
}

function _nonReentrantAfter() private {
_set(_NOT_ENTERED);
}

/**
* @dev Store `value` at location `slot` in transient storage.
*/
function _set(uint256 value) internal {
assembly ("memory-safe") {
let slot := _status.slot
tstore(slot, value)
}
}

/**
* @dev Load the value held at location `slot` in transient storage.
*/
function _get() internal view returns (uint256 value) {
assembly ("memory-safe") {
let slot := _status.slot
value := tload(slot)
}
}

/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
4 changes: 2 additions & 2 deletions packages/solidity-contracts/contracts/test/CustomToken.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

Expand All @@ -24,7 +24,7 @@ contract CustomToken is ERC20 {
function decimals() public view virtual override returns (uint8) {
return customDecimals;
}

// to handle hardhat_setcode as state is reset after that operation
function setDecimals(uint8 _decimals) external {
customDecimals = _decimals;
Expand Down
21 changes: 9 additions & 12 deletions packages/solidity-contracts/contracts/test/CustomTokenWETH.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

contract CustomTokenWETH {
string public name = "Wrapped Ether";
string public symbol = "WETH";
uint8 public constant decimals = 18;
uint8 public constant decimals = 18;

event Approval(address indexed src, address indexed guy, uint wad);
event Transfer(address indexed src, address indexed dst, uint wad);
event Deposit(address indexed dst, uint wad);
event Withdrawal(address indexed src, uint wad);
event Approval(address indexed src, address indexed guy, uint wad);
event Transfer(address indexed src, address indexed dst, uint wad);
event Deposit(address indexed dst, uint wad);
event Withdrawal(address indexed src, uint wad);

mapping (address => uint) public balanceOf;
mapping (address => mapping (address => uint)) public allowance;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;

function deposit() public payable {
balanceOf[msg.sender] += msg.value;
Expand All @@ -39,10 +39,7 @@ contract CustomTokenWETH {
return transferFrom(msg.sender, dst, wad);
}

function transferFrom(address src, address dst, uint wad)
public
returns (bool)
{
function transferFrom(address src, address dst, uint wad) public returns (bool) {
require(balanceOf[src] >= wad);

if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {FuelBlockHeader, FuelBlockHeaderLib} from "../fuelchain/types/FuelBlockHeader.sol";
import {FuelBlockHeaderLite, FuelBlockHeaderLiteLib} from "../fuelchain/types/FuelBlockHeaderLite.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {FuelMessagesEnabled} from "../messaging/FuelMessagesEnabled.sol";
import {FuelMessagePortal} from "../fuelchain/FuelMessagePortal.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

Expand Down
2 changes: 1 addition & 1 deletion packages/solidity-contracts/contracts/test/Token.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;
pragma solidity 0.8.24;

import {FuelMessagesEnabledUpgradeable} from "../messaging/FuelMessagesEnabledUpgradeable.sol";
import {FuelMessagePortal} from "../fuelchain/FuelMessagePortal.sol";
Expand Down
2 changes: 1 addition & 1 deletion packages/solidity-contracts/contracts/utils/Permit.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;
pragma solidity 0.8.24;

/// @notice Structure for erc20 token permit signature
struct PermitSignature {
Expand Down
2 changes: 1 addition & 1 deletion packages/solidity-contracts/contracts/vendor/SafeCall.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
pragma solidity 0.8.24;

/**
* @title SafeCall
Expand Down
3 changes: 2 additions & 1 deletion packages/solidity-contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ const config: HardhatUserConfig = {
solidity: {
compilers: [
{
version: '0.8.9',
version: '0.8.24',
settings: {
evmVersion: 'cancun',
optimizer: {
enabled: true,
runs: 10000,
Expand Down
5 changes: 4 additions & 1 deletion packages/solidity-contracts/test/messagesIncoming.ts
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,10 @@ describe('Incoming Messages', async () => {
blockInHistoryProof,
messageInBlockProof
)
).to.be.revertedWith('ReentrancyGuard: reentrant call');
).to.be.revertedWithCustomError(
env.fuelMessagePortal,
'ReentrancyGuardReentrantCall()'
);
expect(
await env.fuelMessagePortal.incomingMessageSuccessful(
messageReentrantId
Expand Down
5 changes: 4 additions & 1 deletion packages/solidity-contracts/test/messagesIncomingV2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,10 @@ describe('FuelMessagePortalV2 - Incoming messages', () => {
blockInHistoryProof,
messageInBlockProof
)
).to.be.revertedWith('ReentrancyGuard: reentrant call');
).to.be.revertedWithCustomError(
fuelMessagePortal,
'ReentrancyGuardReentrantCall()'
);
});
});
});
Loading

0 comments on commit c337d51

Please sign in to comment.