Skip to content

Commit c337d51

Browse files
authored
feat: Use EIP1153 (transient storage) for re-entrancy checks (#324)
- closes #145 - update solidity compiler version to `0.8.24`
1 parent f77346c commit c337d51

34 files changed

+141
-47
lines changed

.changeset/wild-lizards-wonder.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@fuel-bridge/solidity-contracts': minor
3+
---
4+
5+
add transient storage version of the reentrancy guard

packages/solidity-contracts/contracts/fuelchain/FuelChainState.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: UNLICENSED
22
// solhint-disable not-rely-on-time
3-
pragma solidity 0.8.9;
3+
pragma solidity 0.8.24;
44

55
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
66
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

packages/solidity-contracts/contracts/fuelchain/FuelMessagePortal.sol

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
55
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
66
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
77
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
8-
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
98
import {verifyBinaryTree} from "../lib/VerifyBinaryTree/VerifyBinaryTree.sol";
109
import {FuelChainState} from "./FuelChainState.sol";
1110
import {FuelBlockHeader, FuelBlockHeaderLib} from "./types/FuelBlockHeader.sol";
1211
import {FuelBlockHeaderLite, FuelBlockHeaderLiteLib} from "./types/FuelBlockHeaderLite.sol";
1312
import {CryptographyLib} from "../lib/Cryptography.sol";
1413
import {CommonPredicates} from "../lib/CommonPredicates.sol";
14+
import {ReentrancyGuardTransientUpgradable} from "../security/ReentrancyGuardTransientUpgradable.sol";
1515

1616
/// @notice Structure for proving an element in a merkle tree
1717
struct MerkleProof {
@@ -35,7 +35,7 @@ contract FuelMessagePortal is
3535
Initializable,
3636
PausableUpgradeable,
3737
AccessControlUpgradeable,
38-
ReentrancyGuardUpgradeable,
38+
ReentrancyGuardTransientUpgradable,
3939
UUPSUpgradeable
4040
{
4141
using FuelBlockHeaderLib for FuelBlockHeader;
@@ -123,7 +123,7 @@ contract FuelMessagePortal is
123123
function initializerV1(FuelChainState fuelChainState) internal virtual onlyInitializing {
124124
__Pausable_init();
125125
__AccessControl_init();
126-
__ReentrancyGuard_init();
126+
__ReentrancyGuardTransient_init();
127127
__UUPSUpgradeable_init();
128128

129129
//grant initial roles

packages/solidity-contracts/contracts/fuelchain/FuelMessagePortal/IFuelMessagePortal.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache 2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

packages/solidity-contracts/contracts/fuelchain/FuelMessagePortal/v2/FuelMessagePortalV2.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import "../../FuelMessagePortal.sol";
55

packages/solidity-contracts/contracts/fuelchain/FuelMessagePortal/v3/FuelMessagePortalV3.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

packages/solidity-contracts/contracts/fuelchain/types/FuelBlockHeader.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

packages/solidity-contracts/contracts/fuelchain/types/FuelBlockHeaderLite.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

packages/solidity-contracts/contracts/lib/CommonPredicates.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: Apache 2.0
22

3-
pragma solidity 0.8.9;
3+
pragma solidity 0.8.24;
44

55
/// @notice Common predicates for Fuel inputs
66
library CommonPredicates {

packages/solidity-contracts/contracts/lib/Cryptography.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
/// @notice This is the Fuel protocol cryptography library.
55
library CryptographyLib {

packages/solidity-contracts/contracts/messaging/FuelMessagesEnabled.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

packages/solidity-contracts/contracts/messaging/FuelMessagesEnabledUpgradeable.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
55
import {FuelMessagePortal} from "../fuelchain/FuelMessagePortal.sol";

packages/solidity-contracts/contracts/messaging/gateway/FuelBridgeBase/FuelBridgeBase.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
abstract contract FuelBridgeBase {
55
/// @notice Finalizes the withdrawal process from the Fuel side gateway contract

packages/solidity-contracts/contracts/messaging/gateway/FuelBridgeBase/FuelBridgeBaseV2.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
/// @custom:deprecation THIS CONTRACT IS DEPRECATED
55
abstract contract FuelBridgeBaseV2 {

packages/solidity-contracts/contracts/messaging/gateway/FuelERC20Gateway/FuelERC20Gateway.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
55
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

packages/solidity-contracts/contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV2.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import "./FuelERC20Gateway.sol";
55
import "../FuelBridgeBase/FuelBridgeBaseV2.sol";

packages/solidity-contracts/contracts/messaging/gateway/FuelERC20Gateway/FuelERC20GatewayV4.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
55
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

packages/solidity-contracts/contracts/messaging/gateway/FuelERC721Gateway/FuelERC721Gateway.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
55
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

packages/solidity-contracts/contracts/messaging/gateway/FuelERC721Gateway/FuelERC721GatewayV2.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import "./FuelERC721Gateway.sol";
55
import "../FuelBridgeBase/FuelBridgeBaseV2.sol";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.24;
3+
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
4+
5+
/**
6+
* @dev Variant of {ReentrancyGuard} that uses transient storage.
7+
* Modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol
8+
* For detailed context on reentrancy guard check https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/ReentrancyGuardUpgradeable.sol
9+
* For detailed context on EIP1153(Transient Storage) check https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1153.md
10+
*
11+
*/
12+
abstract contract ReentrancyGuardTransientUpgradable is Initializable {
13+
/**
14+
* @dev Unauthorized reentrant call.
15+
*/
16+
error ReentrancyGuardReentrantCall();
17+
18+
uint256 private constant _NOT_ENTERED = 0;
19+
uint256 private constant _ENTERED = 1;
20+
21+
// @notice acts as the storage slot in transient storage
22+
// avoiding the use of a namespace storage slot, to avoid storage collisions with upgrades
23+
uint256 _status;
24+
25+
function __ReentrancyGuardTransient_init() internal onlyInitializing {
26+
__ReentrancyGuardTransient_init_unchained();
27+
}
28+
29+
function __ReentrancyGuardTransient_init_unchained() internal onlyInitializing {}
30+
31+
/**
32+
* @dev Prevents a contract from calling itself, directly or indirectly.
33+
* Calling a `nonReentrant` function from another `nonReentrant`
34+
* function is not supported. It is possible to prevent this from happening
35+
* by making the `nonReentrant` function external, and making it call a
36+
* `private` function that does the actual work.
37+
*/
38+
modifier nonReentrant() {
39+
_nonReentrantBefore();
40+
_;
41+
_nonReentrantAfter();
42+
}
43+
44+
function _nonReentrantBefore() private {
45+
// On the first call to nonReentrant, _status will be NOT_ENTERED
46+
if (_get() != _NOT_ENTERED) revert ReentrancyGuardReentrantCall();
47+
48+
// Any calls to nonReentrant after this point will fail
49+
_set(_ENTERED);
50+
}
51+
52+
function _nonReentrantAfter() private {
53+
_set(_NOT_ENTERED);
54+
}
55+
56+
/**
57+
* @dev Store `value` at location `slot` in transient storage.
58+
*/
59+
function _set(uint256 value) internal {
60+
assembly ("memory-safe") {
61+
let slot := _status.slot
62+
tstore(slot, value)
63+
}
64+
}
65+
66+
/**
67+
* @dev Load the value held at location `slot` in transient storage.
68+
*/
69+
function _get() internal view returns (uint256 value) {
70+
assembly ("memory-safe") {
71+
let slot := _status.slot
72+
value := tload(slot)
73+
}
74+
}
75+
76+
/**
77+
* @dev This empty reserved space is put in place to allow future versions to add new
78+
* variables without shifting down storage in the inheritance chain.
79+
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
80+
*/
81+
uint256[49] private __gap;
82+
}

packages/solidity-contracts/contracts/test/CustomToken.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

@@ -24,7 +24,7 @@ contract CustomToken is ERC20 {
2424
function decimals() public view virtual override returns (uint8) {
2525
return customDecimals;
2626
}
27-
27+
2828
// to handle hardhat_setcode as state is reset after that operation
2929
function setDecimals(uint8 _decimals) external {
3030
customDecimals = _decimals;

packages/solidity-contracts/contracts/test/CustomTokenWETH.sol

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
contract CustomTokenWETH {
55
string public name = "Wrapped Ether";
66
string public symbol = "WETH";
7-
uint8 public constant decimals = 18;
7+
uint8 public constant decimals = 18;
88

9-
event Approval(address indexed src, address indexed guy, uint wad);
10-
event Transfer(address indexed src, address indexed dst, uint wad);
11-
event Deposit(address indexed dst, uint wad);
12-
event Withdrawal(address indexed src, uint wad);
9+
event Approval(address indexed src, address indexed guy, uint wad);
10+
event Transfer(address indexed src, address indexed dst, uint wad);
11+
event Deposit(address indexed dst, uint wad);
12+
event Withdrawal(address indexed src, uint wad);
1313

14-
mapping (address => uint) public balanceOf;
15-
mapping (address => mapping (address => uint)) public allowance;
14+
mapping(address => uint) public balanceOf;
15+
mapping(address => mapping(address => uint)) public allowance;
1616

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

42-
function transferFrom(address src, address dst, uint wad)
43-
public
44-
returns (bool)
45-
{
42+
function transferFrom(address src, address dst, uint wad) public returns (bool) {
4643
require(balanceOf[src] >= wad);
4744

4845
if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {

packages/solidity-contracts/contracts/test/FuelBlockHeaderTester.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {FuelBlockHeader, FuelBlockHeaderLib} from "../fuelchain/types/FuelBlockHeader.sol";
55
import {FuelBlockHeaderLite, FuelBlockHeaderLiteLib} from "../fuelchain/types/FuelBlockHeaderLite.sol";

packages/solidity-contracts/contracts/test/MessageTester.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {FuelMessagesEnabled} from "../messaging/FuelMessagesEnabled.sol";
55
import {FuelMessagePortal} from "../fuelchain/FuelMessagePortal.sol";

packages/solidity-contracts/contracts/test/MockPermitToken.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
55
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";

packages/solidity-contracts/contracts/test/NoDecimalsToken.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

packages/solidity-contracts/contracts/test/Token.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

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

packages/solidity-contracts/contracts/test/UpgradeableTester.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: UNLICENSED
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
import {FuelMessagesEnabledUpgradeable} from "../messaging/FuelMessagesEnabledUpgradeable.sol";
55
import {FuelMessagePortal} from "../fuelchain/FuelMessagePortal.sol";

packages/solidity-contracts/contracts/utils/Permit.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: Apache-2.0
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
/// @notice Structure for erc20 token permit signature
55
struct PermitSignature {

packages/solidity-contracts/contracts/vendor/SafeCall.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.9;
2+
pragma solidity 0.8.24;
33

44
/**
55
* @title SafeCall

packages/solidity-contracts/hardhat.config.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ const config: HardhatUserConfig = {
2222
solidity: {
2323
compilers: [
2424
{
25-
version: '0.8.9',
25+
version: '0.8.24',
2626
settings: {
27+
evmVersion: 'cancun',
2728
optimizer: {
2829
enabled: true,
2930
runs: 10000,

packages/solidity-contracts/test/messagesIncoming.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,10 @@ describe('Incoming Messages', async () => {
921921
blockInHistoryProof,
922922
messageInBlockProof
923923
)
924-
).to.be.revertedWith('ReentrancyGuard: reentrant call');
924+
).to.be.revertedWithCustomError(
925+
env.fuelMessagePortal,
926+
'ReentrancyGuardReentrantCall()'
927+
);
925928
expect(
926929
await env.fuelMessagePortal.incomingMessageSuccessful(
927930
messageReentrantId

packages/solidity-contracts/test/messagesIncomingV2.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,10 @@ describe('FuelMessagePortalV2 - Incoming messages', () => {
897897
blockInHistoryProof,
898898
messageInBlockProof
899899
)
900-
).to.be.revertedWith('ReentrancyGuard: reentrant call');
900+
).to.be.revertedWithCustomError(
901+
fuelMessagePortal,
902+
'ReentrancyGuardReentrantCall()'
903+
);
901904
});
902905
});
903906
});

0 commit comments

Comments
 (0)