generated from defi-wonderland/solidity-foundry-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
517 additions
and
461 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 |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity =0.8.19; | ||
|
||
import {Guard} from 'safe-contracts/base/GuardManager.sol'; | ||
import {Enum} from 'safe-contracts/common/Enum.sol'; | ||
import {IGuardCallbackModule} from 'interfaces/IGuardCallbackModule.sol'; | ||
|
||
/** | ||
* @title UpdateStorageMirrorGuard | ||
* @notice This guard is responsible for calling the GuardCallbackModule when a change in settings of a safe is executed. | ||
*/ | ||
contract UpdateStorageMirrorGuard is Guard { | ||
/** | ||
* @notice The address of the guard callback module | ||
*/ | ||
IGuardCallbackModule public immutable GUARD_CALLBACK_MODULE; | ||
|
||
/** | ||
* @notice A boolean that returns true if a tx is changing the safe's settings | ||
*/ | ||
bool public didSettingsChange; | ||
|
||
/** | ||
* @notice The hash of the new settings | ||
*/ | ||
bytes32 public settingsHash; | ||
|
||
constructor(IGuardCallbackModule _guardCallbackModule) { | ||
GUARD_CALLBACK_MODULE = _guardCallbackModule; | ||
} | ||
|
||
/** | ||
* @notice Guard hook that is called before a Safe transaction is executed | ||
*/ | ||
function checkTransaction( | ||
address to, | ||
uint256 value, | ||
bytes memory data, | ||
Enum.Operation operation, | ||
uint256 safeTxGas, | ||
uint256 baseGas, | ||
uint256 gasPrice, | ||
address gasToken, | ||
address payable refundReceiver, | ||
bytes memory signatures, | ||
address msgSender | ||
) external { | ||
didSettingsChange = true; | ||
settingsHash = keccak256(abi.encodePacked('settings')); | ||
} | ||
|
||
/** | ||
* @notice Guard hook that is called after a Safe transaction is executed | ||
* @dev It should call the GuardCallbackModule | ||
* @dev The msg.sender should be the safe | ||
*/ | ||
function checkAfterExecution(bytes32 _txHash, bool _success) external { | ||
if (didSettingsChange && _success) { | ||
GUARD_CALLBACK_MODULE.saveUpdatedSettings(msg.sender, settingsHash); | ||
didSettingsChange = false; | ||
settingsHash = keccak256(abi.encodePacked('')); | ||
} | ||
} | ||
} |
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,6 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity =0.8.19; | ||
|
||
interface IGuardCallbackModule { | ||
function saveUpdatedSettings(address _safe, bytes32 _settingsHash) external; | ||
} |
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,81 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity >=0.8.4 <0.9.0; | ||
|
||
import 'forge-std/Test.sol'; | ||
import {Enum} from 'safe-contracts/common/Enum.sol'; | ||
import {UpdateStorageMirrorGuard} from 'contracts/UpdateStorageMirrorGuard.sol'; | ||
import {IGuardCallbackModule} from 'interfaces/IGuardCallbackModule.sol'; | ||
|
||
abstract contract Base is Test { | ||
address public safe; | ||
IGuardCallbackModule public guardCallbackModule; | ||
UpdateStorageMirrorGuard public updateStorageMirrorGuard; | ||
|
||
bytes32 public immutable SETTINGS_HASH = keccak256(abi.encodePacked('settings')); | ||
|
||
function setUp() public { | ||
safe = makeAddr('safe'); | ||
guardCallbackModule = IGuardCallbackModule(makeAddr('guardCallbackModule')); | ||
updateStorageMirrorGuard = new UpdateStorageMirrorGuard(guardCallbackModule); | ||
} | ||
} | ||
|
||
contract UnitUpdateStorageMirrorGuard is Base { | ||
function testCheckTransaction() public { | ||
assertFalse(updateStorageMirrorGuard.didSettingsChange()); | ||
assertEq(updateStorageMirrorGuard.settingsHash(), bytes32('')); | ||
|
||
vm.prank(safe); | ||
updateStorageMirrorGuard.checkTransaction( | ||
address(0), 0, '', Enum.Operation.Call, 0, 0, 0, address(0), payable(0), '', address(0) | ||
); | ||
|
||
assertTrue(updateStorageMirrorGuard.didSettingsChange()); | ||
assertEq(updateStorageMirrorGuard.settingsHash(), keccak256(abi.encodePacked('settings'))); | ||
} | ||
|
||
function testCheckAfterExecution(bytes32 _txHash) public { | ||
// Call checkTransaction to change didSettingsChange to true | ||
vm.prank(safe); | ||
updateStorageMirrorGuard.checkTransaction( | ||
address(0), 0, '', Enum.Operation.Call, 0, 0, 0, address(0), payable(0), '', address(0) | ||
); | ||
|
||
vm.mockCall( | ||
address(guardCallbackModule), | ||
abi.encodeCall(IGuardCallbackModule.saveUpdatedSettings, (safe, SETTINGS_HASH)), | ||
abi.encode() | ||
); | ||
vm.expectCall( | ||
address(guardCallbackModule), abi.encodeCall(IGuardCallbackModule.saveUpdatedSettings, (safe, SETTINGS_HASH)) | ||
); | ||
vm.prank(safe); | ||
updateStorageMirrorGuard.checkAfterExecution(_txHash, true); | ||
|
||
assertFalse(updateStorageMirrorGuard.didSettingsChange()); | ||
assertEq(updateStorageMirrorGuard.settingsHash(), keccak256(abi.encodePacked(''))); | ||
} | ||
|
||
function testCheckAfterExecutionNoSettingsChange(bytes32 _txHash) public { | ||
vm.prank(safe); | ||
updateStorageMirrorGuard.checkAfterExecution(_txHash, true); | ||
|
||
assertFalse(updateStorageMirrorGuard.didSettingsChange()); | ||
assertEq(updateStorageMirrorGuard.settingsHash(), bytes32('')); | ||
} | ||
|
||
function testCheckAfterExecutionTxFailed(bytes32 _txHash) public { | ||
// Call checkTransaction to change didSettingsChange to true | ||
vm.prank(safe); | ||
updateStorageMirrorGuard.checkTransaction( | ||
address(0), 0, '', Enum.Operation.Call, 0, 0, 0, address(0), payable(0), '', address(0) | ||
); | ||
|
||
vm.prank(safe); | ||
updateStorageMirrorGuard.checkAfterExecution(_txHash, false); | ||
|
||
// Should be true since the tx failed to execute and thus didnt make it to reset | ||
assertTrue(updateStorageMirrorGuard.didSettingsChange()); | ||
assertEq(updateStorageMirrorGuard.settingsHash(), keccak256(abi.encodePacked('settings'))); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.