-
Notifications
You must be signed in to change notification settings - Fork 56
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 #36 from pentagonxyz/rayquaza7/reentrancy-guard
reentrancy guard
- Loading branch information
Showing
8 changed files
with
187 additions
and
8 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
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 |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/// @title Reentrancy Guard | ||
/// @author rayquaza7 | ||
/// @notice A Reentrancy Guard based off <https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol> | ||
/// @license Apache License, Version 2.0 | ||
|
||
#include "./CommonErrors.huff" | ||
|
||
// Constants | ||
#define constant _UNLOCKED = 0x01 | ||
#define constant _LOCKED = 0x02 | ||
#define constant LOCKED_SLOT = FREE_STORAGE_POINTER() | ||
|
||
/// @title Lock | ||
/// @notice Locks the contract to prevent reentrancy | ||
#define fn LOCK() = takes (0) returns (0) { | ||
[_LOCKED] // [0x02] | ||
dup1 // [0x02, 0x02] | ||
[LOCKED_SLOT] // [locked_slot, 0x02, 0x02] | ||
sload // [locked_slot_value, 0x02, 0x02] | ||
lt // [locked_slot_value < 0x02, 0x02] | ||
lock jumpi | ||
|
||
// Otherwise revert with re-entrancy | ||
REENTRANCY(0x00) | ||
|
||
lock: | ||
[LOCKED_SLOT] sstore | ||
} | ||
|
||
/// @title Unlock | ||
/// @notice Unlocks the contract | ||
#define fn UNLOCK() = takes (0) returns (0) { | ||
[_UNLOCKED] [LOCKED_SLOT] sstore | ||
} | ||
|
||
// Tests | ||
|
||
#define test TEST_LOCK() = takes (0) returns (0) { | ||
// Make sure our slot is set to the UNLOCKED state | ||
UNLOCK() | ||
|
||
// Lock | ||
LOCK() | ||
[LOCKED_SLOT] sload | ||
|
||
// We expect the locked slot to be set to 2 - the LOCKED state | ||
0x02 eq succeed jumpi | ||
0x00 dup1 revert | ||
|
||
succeed: | ||
} | ||
|
||
#define test TEST_UNLOCK() = takes (0) returns (0) { | ||
// Make sure our slot is set to the LOCKED state | ||
LOCK() | ||
|
||
// Unlock | ||
UNLOCK() | ||
[LOCKED_SLOT] sload | ||
|
||
// We expect the locked slot to be set to 1 - the UNLOCKED state | ||
0x01 eq succeed jumpi | ||
0x00 dup1 revert | ||
|
||
succeed: | ||
} | ||
|
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 |
---|---|---|
@@ -1,2 +1,52 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import "foundry-huff/HuffDeployer.sol"; | ||
import "forge-std/Test.sol"; | ||
|
||
// Mock Interface | ||
interface IGuard { | ||
function state() external view returns (uint256); | ||
function lock() external; | ||
function unlock() external; | ||
} | ||
|
||
contract ReentranctGuardTest is Test { | ||
IGuard guard; | ||
|
||
function setUp() public { | ||
string memory wrapper_code = vm.readFile("test/utils/mocks/ReentrancyGuardMock.huff"); | ||
guard = IGuard(HuffDeployer.deploy_with_code("utils/ReentrancyGuard", wrapper_code)); | ||
} | ||
|
||
/// @notice Test locking | ||
function testLocking() public { | ||
guard.unlock(); | ||
uint256 state = guard.state(); | ||
assertEq(state, 1); | ||
|
||
// We should remain unlocked | ||
guard.unlock(); | ||
state = guard.state(); | ||
assertEq(state, 1); | ||
|
||
// Let's lock | ||
guard.lock(); | ||
state = guard.state(); | ||
assertEq(state, 2); | ||
|
||
// We should be able to unlock | ||
guard.unlock(); | ||
state = guard.state(); | ||
assertEq(state, 1); | ||
|
||
// We cannot lock twice | ||
guard.lock(); | ||
state = guard.state(); | ||
assertEq(state, 2); | ||
|
||
// vm.expectRevert(bytes4("")); | ||
// guard.lock(); | ||
} | ||
|
||
} |
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,39 @@ | ||
|
||
#define function state() view returns (uint256) | ||
#define function lock() nonpayable returns () | ||
#define function unlock() nonpayable returns () | ||
|
||
#define macro LOCK_WRAPPER() = takes (0) returns (0) { | ||
LOCK() | ||
stop | ||
} | ||
|
||
#define macro UNLOCK_WRAPPER() = takes (0) returns (0) { | ||
UNLOCK() | ||
stop | ||
} | ||
|
||
#define macro GET_STATE() = takes (0) returns (0) { | ||
[LOCKED_SLOT] sload // [LOCKED] | ||
0x00 mstore // [] | ||
0x20 0x00 return // [] | ||
} | ||
|
||
#define macro MAIN() = takes (0) returns (0) { | ||
pc calldataload 0xE0 shr // [selector] | ||
|
||
dup1 __FUNC_SIG(state) eq state_jump jumpi | ||
dup1 __FUNC_SIG(lock) eq lock_jump jumpi | ||
dup1 __FUNC_SIG(unlock) eq unlock_jump jumpi | ||
|
||
DISPATCH_ERROR(0x00) | ||
|
||
state_jump: | ||
GET_STATE() | ||
|
||
lock_jump: | ||
LOCK_WRAPPER() | ||
|
||
unlock_jump: | ||
UNLOCK_WRAPPER() | ||
} |