Skip to content

Commit

Permalink
feat: support 1271 (#254)
Browse files Browse the repository at this point in the history
* feat: support 1271

* remove blockNumber comment
  • Loading branch information
pscott authored Jan 8, 2025
1 parent 628c18b commit 8e5c1dd
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 92 deletions.
2 changes: 1 addition & 1 deletion src/ProxyFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract ProxyFactory is IProxyFactory {
return
address(
uint160(
uint(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
Expand Down
6 changes: 4 additions & 2 deletions src/Space.sol
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ contract Space is ISpace, Initializable, IERC4824, UUPSUpgradeable, OwnableUpgra
// We don't use the internal `_setMinVotingDuration` and `_setMaxVotingDuration` functions because
// it would revert when `_minVotingDuration > maxVotingDuration` (when the new `_min` is
// bigger than the current `max`).
if (input.minVotingDuration > input.maxVotingDuration)
if (input.minVotingDuration > input.maxVotingDuration) {
revert InvalidDuration(input.minVotingDuration, input.maxVotingDuration);
}

minVotingDuration = input.minVotingDuration;
emit MinVotingDurationUpdated(input.minVotingDuration);
Expand Down Expand Up @@ -156,8 +157,9 @@ contract Space is ISpace, Initializable, IERC4824, UUPSUpgradeable, OwnableUpgra
}

if (input.votingStrategiesToAdd.length > 0) {
if (input.votingStrategiesToAdd.length != input.votingStrategyMetadataURIsToAdd.length)
if (input.votingStrategiesToAdd.length != input.votingStrategyMetadataURIsToAdd.length) {
revert ArrayLengthMismatch();
}
_addVotingStrategies(input.votingStrategiesToAdd);
emit VotingStrategiesAdded(input.votingStrategiesToAdd, input.votingStrategyMetadataURIsToAdd);
}
Expand Down
22 changes: 11 additions & 11 deletions src/interfaces/ICompTimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ interface ICompTimelock {
/// @return The transaction hash.
function queueTransaction(
address target,
uint value,
uint256 value,
string memory signature,
bytes memory data,
uint eta
uint256 eta
) external returns (bytes32);

/// @notice Execute a queued transaction.
Expand All @@ -30,10 +30,10 @@ interface ICompTimelock {
/// @return The transaction return data.
function executeTransaction(
address target,
uint value,
uint256 value,
string memory signature,
bytes memory data,
uint eta
uint256 eta
) external payable returns (bytes memory);

/// @notice Cancel a queued transaction.
Expand All @@ -44,21 +44,21 @@ interface ICompTimelock {
/// @param eta The timestamp at which to execute the transaction, in seconds.
function cancelTransaction(
address target,
uint value,
uint256 value,
string memory signature,
bytes memory data,
uint eta
uint256 eta
) external;

function setDelay(uint delay) external;
function setDelay(uint256 delay) external;

function GRACE_PERIOD() external view returns (uint);
function GRACE_PERIOD() external view returns (uint256);

Check warning on line 55 in src/interfaces/ICompTimelock.sol

View workflow job for this annotation

GitHub Actions / lint

Function name must be in mixedCase

function MINIMUM_DELAY() external view returns (uint);
function MINIMUM_DELAY() external view returns (uint256);

Check warning on line 57 in src/interfaces/ICompTimelock.sol

View workflow job for this annotation

GitHub Actions / lint

Function name must be in mixedCase

function MAXIMUM_DELAY() external view returns (uint);
function MAXIMUM_DELAY() external view returns (uint256);

Check warning on line 59 in src/interfaces/ICompTimelock.sol

View workflow job for this annotation

GitHub Actions / lint

Function name must be in mixedCase

function delay() external view returns (uint);
function delay() external view returns (uint256);

function queuedTransactions(bytes32 hash) external view returns (bool);
}
106 changes: 51 additions & 55 deletions src/utils/SignatureVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.18;

import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import { Choice, IndexedStrategy, Strategy } from "src/types.sol";
import { SXHash } from "src/utils/SXHash.sol";
import { TRUE, FALSE } from "../types.sol";
Expand Down Expand Up @@ -56,30 +57,28 @@ abstract contract SignatureVerifier is EIP712 {
) = abi.decode(data, (address, string, Strategy, bytes));

if (usedSalts[author][salt] != FALSE) revert SaltAlreadyUsed();
// Mark salt as used to prevent replay attacks.
usedSalts[author][salt] = TRUE;

address recoveredAddress = ECDSA.recover(
_hashTypedDataV4(
keccak256(
abi.encode(
PROPOSE_TYPEHASH,
space,
author,
keccak256(bytes(metadataURI)),
executionStrategy.hash(),
keccak256(userProposalValidationParams),
salt
)
bytes32 messageHash = _hashTypedDataV4(
keccak256(
abi.encode(
PROPOSE_TYPEHASH,
space,
author,
keccak256(bytes(metadataURI)),
executionStrategy.hash(),
keccak256(userProposalValidationParams),
salt
)
),
v,
r,
s
)
);

if (recoveredAddress != author) revert InvalidSignature();
bytes memory signature = abi.encodePacked(r, s, v);

// Mark salt as used to prevent replay attacks.
usedSalts[author][salt] = TRUE;
bool valid = SignatureChecker.isValidSignatureNow(author, messageHash, signature);

if (!valid) revert InvalidSignature();
}

/// @dev Verifies an EIP712 signature for a vote call.
Expand All @@ -92,26 +91,25 @@ abstract contract SignatureVerifier is EIP712 {
string memory voteMetadataURI
) = abi.decode(data, (address, uint256, Choice, IndexedStrategy[], string));

address recoveredAddress = ECDSA.recover(
_hashTypedDataV4(
keccak256(
abi.encode(
VOTE_TYPEHASH,
space,
voter,
proposeId,
choice,
userVotingStrategies.hash(),
keccak256(bytes(voteMetadataURI))
)
bytes32 messageHash = _hashTypedDataV4(
keccak256(
abi.encode(
VOTE_TYPEHASH,
space,
voter,
proposeId,
choice,
userVotingStrategies.hash(),
keccak256(bytes(voteMetadataURI))
)
),
v,
r,
s
)
);

if (recoveredAddress != voter) revert InvalidSignature();
bytes memory signature = abi.encodePacked(r, s, v);

bool valid = SignatureChecker.isValidSignatureNow(voter, messageHash, signature);

if (!valid) revert InvalidSignature();
}

/// @dev Verifies an EIP712 signature for an update proposal call.
Expand All @@ -130,29 +128,27 @@ abstract contract SignatureVerifier is EIP712 {
);

if (usedSalts[author][salt] != FALSE) revert SaltAlreadyUsed();
// Mark salt as used to prevent replay attacks.
usedSalts[author][salt] = TRUE;

address recoveredAddress = ECDSA.recover(
_hashTypedDataV4(
keccak256(
abi.encode(
UPDATE_PROPOSAL_TYPEHASH,
space,
author,
proposalId,
executionStrategy.hash(),
keccak256(bytes(metadataURI)),
salt
)
bytes32 messageHash = _hashTypedDataV4(
keccak256(
abi.encode(
UPDATE_PROPOSAL_TYPEHASH,
space,
author,
proposalId,
executionStrategy.hash(),
keccak256(bytes(metadataURI)),
salt
)
),
v,
r,
s
)
);

if (recoveredAddress != author) revert InvalidSignature();
bytes memory signature = abi.encodePacked(r, s, v);

// Mark salt as used to prevent replay attacks.
usedSalts[author][salt] = TRUE;
bool valid = SignatureChecker.isValidSignatureNow(author, messageHash, signature);

if (!valid) revert InvalidSignature();
}
}
2 changes: 1 addition & 1 deletion src/voting-strategies/MerkleWhitelistVotingStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ contract MerkleWhitelistVotingStrategy is IVotingStrategy {
/// @param userParams Parameter array containing the desired member of the whitelist and its associated merkle proof.
/// @return votingPower The voting power of the address if it exists in the whitelist, otherwise reverts.
function getVotingPower(
uint32 /* blockNumber */,
uint32 _blockNumber,

Check warning on line 31 in src/voting-strategies/MerkleWhitelistVotingStrategy.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "_blockNumber" is unused
address voter,
bytes calldata params,
bytes calldata userParams
Expand Down
2 changes: 1 addition & 1 deletion src/voting-strategies/WhitelistVotingStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract WhitelistVotingStrategy is IVotingStrategy {
/// @param userParams Expected to contain a `uint256` corresponding to the voterIndex in the array provided by `params`.
/// @return votingPower The voting power of the address if it exists in the whitelist, otherwise reverts.
function getVotingPower(
uint32 /* blockNumber */,
uint32 _blockNumber,

Check warning on line 29 in src/voting-strategies/WhitelistVotingStrategy.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "_blockNumber" is unused
address voter,
bytes calldata params,
bytes calldata userParams
Expand Down
1 change: 1 addition & 0 deletions test/CompTimelockExecutionStrategy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ abstract contract CompTimelockExecutionStrategyTest is SpaceTest {
error DuplicateMetaTransaction();
error OnlyVetoGuardian();
error InvalidTransaction();

event CompTimelockCompatibleExecutionStrategySetUp(
address owner,
address vetoGuardian,
Expand Down
1 change: 1 addition & 0 deletions test/OptimisticCompTimelockExecutionStrategy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ abstract contract OptimisticCompTimelockExecutionStrategyTest is SpaceTest {
error DuplicateMetaTransaction();
error OnlyVetoGuardian();
error InvalidTransaction();

event OptimisticCompTimelockCompatibleExecutionStrategySetUp(
address owner,
address vetoGuardian,
Expand Down
1 change: 1 addition & 0 deletions test/OptimisticTimelockExecutionStrategy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ abstract contract OptimisticTimelockExecutionStrategyTest is SpaceTest {
error ProposalNotQueued();
error DuplicateExecutionPayloadHash();
error OnlyVetoGuardian();

event OptimisticTimelockExecutionStrategySetUp(
address owner,
address vetoGuardian,
Expand Down
2 changes: 1 addition & 1 deletion test/ProxyFactory.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ contract SpaceFactoryTest is Test, IProxyFactoryEvents, IProxyFactoryErrors, ISp
return
address(
uint160(
uint(
uint256(
keccak256(
abi.encodePacked(
bytes1(0xff),
Expand Down
1 change: 1 addition & 0 deletions test/TimelockExecutionStrategy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ abstract contract TimelockExecutionStrategyTest is SpaceTest {
error ProposalNotQueued();
error DuplicateExecutionPayloadHash();
error OnlyVetoGuardian();

event TimelockExecutionStrategySetUp(
address owner,
address vetoGuardian,
Expand Down
1 change: 1 addition & 0 deletions test/VotingPowerProposalValidationStrategy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { CompToken } from "./mocks/CompToken.sol";

contract PropositionPowerProposalValidationTest is SpaceTest {
error DuplicateFound(uint8 index);

uint256 internal proposalThreshold = 100;
CompToken internal compToken;
IndexedStrategy[] internal userPropositionPowerStrategies;
Expand Down
Loading

0 comments on commit 8e5c1dd

Please sign in to comment.