-
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 #96 from Zarfsec/main
Pausable huff implementation
- Loading branch information
Showing
4 changed files
with
185 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/// @title Pausable | ||
/// @notice SPDX-License-Identifier: MIT | ||
/// @author zarf.eth <https://github.com/zarfsec> | ||
/// @notice A Pausable implementation | ||
|
||
|
||
// Interface | ||
|
||
/// @notice returns whether the contract is paused | ||
#define function isPaused() view returns (bool) | ||
|
||
/// @notice Pauses the contract | ||
/// @dev Only callable when the contract is unpaused. | ||
#define function pause() nonpayable returns () | ||
|
||
/// @notice Unpauses the contract | ||
/// @dev Only callable when the contract is paused. | ||
#define function unpause() nonpayable returns () | ||
|
||
/// @notice Emitted when contract is paused. | ||
#define event Paused(address) | ||
|
||
/// @notice Emitted when contract is unpaused. | ||
#define event Unpaused(address) | ||
|
||
|
||
|
||
// Storage | ||
|
||
/// @notice Paused Storage Slot | ||
#define constant PAUSED_SLOT = FREE_STORAGE_POINTER() | ||
|
||
/// @notice Unpaused representation | ||
#define constant _UNPAUSED = 0x01 | ||
|
||
/// @notice Paused representation | ||
#define constant _PAUSED = 0x02 | ||
|
||
|
||
/// @notice Pausable constructor | ||
#define macro PAUSABLE_CONSTRUCTOR() = takes (0) returns (0) { | ||
[_UNPAUSED] [PAUSED_SLOT] sstore // [] | ||
} | ||
|
||
/// @notice whenNotPaused modifier | ||
#define macro WHEN_NOT_PAUSED_MODIFIER() = takes (0) returns (0) { | ||
[PAUSED_SLOT] sload // [isPaused] | ||
[_UNPAUSED] eq when_not_paused jumpi // [] | ||
0x00 dup1 revert // [] | ||
when_not_paused: // [] | ||
} | ||
|
||
/// @notice whenPaused modifier | ||
#define macro WHEN_PAUSED_MODIFIER() = takes (0) returns (0) { | ||
[PAUSED_SLOT] sload // [isPaused] | ||
[_PAUSED] eq when_paused jumpi // [] | ||
0x00 dup1 revert // [] | ||
when_paused: // [] | ||
} | ||
|
||
/// @notice return whether contract is paused | ||
#define macro PAUSABLE_IS_PAUSED() = takes (0) returns (0) { | ||
0x01 // [1] | ||
[PAUSED_SLOT] sload // [isPaused, 1] | ||
sub // [bool] | ||
0x00 mstore // [] | ||
0x20 0x00 return // [] | ||
} | ||
|
||
|
||
/// @notice Pause the contract | ||
#define macro PAUSABLE_PAUSE() = takes (0) returns (0) { | ||
WHEN_NOT_PAUSED_MODIFIER() // [] | ||
|
||
//emit Paused(address) | ||
caller __EVENT_HASH(Paused) 0x00 dup1 // [0, 0, EVENT_PAUSED, msg.sender] | ||
log2 // [] | ||
|
||
[_PAUSED] [PAUSED_SLOT] sstore // [] | ||
stop | ||
} | ||
|
||
/// @notice Unpause the contract | ||
#define macro PAUSABLE_UNPAUSE() = takes (0) returns (0) { | ||
WHEN_PAUSED_MODIFIER() // [] | ||
|
||
//emit Unpaused(address) | ||
caller __EVENT_HASH(Unpaused) 0x00 dup1 // [0, 0, EVENT_UNPAUSED, msg.sender] | ||
log2 // [] | ||
|
||
[_UNPAUSED] [PAUSED_SLOT] sstore // [] | ||
stop | ||
} |
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,52 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import "foundry-huff/HuffDeployer.sol"; | ||
import "forge-std/Test.sol"; | ||
|
||
|
||
interface IPausable { | ||
function isPaused() external view returns (bool); | ||
function pause() external; | ||
function unpause() external; | ||
} | ||
|
||
|
||
|
||
contract PausableTest is Test { | ||
IPausable pausable; | ||
|
||
function setUp() public { | ||
string memory wrapper_code = vm.readFile("test/utils/mocks/PausableWrappers.huff"); | ||
pausable = IPausable(HuffDeployer.deploy_with_code("utils/Pausable", wrapper_code)); | ||
} | ||
|
||
function testIsPausedByDefault() public { | ||
assertEq(pausable.isPaused(), false); | ||
} | ||
|
||
function testPauseUnPause() public { | ||
pausable.pause(); | ||
assertEq(pausable.isPaused(), true); | ||
|
||
pausable.unpause(); | ||
assertEq(pausable.isPaused(), false); | ||
} | ||
|
||
function testUnpauseWhenUnpaused() public { | ||
assertEq(pausable.isPaused(), false); | ||
|
||
vm.expectRevert(); | ||
pausable.unpause(); | ||
} | ||
|
||
function testPauseWhenPaused() public { | ||
pausable.pause(); | ||
assertEq(pausable.isPaused(), true); | ||
|
||
vm.expectRevert(); | ||
pausable.pause(); | ||
} | ||
|
||
|
||
} |
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 isPaused() view returns (bool) | ||
#define function pause() nonpayable returns () | ||
#define function unpause() nonpayable returns () | ||
|
||
|
||
#define macro CONSTRUCTOR() = takes (0) returns (0) { | ||
PAUSABLE_CONSTRUCTOR() | ||
} | ||
|
||
|
||
#define macro IS_PAUSED_WRAPPER() = takes (0) returns (0) { | ||
PAUSABLE_IS_PAUSED() | ||
} | ||
|
||
#define macro PAUSE_WRAPPER() = takes (0) returns (0) { | ||
PAUSABLE_PAUSE() | ||
} | ||
|
||
#define macro UNPAUSE_WRAPPER() = takes (0) returns (0) { | ||
PAUSABLE_UNPAUSE() | ||
} | ||
|
||
|
||
#define macro MAIN() = takes (0) returns (0) { | ||
pc calldataload 0xe0 shr // [sig] | ||
|
||
dup1 __FUNC_SIG(pause) eq pause jumpi | ||
dup1 __FUNC_SIG(unpause) eq unpause jumpi | ||
dup1 __FUNC_SIG(isPaused) eq is_paused jumpi | ||
|
||
0x00 dup1 revert | ||
|
||
pause: | ||
PAUSE_WRAPPER() | ||
unpause: | ||
UNPAUSE_WRAPPER() | ||
is_paused: | ||
IS_PAUSED_WRAPPER() | ||
} |