Developer Docs
AppGitHub
  • Welcome!
  • Smart contracts
    • Core
      • Introduction
      • Deep Dive
      • Smart Contract Reference
        • PWN Hub
          • Tags
        • PWN Config
        • PWN Vault
        • Loan Types
          • Simple Loan
        • Proposals
          • Simple Loan Proposal
            • Simple Proposal
            • List Proposal
            • Elastic Proposal
            • Elastic Chainlink Proposal
            • Dutch Proposal
        • PWN Utilized Credit
        • PWN LOAN
        • PWN Revoked Nonce
        • Peripheral Contracts
          • Acceptor Controller
            • World ID
          • State Fingerprint Computer
            • UniV3
            • Chicken Bonds
          • Pool Adapter
            • Aave
            • Compound
            • ERC4626
        • Miscellaneous
          • PWN Fee Calculator
          • PWN Signature Checker
          • PWN Errors
          • PWN Periphery
          • Timelock
    • PWN DAO
      • Governance
        • Optimistic
        • Token
      • Tokens
        • PWN
        • stPWN
        • vePWN
          • Stake
          • Power
          • Metadata
      • Epoch Clock
      • Miscellaneous
        • Errors
        • EpochPowerLib
    • Tools
      • PWN Safe
        • Architecture
        • Security considerations
        • Smart Contract Reference
          • PWN Safe Factory
          • ATR Module
            • Tokenized Asset Manager
            • Recipient Permission Manager
          • Whitelist
          • ATR Guard
            • Operators context
      • Token Bundler
      • PWN Deployer
    • Libraries
      • MultiToken
    • Contract Addresses
  • More documentation
    • PWN Docs
    • FAQ
    • Audits
    • Using PWN without front-end
  • Deprecated
    • PWN Beta
      • Architecture
      • PWN
        • Off-chain signed offer
        • Offer types
      • PWN Vault
      • PWN LOAN
Powered by GitBook
On this page
  • 1. Summary
  • 2. Important links
  • 3. Contract details
  • Features
  • Inherited contracts, implemented Interfaces and ERCs
  • Functions
  • Events
  • Errors
  • VoteOption Enum
Edit on GitHub
  1. Smart contracts
  2. PWN DAO
  3. Governance

Token

PreviousOptimisticNextTokens

Last updated 6 months ago

1. Summary

The PWN Token governance is based on the Aragon's token voting plugin. The main changes we've made to the plugin are to use our Epoch Clock instead of block numbers, remove VotingMode functionality and use only Standard by default, and we added the assignment of voting rewards on proposal creation.

Aragon OSx VotingMode allows for EarlyExecution and VoteReplacement features. In Standard mode, early execution and vote replacement are disabled.

2. Important links

3. Contract details

  • PWNTokenGovernancePlugin.sol is written in Solidity version 0.8.17

Features

  • Create and Execute Token governance proposals

  • Vote for a proposal

Inherited contracts, implemented Interfaces and ERCs

Functions

createProposal

Overview

Function to create a new token voting proposal.

This function takes five arguments:

  • bytes calldata_metadata - Metadata of the proposal

  • uint256_allowFailureMap - Allows proposal to succeed even if an action reverts. Uses bitmap representation. If the bit at index x is 1, the tx succeeds even if the action at x failed. Passing 0 will be treated as atomic execution.

  • uint64_startDate - The start date of the proposal vote. If 0, the current timestamp is used and the vote starts immediately.

  • uint64_endDate - The end date of the proposal vote. If 0, _startDate + minDuration is used.

Implementation

function createProposal(
    bytes calldata _metadata,
    IDAO.Action[] calldata _actions,
    uint256 _allowFailureMap,
    uint64 _startDate,
    uint64 _endDate,
    VoteOption _voteOption
) external returns (uint256 proposalId) {
    // check that `_msgSender` has enough voting power
    {
        uint256 minProposerVotingPower_ = minProposerVotingPower();

        if (minProposerVotingPower_ != 0) {
            if (votingToken.getVotes(_msgSender()) < minProposerVotingPower_) {
                revert ProposalCreationForbidden(_msgSender());
            }
        }
    }

    uint256 snapshotEpoch = epochClock.currentEpoch();
    uint256 totalVotingPower_ = totalVotingPower(snapshotEpoch);

    if (totalVotingPower_ == 0) {
        revert NoVotingPower();
    }

    (_startDate, _endDate) = _validateProposalDates(_startDate, _endDate);

    proposalId = _createProposal({
        _creator: _msgSender(),
        _metadata: _metadata,
        _startDate: _startDate,
        _endDate: _endDate,
        _actions: _actions,
        _allowFailureMap: _allowFailureMap
    });

    // store proposal related information
    Proposal storage proposal_ = proposals[proposalId];

    proposal_.parameters.startDate = _startDate;
    proposal_.parameters.endDate = _endDate;
    proposal_.parameters.snapshotEpoch = snapshotEpoch.toUint64();
    proposal_.parameters.supportThreshold = supportThreshold();
    proposal_.parameters.minVotingPower = _applyRatioCeiled(totalVotingPower_, minParticipation());

    // reduce costs
    if (_allowFailureMap != 0) {
        proposal_.allowFailureMap = _allowFailureMap;
    }

    for (uint256 i; i < _actions.length;) {
        proposal_.actions.push(_actions[i]);
        unchecked {
            ++i;
        }
    }

    // assign voting reward
    rewardToken.assignProposalReward(proposalId);

    if (_voteOption != VoteOption.None) {
        vote(proposalId, _voteOption);
    }
}
vote

Overview

Function to vote the choosen option. Optionally, this function can also execute the proposal.

This function takes two arguments:

  • uint256proposalId

Implementation

function vote(uint256 _proposalId, VoteOption _voteOption) public {
    address _voter = _msgSender();

    (bool canVote_, uint256 votingPower) = _canVote(_proposalId, _voter, _voteOption);
    if (!canVote_) {
        revert VoteCastForbidden({ proposalId: _proposalId, account: _voter, voteOption: _voteOption });
    }
    _vote(_proposalId, _voteOption, _voter, votingPower);
}
execute

Overview

Function to execute the given proposal.

This function takes one argument:

  • uint256proposalId

Implementation

function execute(uint256 _proposalId) public {
    if (!_canExecute(_proposalId)) {
        revert ProposalExecutionForbidden(_proposalId);
    }
    _execute(_proposalId);
}

Events

event VoteCast(uint256 indexed proposalId, address indexed voter, VoteOption voteOption, uint256 votingPower);
event TokenGovernanceSettingsUpdated(uint32 supportThreshold, uint32 minParticipation, uint64 minDuration, uint256 minProposerVotingPower);
VoteCast

VoteCast event is emitted when a vote is cast by a voter.

This event has four parameters:

  • uint256 indexedproposalId

  • address indexedvoter

  • uint256votingPower - Voting power behind the vote

TokenGovernanceSettingsUpdated

TokenGovernanceSettingsUpdated event is emitted when the token governance settings are updated.

This event has four parameters:

  • uint32supportThreshold

  • uint32minParticipation

  • uint64minDuration - Minimum duration of the proposal vote in seconds

  • uint256minProposerVotingPower - Minimum voting power required to create a proposal

Errors

error NoVotingPower();
error DateOutOfBounds(uint64 limit, uint64 actual);
error MinDurationOutOfBounds(uint64 limit, uint64 actual);
error ProposalCreationForbidden(address sender);
error VoteCastForbidden(uint256 proposalId, address account, VoteOption voteOption);
error ProposalExecutionForbidden(uint256 proposalId);
NoVotingPower

NoVotingPower error is thrown if the voting power is zero.

DateOutOfBounds

DateOutOfBounds error is thrown when a date is out of bounds.

This error has two parameters:

  • uint64limit

  • uint64actual

MinDurationOutOfBounds

MinDurationOutOfBounds error is thrown when the minimum duration value is out of bounds (less than 1 hour or greater than 1 year).

This error has two parameters:

  • uint64limit

  • uint64actual

ProposalCreationForbidden

ProposalCreationForbidden error is thrown when a sender is not allowed to create a proposal.

This error has one parameter:

  • addresssender

VoteCastForbidden

VoteCastForbidden error is thrown when an account is not allowed to cast a vote. This happens when the vote:

  • has not started

  • has ended

  • was executed

  • the account doesn't have voting powers

This error has three parameters:

  • uint256proposalId

  • addressaccount

ProposalExecutionForbidden

ProposalExecutionForbidden error is thrown when a proposal execution is forbidden.

This error has one parameter:

  • uint256proposalId

VoteOption Enum

enum VoteOption {
    None, Abstain, Yes, No
}

IDAO.Action[] calldata_actions - Actions to be executed after the proposal passes. (Learn more about struct)

VoteOption_voteOption - Chosen vote option () to be casted on proposal creation.

VoteOptionvoteOption -

VoteOptionvoteOption -

VoteOptionvoteOption -

IPWNTokenGovernance
IMembership
Initializable
ERC165Upgradeable
PluginUUPSUpgradeable
ProposalUpgradeable
IDAO.Action
VoteOption Enum
VoteOption Enum
VoteOption Enum
VoteOption Enum
osx/packages/contracts/src/plugins/governance/majority-voting/token/TokenVoting.sol at e90ea8f5cd6b98cbba16db07ab7bc0cdbf517f3e · aragon/osxGitHub
Logo