Commit 4a042355 authored by Maurelian's avatar Maurelian

refactor(ctb): Make GetSigners into a library rather than contract

This required copy/pasting the SignatureDecoder code from the Safe repo.
parent b1574255
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { SignatureDecoder } from "safe-contracts/common/SignatureDecoder.sol"; library GetSigners {
/// @notice Splits signature bytes into `uint8 v, bytes32 r, bytes32 s`.
/// Copied directly from
/// https://github.com/safe-global/safe-contracts/blob/e870f514ad34cd9654c72174d6d4a839e3c6639f/contracts/common/SignatureDecoder.sol
/// @dev Make sure to perform a bounds check for @param pos, to avoid out of bounds access on @param signatures
/// The signature format is a compact form of {bytes32 r}{bytes32 s}{uint8 v}
/// Compact means uint8 is not padded to 32 bytes.
/// @param pos Which signature to read.
/// A prior bounds check of this parameter should be performed, to avoid out of bounds access.
/// @param signatures Concatenated {r, s, v} signatures.
/// @return v Recovery ID or Safe signature type.
/// @return r Output value r of the signature.
/// @return s Output value s of the signature.
function signatureSplit(
bytes memory signatures,
uint256 pos
)
internal
pure
returns (uint8 v, bytes32 r, bytes32 s)
{
// solhint-disable-next-line no-inline-assembly
assembly {
let signaturePos := mul(0x41, pos)
r := mload(add(signatures, add(signaturePos, 0x20)))
s := mload(add(signatures, add(signaturePos, 0x40)))
/**
* Here we are loading the last 32 bytes, including 31 bytes
* of 's'. There is no 'mload8' to do this.
* 'byte' is not working due to the Solidity parser, so lets
* use the second best option, 'and'
*/
v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)
}
}
abstract contract GetSigners is SignatureDecoder {
/// @notice Extract the signers from a set of signatures. /// @notice Extract the signers from a set of signatures.
/// @param dataHash Hash of the data. /// @param dataHash Hash of the data.
/// @param signatures Signature data for identifying signers. /// @param signatures Signature data for identifying signers.
/// @param requiredSignatures Amount of required valid signatures. /// @param requiredSignatures Amount of required valid signatures.
function _getNSigners( function getNSigners(
bytes32 dataHash, bytes32 dataHash,
bytes memory signatures, bytes memory signatures,
uint256 requiredSignatures uint256 requiredSignatures
......
...@@ -9,7 +9,7 @@ import { Enum } from "safe-contracts/common/Enum.sol"; ...@@ -9,7 +9,7 @@ import { Enum } from "safe-contracts/common/Enum.sol";
import { ISemver } from "src/universal/ISemver.sol"; import { ISemver } from "src/universal/ISemver.sol";
import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
contract LivenessGuard is ISemver, GetSigners, BaseGuard { contract LivenessGuard is ISemver, BaseGuard {
using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.AddressSet;
/// @notice Emitted when a new set of signers is recorded. /// @notice Emitted when a new set of signers is recorded.
...@@ -110,7 +110,7 @@ contract LivenessGuard is ISemver, GetSigners, BaseGuard { ...@@ -110,7 +110,7 @@ contract LivenessGuard is ISemver, GetSigners, BaseGuard {
uint256 threshold = safe.getThreshold(); uint256 threshold = safe.getThreshold();
address[] memory signers = address[] memory signers =
_getNSigners({ dataHash: txHash, signatures: signatures, requiredSignatures: threshold }); GetSigners.getNSigners({ dataHash: txHash, signatures: signatures, requiredSignatures: threshold });
for (uint256 i = 0; i < signers.length; i++) { for (uint256 i = 0; i < signers.length; i++) {
lastLive[signers[i]] = block.timestamp; lastLive[signers[i]] = block.timestamp;
......
...@@ -8,7 +8,7 @@ import "test/safe-tools/SafeTestTools.sol"; ...@@ -8,7 +8,7 @@ import "test/safe-tools/SafeTestTools.sol";
import { SignatureDecoder } from "safe-contracts/common/SignatureDecoder.sol"; import { SignatureDecoder } from "safe-contracts/common/SignatureDecoder.sol";
contract GetSigners_Test is Test, SafeTestTools, GetSigners { contract GetSigners_Test is Test, SafeTestTools {
bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b; bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
enum SigTypes { enum SigTypes {
...@@ -98,7 +98,7 @@ contract GetSigners_Test is Test, SafeTestTools, GetSigners { ...@@ -98,7 +98,7 @@ contract GetSigners_Test is Test, SafeTestTools, GetSigners {
// Recover the signatures using the _getNSigners() method. // Recover the signatures using the _getNSigners() method.
address[] memory gotSigners = address[] memory gotSigners =
_getNSigners({ dataHash: digest, signatures: signatures, requiredSignatures: numSigs }); GetSigners.getNSigners({ dataHash: digest, signatures: signatures, requiredSignatures: numSigs });
// Compare the list of recovered signers to the expected signers. // Compare the list of recovered signers to the expected signers.
assertEq(gotSigners.length, numSigs); assertEq(gotSigners.length, numSigs);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment