# Governance

### Introduction

The Paribus protocol is governed and upgraded by PBX token-holders, using three distinct components; the [PBX](https://arbiscan.io/token/0xbad58ed9b5f26a002ea250d7a60dc6729a4a2403) token, governance module ([Governor Delegator](https://arbiscan.io/)), and [Timelock](https://arbiscan.io/). Together, these contracts allow the community to propose, vote, and implement changes through the administrative functions of a pToken or the Comptroller. Proposals can modify system parameters, support new markets, or add entirely new functionality to the protocol.

Holders of PBX tokens may stake their tokens in order to get voting rights. Proposals for governance may be made by addresses having at least 10.000.000 voting power.

When a governance proposal is created, it enters a 2 day review period, after which the voting begins. Voting lasts for 5 days; if a majority, and at least 100.000.000 votes are cast for the proposal, it is queued in the Timelock, and can be implemented threedays later. In total, any change to the protocol takes at least 10 days.

### PBX

PBX is an [ERC-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) token that allows the owner to delegate voting rights to themselve by locking it up for a certain period by using the Governor Delegator.

### Key Events

<table><thead><tr><th width="519">Event</th><th>Description</th></tr></thead><tbody><tr><td><code>ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string title, string description)</code></td><td>An event emitted when a new <a href="#propose">proposal</a> is created.</td></tr><tr><td><code>VoteCast(address voter, uint proposalId, bool support, uint votes, string reason)</code></td><td>An event emitted when a <a href="#cast-vote">vote has been cast</a> on a proposal.</td></tr><tr><td><code>ProposalCanceled(uint id)</code></td><td>An event emitted when a proposal has been <a href="#cancel">canceled</a>.</td></tr><tr><td><code>ProposalQueued(uint id, uint eta)</code></td><td>An event emitted when a proposal has been <a href="#queue">queued</a> in the <a href="#timelock">Timelock</a>.</td></tr><tr><td><code>ProposalExecuted(uint id)</code></td><td>An event emitted when a proposal has been <a href="#execute">executed</a> in the <a href="#timelock">Timelock</a>.</td></tr><tr><td><code>NewPBXStake(address indexed account, uint PBXAmount, uint startsAtTimestamp, uint endsAtTimestamp)</code></td><td>An event emitted when an account <a href="#stake-pbx">stake PBX</a> for votes.</td></tr><tr><td><code>PBXWithdrawal(address indexed account, uint PBXAmount, uint startsAtTimestamp, uint endsAtTimestamp)</code></td><td>An event emitted when an account <a href="#withdraw-pbx-stake">withdraw staked PBX</a>.</td></tr><tr><td><code>PBXRewardCampaignStarted(uint startsAtTimestamp, uint endsAtTimestamp, uint PBXRewardsAmount)</code></td><td>An event emitted when a <a href="#start-pbx-reward-campaign">reward campaign</a> started.</td></tr></tbody></table>

### Governor Delegator

Governor Delegator is the governance module of the protocol; it allows addresses with more than 10.000.000 voting power to propose changes to the protocol. Addresses that held voting weight, at the start of the proposal, invoked through the getpriorvotes function, can submit their votes during a 3 day voting period. If a majority, and at least 400,000 votes are cast for the proposal, it is queued in the Timelock, and can be implemented after 2 days.

### Start PBX Reward campaign

Launch PBX Rewards Campaign that is distributed among activate participants of the governance.

**Governor Delegator**

```solidity
function startPBXRewardsCampaign(uint endsAtTimestamp, uint PBXRewardsAmount)
```

* `endsAtTimestamp`: PBX Rewards Campaign end time.
* `PBXRewardsAmount`: Total PBX amount to be distributed
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.startPBXRewardsCampaign(endTime, rewardAmount);
```

**Web3 1.2.6**

```solidity
const endTimestamp = 1735490002; // end of campaign
const rewards = 1000000 * e18 // 100.000 PBX as reward

const tx = gov.methods
  .startPBXRewardsCampaign(endTimestamp, rewards)
  .send({ from: sender });
```

### Calculate PBX Reward

Calculate the amount of PBX that a given account has pending from participating in Governance during an on-going campaign

**Governor Delegator**

```solidity
function calculatePBXReward(address account) returns (uint)
```

* `account`: Account to check for pending rewards
* `RETURN`: The amount of pending PBX for withdraw

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.calculatePBXReward(0x123 ...);
```

**Web3 1.2.6**

```solidity
const account = '0x123...'; // contract address

const rewards = await gov.methods.calculatePBXReward(account).call();
```

### Withdraw PBX Reward

Withdraw the PBX that a given account has pending from participating in Governance during an on-going campaign

**Governor Delegator**

```solidity
function withdrawPBXReward()
```

* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.withdrawPBXReward();
```

**Web3 1.2.6**

```solidity
const tx = gov.methods
  .withdrawPBXReward().send({ from: sender });
```

### Stake PBX

Stake PBX to receive votes. Votes received depends on the staking period.

**Governor Delegator**

```solidity
function stakePBXForVotes(uint addPBXAmount, uint newStakePeriodLenSecs)
```

* `addPBXAmount`: PBX amount to be transferred. Can be 0 when updating existing stakePeriodLen only, without changing the amount
* `newStakePeriodLenSecs`: Stake period length in seconds. Use 0 when updating existing stake without changing existing stakePeriodLen
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.stakePBXForVotes(pbxAmount, stakingPeriod);
```

**Web3 1.2.6**

```solidity
const pbxAmount = 1000000 * e18 // 100.000 PBX to stake
const stakingPeriod = 60 * 24 * 24 * 7 * 13; // 13 weeks

const tx = gov.methods
  .stakePBXForVotes(pbxAmount, stakingPeriod)
  .send({ from: sender });
```

### Withdraw PBX Stake

Withdraw staked PBX after the lockup period finished

**Governor Delegator**

```solidity
function withdrawPBXStake()
```

* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.withdrawPBXStake();
```

**Web3 1.2.6**

```solidity

const tx = gov.methods
  .withdrawPBXStake()
  .send({ from: sender });
```

### Get Current Votes

Gets the balance of votes for an account as of the current block.

**PBX**

```solidity
function getVotes(address account) returns (uint)
```

* `account`: Address of the account in which to retrieve the number of votes.
* `RETURN`: The number of votes (integer).

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint votes = gov.getVotes(0xabc...);
```

**Web3 1.2.6**

```solidity
const account = '0x123...'; // contract address
const votes = await gov.methods.getVotes(account).call();
```

### Get Hypothetical Votes

Get hypothetical number of votes for a given account after staking PBX.

**PBX**

```solidity
function getHypotheticalVotes(address account, uint addPBXAmount, uint newStakePeriodLenSecs) returns (uint votes)
```

* `account`: Address of the account in which to retrieve the number of votes.
* `addPBXAmount`: New stake amount. Can be 0 when updating existing stakePeriodLen only, without changing the amount
* `newStakePeriodLenSecs`: New stake period length in blocks. Use 0 when updating existing stake without changing existing stakePeriodLen
* `RETURN`: The number of votes (integer).

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint votes = gov.getHypotheticalVotes(0xabc..., pbxAmount, stakingPeriod);
```

**Web3 1.2.6**

```solidity
const account = '0x123...'; // contract address
const pbxAmount = 1000000 * e18 // 100.000 PBX to stake
const stakingPeriod = 60 * 24 * 24 * 7 * 13; // 13 weeks

const votes = await gov.methods.
  getHypotheticalVotes(account, pbxAmount, stakingPeriod).call();
```

### Quorum Votes

The required minimum number of votes in support of a proposal for it to succeed.

**Governor Delegator**

```solidity
function quorumVotes() public pure returns (uint)
```

* `RETURN`: The minimum number of votes required for a proposal to succeed.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint quorum = gov.quorumVotes();
```

**Web3 1.2.6**

```js
const quorum = await gov.methods.quorumVotes().call();
```

### Proposal Threshold

The minimum number of votes required for an account to create a proposal. This can be changed through governance.

**Governor Delegator**

```solidity
function proposalThreshold() returns (uint)
```

* `RETURN`: The minimum number of votes required for an account to create a proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint threshold = gov.proposalThreshold();
```

**Web3 1.2.6**

```js
const threshold = await gov.methods.proposalThreshold().call();
```

### Proposal Max Operations

The maximum number of actions that can be included in a proposal. Actions are functions calls that will be made when a proposal succeeds and executes.

**Governor Delegator**

```solidity
function proposalMaxOperations() returns (uint)
```

* `RETURN`: The maximum number of actions that can be included in a proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint operations = gov.proposalMaxOperations();
```

**Web3 1.2.6**

```js
const operations = await gov.methods.proposalMaxOperations().call();
```

### Voting Delay

The number of Ethereum blocks to wait before voting on a proposal may begin. This value is added to the current block number when a proposal is created. This can be changed through governance.

* `MINIMUM_DELAY`: 2 days
* `MAXIMUM_DELAY`: 30 days

**Governor Delegator**

```solidity
function votingDelay() returns (uint)
```

* `RETURN`: Number of blocks to wait before voting on a proposal may begin.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint blocks = gov.votingDelay();
```

**Web3 1.2.6**

```js
const blocks = await gov.methods.votingDelay().call();
```

### Voting Period

The duration of voting on a proposal, in Ethereum blocks. This can be changed through governance.

**Governor Delegator**

```solidity
function votingPeriod() returns (uint)
```

* `RETURN`: The duration of voting on a proposal, in Ethereum blocks.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint blocks = gov.votingPeriod();
```

**Web3 1.2.6**

```js
const blocks = await gov.methods.votingPeriod().call();
```

### Grace Period

The duration after which a queued proposal becomes invalid.

* `GRACE_PERIOD`: 14 days

### Propose

Create a Proposal to change the protocol. E.g., A proposal can set a cToken's interest rate model or risk parameters on the Comptroller. Proposals will be voted on by delegated voters. If there is sufficient support before the voting period ends, the proposal shall be automatically enacted. Enacted proposals are queued and executed in the Compound Timelock contract.

The sender must hold more PBX than the current proposal threshold (`proposalThreshold()`) as of the immediately previous block. The proposal can have up to 10 actions (based on `proposalMaxOperations()`).

The proposer cannot create another proposal if they currently have a pending or active proposal. It is not possible to queue two identical actions in the same block (due to a restriction in the Timelock), therefore actions in a single proposal must be unique, and unique proposals that share an identical action must be queued in different blocks.

**Governor Delegator**

```solidity
function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) returns (uint)
```

* `targets`: The ordered list of target addresses for calls to be made during proposal execution. This array must be the same length as all other array parameters in this function.
* `values`: The ordered list of values (i.e. msg.value) to be passed to the calls made during proposal execution. This array must be the same length as all other array parameters in this function.
* `signatures`: The ordered list of function signatures to be passed during execution. This array must be the same length as all other array parameters in this function.
* `calldatas`: The ordered list of data to be passed to each individual function call during proposal execution. This array must be the same length as all other array parameters in this function.
* `description`: A human readable description of the proposal and the changes it will enact.
* `RETURN`: The ID of the newly created proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint proposalId = gov.propose(targets, values, signatures, calldatas, description);
```

**Web3 1.2.6**

```js
const tx = gov.methods
  .propose(targets, values, signatures, calldatas, description)
  .send({ from: sender });
```

### Queue

After a proposal has succeeded, it is moved into the Timelock waiting period using this function. The waiting period (e.g. 2 days) begins when this function is called. The queue function can be called by any Ethereum address.

**Governor Delegator**

```solidity
function queue(uint proposalId)
```

* `proposalId`: ID of a proposal that has succeeded.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.queue(proposalId);
```

**Web3 1.2.6**

```js
const tx = gov.methods.queue(proposalId).send({ from: sender });
```

### Execute

After the Timelock waiting period has elapsed, a proposal can be executed using this function, which applies the proposal changes to the target contracts. This will invoke each of the actions described in the proposal. The execute function can be called by any Ethereum address. Note: this function is *payable*, so the Timelock contract can invoke payable functions that were selected in the proposal.

**Governor Delegator**

```solidity
function execute(uint proposalId) payable
```

* `proposalId`: ID of a succeeded proposal to execute.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.execute(proposalId).value(999).gas(999)();
```

**Web3 1.2.6**

```js
const tx = gov.methods.execute(proposalId).send({ from: sender, value: 1 });
```

### Cancel

A proposal is eligible to be cancelled at any time prior to its execution, including while queued in the Timelock, using this function.

The cancel function can be called by the proposal creator, or any Ethereum address, if the proposal creator fails to maintain more delegated votes than the proposal threshold (e.g. 25,000).

**Governor Delegator**

```solidity
function cancel(uint proposalId)
```

* `proposalId`: ID of a proposal to cancel. The proposal cannot have already been executed.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.cancel(proposalId);
```

**Web3 1.2.6**

```js
const tx = gov.methods.cancel(proposalId).send({ from: sender });
```

### Get Actions

Gets the actions of a selected proposal. Pass a proposal ID and get the targets, values, signatures and calldatas of that proposal.

**Governor Delegator**

```solidity
function getActions(uint proposalId) returns (uint proposalId) public view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas)
```

* `proposalId`: ID of a proposal in which to get its actions.
* `RETURN`: Reverts if the proposal ID is invalid. If successful, the following 4 references are returned.

1. Array of addresses of contracts the proposal calls.
2. Array of unsigned integers the proposal uses as values.
3. Array of strings of the proposal’s signatures.
4. Array of calldata bytes of the proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint proposalId = 123;
(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) = gov.getActions(proposalId);
```

**Web3 1.2.6**

```js
const {
  0: targets,
  1: values,
  2: signatures,
  3: calldatas,
} = gov.methods.getActions(proposalId).call();
```

### Get Receipt

Gets a proposal ballot receipt of the indicated voter.

**Governor Delegator**

```solidity
function getReceipt(uint proposalId, address voter) returns (Receipt memory)
```

* `proposalId`: ID of the proposal in which to get a voter’s ballot receipt.
* `voter`: Address of the account of a proposal voter.
* `RETURN`: Reverts on error. If successful, returns a Receipt struct for the ballot of the voter address.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
Receipt ballot = gov.getReceipt(proposalId, voterAddress);
```

**Web3 1.2.6**

```js
const proposalId = 11;
const voterAddress = '0x123...';
const result = await gov.methods.getReceipt(proposalId, voterAddress).call();
const { hasVoted, support, votes } = result;
```

### State

Gets the proposal state for the specified proposal. The return value, `ProposalState` is an enumerated type defined in the Governor Delegator contract.

**Governor Delegator**

```solidity
function state(uint proposalId) returns (ProposalState)
```

* `proposalId`: ID of a proposal in which to get its state.
* `RETURN`: Enumerated type ProposalState. The types are Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, and Executed.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
GovernorDelegator.ProposalState state = gov.state(123);
```

**Web3 1.2.6**

```js
const proposalStates = [
  'Pending',
  'Active',
  'Canceled',
  'Defeated',
  'Succeeded',
  'Queued',
  'Expired',
  'Executed',
];
const proposalId = 123;
result = await gov.methods.state(proposalId).call();
const proposalState = proposalStates[result];
```

### Cast Vote

Cast a vote on a proposal. The account's voting weight is determined by the number of votes the account had delegated to it at the time the proposal state became active.

**Governor Delegator**

```solidity
function castVote(uint proposalId, uint8 support)
```

* `proposalId`: ID of a proposal in which to cast a vote.
* `support`: An integer of 0 for against, 1 for in-favor, and 2 for abstain.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.castVote(proposalId, 1);
```

**Web3 1.2.6**

```js
const tx = gov.methods.castVote(proposalId, 0).send({ from: sender });
```

### Cast Vote With Reason

Cast a vote on a proposal with a reason attached to the vote.

**Governor Delegator**

```solidity
function castVoteWithReason(uint proposalId, uint8 support, string calldata reason)
```

* `proposalId`: ID of a proposal in which to cast a vote.
* `support`: An integer of 0 for against, 1 for in-favor, and 2 for abstain.
* `reason`: A string containing the voter's reason for their vote selection.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.castVoteWithReason(proposalId, 2, "I think...");
```

**Web3 1.2.6**

```js
const tx = gov.methods
  .castVoteWithReason(proposalId, 0, 'I think...')
  .send({ from: sender });
```

### Timelock

Each protocol contract is controlled by the [Timelock contract](https://github.com/paribus), which can modify system parameters, logic, and contracts in a 'time-delayed, opt-out' upgrade pattern. The Timelock has a hard-coded minimum delay which is the least amount of notice possible for a governance action. The Timelock contract queues and executes proposals that have passed a Governance vote.

### Pause Guardian

The Comptroller contract designates a Pause Guardian address capable of disabling protocol functionality. Used only in the event of an unforeseen vulnerability, the Pause Guardian has one and only one ability: to disable a select set of functions: Mint, Borrow, Transfer, and Liquidate. The Pause Guardian cannot unpause an action, nor can it ever prevent users from calling Redeem, or Repay Borrow to close positions and exit the protocol. PBX token-holders designate the Pause Guardian address, which is held by the [Community Multi-Sig](https://arbiscan.io).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.paribus.io/for-developers/governance.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
