Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ZumZoom committed Jun 27, 2024
1 parent 1f26b3e commit dc56aa1
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 1 deletion.
148 changes: 148 additions & 0 deletions contracts/mocks/CompatibilityFallbackHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;

Check failure on line 2 in contracts/mocks/CompatibilityFallbackHandler.sol

View workflow job for this annotation

GitHub Actions / lint

Compiler version >=0.7.0 <0.9.0 does not satisfy the ^0.8.0 semver requirement

// This mock is needed because gnosis CompatibilityFallbackHandler.sol does not compile with modern solidity version
// isValidSignature changes argument types location from memory to calldata which is not allowed
// TODO: switch to original version when new version of @gnosis.pm will be released

import "@gnosis.pm/safe-contracts/contracts/handler/DefaultCallbackHandler.sol";
import "@gnosis.pm/safe-contracts/contracts/interfaces/ISignatureValidator.sol";
import "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol";

/// @title Compatibility Fallback Handler - fallback handler to provider compatibility between pre 1.3.0 and 1.3.0+ Safe contracts
/// @author Richard Meissner - <[email protected]>
contract CompatibilityFallbackHandler is DefaultCallbackHandler, ISignatureValidator {
//keccak256(
// "SafeMessage(bytes message)"
//);
bytes32 private constant SAFE_MSG_TYPEHASH = 0x60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca;

Check failure on line 18 in contracts/mocks/CompatibilityFallbackHandler.sol

View workflow job for this annotation

GitHub Actions / lint

'SAFE_MSG_TYPEHASH' should start with _

bytes4 internal constant SIMULATE_SELECTOR = bytes4(keccak256("simulate(address,bytes)"));

Check failure on line 20 in contracts/mocks/CompatibilityFallbackHandler.sol

View workflow job for this annotation

GitHub Actions / lint

'SIMULATE_SELECTOR' should start with _

address internal constant SENTINEL_MODULES = address(0x1);

Check failure on line 22 in contracts/mocks/CompatibilityFallbackHandler.sol

View workflow job for this annotation

GitHub Actions / lint

'SENTINEL_MODULES' should start with _
bytes4 internal constant UPDATED_MAGIC_VALUE = 0x1626ba7e;

Check failure on line 23 in contracts/mocks/CompatibilityFallbackHandler.sol

View workflow job for this annotation

GitHub Actions / lint

'UPDATED_MAGIC_VALUE' should start with _

/**
* Implementation of ISignatureValidator (see `interfaces/ISignatureValidator.sol`)
* @dev Should return whether the signature provided is valid for the provided data.
* @param _data Arbitrary length data signed on the behalf of address(msg.sender)
* @param _signature Signature byte array associated with _data
* @return a bool upon valid or invalid signature with corresponding _data
*/
function isValidSignature(bytes memory _data, bytes memory _signature) public view override returns (bytes4) {
// Caller should be a Safe
GnosisSafe safe = GnosisSafe(payable(msg.sender));
bytes32 messageHash = getMessageHashForSafe(safe, _data);
if (_signature.length == 0) {
require(safe.signedMessages(messageHash) != 0, "Hash not approved");

Check warning on line 37 in contracts/mocks/CompatibilityFallbackHandler.sol

View workflow job for this annotation

GitHub Actions / lint

Use Custom Errors instead of require statements
} else {
safe.checkSignatures(messageHash, _data, _signature);
}
return EIP1271_MAGIC_VALUE;
}

/// @dev Returns hash of a message that can be signed by owners.
/// @param message Message that should be hashed
/// @return Message hash.
function getMessageHash(bytes memory message) public view returns (bytes32) {
return getMessageHashForSafe(GnosisSafe(payable(msg.sender)), message);
}

/// @dev Returns hash of a message that can be signed by owners.
/// @param safe Safe to which the message is targeted
/// @param message Message that should be hashed
/// @return Message hash.
function getMessageHashForSafe(GnosisSafe safe, bytes memory message) public view returns (bytes32) {
bytes32 safeMessageHash = keccak256(abi.encode(SAFE_MSG_TYPEHASH, keccak256(message)));
return keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x01), safe.domainSeparator(), safeMessageHash));
}

/**
* Implementation of updated EIP-1271
* @dev Should return whether the signature provided is valid for the provided data.
* The save does not implement the interface since `checkSignatures` is not a view method.
* The method will not perform any state changes (see parameters of `checkSignatures`)
* @param _dataHash Hash of the data signed on the behalf of address(msg.sender)
* @param _signature Signature byte array associated with _dataHash
* @return a bool upon valid or invalid signature with corresponding _dataHash
* @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
*/
function isValidSignature(bytes32 _dataHash, bytes calldata _signature) external view returns (bytes4) {
ISignatureValidator validator = ISignatureValidator(msg.sender);
bytes4 value = validator.isValidSignature(abi.encode(_dataHash), _signature);
return (value == EIP1271_MAGIC_VALUE) ? UPDATED_MAGIC_VALUE : bytes4(0);
}

/// @dev Returns array of first 10 modules.
/// @return Array of modules.
function getModules() external view returns (address[] memory) {
// Caller should be a Safe
GnosisSafe safe = GnosisSafe(payable(msg.sender));
(address[] memory array, ) = safe.getModulesPaginated(SENTINEL_MODULES, 10);
return array;
}

/**
* @dev Performs a delegetecall on a targetContract in the context of self.
* Internally reverts execution to avoid side effects (making it static). Catches revert and returns encoded result as bytes.
* @param targetContract Address of the contract containing the code to execute.
* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
*/
function simulate(address targetContract, bytes calldata calldataPayload) external returns (bytes memory response) {
// Suppress compiler warnings about not using parameters, while allowing
// parameters to keep names for documentation purposes. This does not
// generate code.
targetContract;
calldataPayload;

// solhint-disable-next-line no-inline-assembly
assembly {
let internalCalldata := mload(0x40)
// Store `simulateAndRevert.selector`.
// String representation is used to force right padding
mstore(internalCalldata, "\xb4\xfa\xba\x09")
// Abuse the fact that both this and the internal methods have the
// same signature, and differ only in symbol name (and therefore,
// selector) and copy calldata directly. This saves us approximately
// 250 bytes of code and 300 gas at runtime over the
// `abi.encodeWithSelector` builtin.
calldatacopy(add(internalCalldata, 0x04), 0x04, sub(calldatasize(), 0x04))

// `pop` is required here by the compiler, as top level expressions
// can't have return values in inline assembly. `call` typically
// returns a 0 or 1 value indicated whether or not it reverted, but
// since we know it will always revert, we can safely ignore it.
pop(
call(
gas(),
// address() has been changed to caller() to use the implementation of the Safe
caller(),
0,
internalCalldata,
calldatasize(),
// The `simulateAndRevert` call always reverts, and
// instead encodes whether or not it was successful in the return
// data. The first 32-byte word of the return data contains the
// `success` value, so write it to memory address 0x00 (which is
// reserved Solidity scratch space and OK to use).
0x00,
0x20
)
)

// Allocate and copy the response bytes, making sure to increment
// the free memory pointer accordingly (in case this method is
// called as an internal function). The remaining `returndata[0x20:]`
// contains the ABI encoded response bytes, so we can just write it
// as is to memory.
let responseSize := sub(returndatasize(), 0x20)
response := mload(0x40)
mstore(0x40, add(response, responseSize))
returndatacopy(response, 0x20, responseSize)

if iszero(mload(0x00)) {
revert(add(response, 0x20), mload(response))
}
}
}
}
1 change: 0 additions & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ module.exports = {
'@1inch/solidity-utils/contracts/mocks/TokenCustomDecimalsMock.sol',
'@1inch/solidity-utils/contracts/mocks/TokenMock.sol',
'@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol',
'@gnosis.pm/safe-contracts/contracts/handler/CompatibilityFallbackHandler.sol',
],
},
zksolc: {
Expand Down

0 comments on commit dc56aa1

Please sign in to comment.