Skip to content

Commit

Permalink
Merge pull request #816 from nounsDAO/verbs-data-contract-remove-prop…
Browse files Browse the repository at this point in the history
…-update-candidate-fee

Data: remove candidate creation fee when used to update a proposal
  • Loading branch information
eladmallel authored Dec 20, 2023
2 parents beb86c1 + 9bf65a1 commit 61d2b50
Show file tree
Hide file tree
Showing 8 changed files with 411 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ pragma solidity ^0.8.19;

import { OwnableUpgradeable } from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import { NounsDAOV3Proposals } from '../NounsDAOV3Proposals.sol';
import { NounsTokenLike } from '../NounsDAOInterfaces.sol';
import { NounsTokenLike, NounsDAOStorageV3 } from '../NounsDAOInterfaces.sol';
import { SignatureChecker } from '../../external/openzeppelin/SignatureChecker.sol';
import { UUPSUpgradeable } from '@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol';
import { NounsDAODataEvents } from './NounsDAODataEvents.sol';

interface INounsDAO {
function proposalsV3(uint256 proposalId) external view returns (NounsDAOStorageV3.ProposalCondensed memory);
}

contract NounsDAOData is OwnableUpgradeable, UUPSUpgradeable, NounsDAODataEvents {
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
Expand All @@ -38,6 +42,9 @@ contract NounsDAOData is OwnableUpgradeable, UUPSUpgradeable, NounsDAODataEvents
error FailedWithdrawingETH(bytes data);
error InvalidSignature();
error InvalidSupportValue();
error ProposalToUpdateMustBeUpdatable();
error OnlyProposerCanCreateUpdateCandidate();
error UpdateProposalCandidatesOnlyWorkWithProposalsBySigs();

/**
* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
Expand Down Expand Up @@ -99,6 +106,12 @@ contract NounsDAOData is OwnableUpgradeable, UUPSUpgradeable, NounsDAODataEvents

/**
* @notice Create a new proposal candidate by emitting an event. Nouners can post for free, while non-Nouners must pay `createCandidateCost` in ETH.
* When used to update a proposal created by signatures, `proposalIdToUpdate` should be the ID of the proposal to update,
* and no fee is required.
* Also in this case, the following conditions must be met:
* 1. The proposal must be in the Updatable state.
* 2. `msg.sender` must be the same as the proposer of the proposal to update.
* 3. The proposal must have at least one signer.
* @dev Reverts if the proposer (msg.sender) has already created a candidate with the same slug.
* @param targets the candidate proposal targets.
* @param values the candidate proposal values.
Expand All @@ -117,8 +130,19 @@ contract NounsDAOData is OwnableUpgradeable, UUPSUpgradeable, NounsDAODataEvents
string memory slug,
uint256 proposalIdToUpdate
) external payable {
if (!isNouner(msg.sender) && msg.value < createCandidateCost) revert MustBeNounerOrPaySufficientFee();
if (proposalIdToUpdate > 0) {
INounsDAO dao = INounsDAO(nounsDao);
NounsDAOStorageV3.ProposalCondensed memory propInfo = dao.proposalsV3(proposalIdToUpdate);

if (block.number > propInfo.updatePeriodEndBlock) revert ProposalToUpdateMustBeUpdatable();
if (propInfo.proposer != msg.sender) revert OnlyProposerCanCreateUpdateCandidate();
if (propInfo.signers.length == 0) revert UpdateProposalCandidatesOnlyWorkWithProposalsBySigs();
} else {
if (!isNouner(msg.sender) && msg.value < createCandidateCost) revert MustBeNounerOrPaySufficientFee();
}

if (propCandidates[msg.sender][keccak256(bytes(slug))]) revert SlugAlreadyUsed();
NounsDAOV3Proposals.checkProposalTxs(NounsDAOV3Proposals.ProposalTxs(targets, values, signatures, calldatas));

propCandidates[msg.sender][keccak256(bytes(slug))] = true;

Expand Down Expand Up @@ -170,6 +194,7 @@ contract NounsDAOData is OwnableUpgradeable, UUPSUpgradeable, NounsDAODataEvents
) external payable {
if (!isNouner(msg.sender) && msg.value < updateCandidateCost) revert MustBeNounerOrPaySufficientFee();
if (!propCandidates[msg.sender][keccak256(bytes(slug))]) revert SlugDoesNotExist();
NounsDAOV3Proposals.checkProposalTxs(NounsDAOV3Proposals.ProposalTxs(targets, values, signatures, calldatas));

bytes memory encodedProp = NounsDAOV3Proposals.calcProposalEncodeData(
msg.sender,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,16 @@ interface INounsAuctionHouse {
function setReservePrice(uint256 reservePrice) external;

function setMinBidIncrementPercentage(uint8 minBidIncrementPercentage) external;

function auction()
external
view
returns (
uint256,
uint256,
uint256,
uint256,
address payable,
bool
);
}
2 changes: 1 addition & 1 deletion packages/nouns-contracts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ export { NounsSeeder__factory as NounsSeederFactory } from '../typechain/factori
export { NounsDAOLogicV1__factory as NounsDaoLogicV1Factory } from '../typechain/factories/contracts/governance/NounsDAOLogicV1__factory';
export { NounsDAOLogicV2__factory as NounsDaoLogicV2Factory } from '../typechain/factories/contracts/governance/NounsDAOLogicV2__factory';
export { NounsDAOLogicV3__factory as NounsDaoLogicV3Factory } from '../typechain/factories/contracts/governance/NounsDAOLogicV3__factory';
export { NounsDAOData__factory as NounsDaoDataFactory } from '../typechain/factories/contracts/governance/data/NounsDAOData__factory';
export { NounsDAOData__factory as NounsDaoDataFactory } from '../typechain/factories/contracts/governance/data/NounsDAOData.sol/NounsDAOData__factory';
export { NounsDAOExecutorV2__factory as NounsDaoExecutorV2Factory } from '../typechain/factories/contracts/governance/NounsDAOExecutorV2__factory';
Loading

0 comments on commit 61d2b50

Please sign in to comment.