Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mds1/ce7b65b02c257dab1569fac081e3aa94 to your computer and use it in GitHub Desktop.
Save mds1/ce7b65b02c257dab1569fac081e3aa94 to your computer and use it in GitHub Desktop.
Gitcoin Proposal 65 Report, along with notes and instructions for reproducing the results
From 000de957f54b25be84619a91919495dae7c5a9a7 Mon Sep 17 00:00:00 2001
From: Matt Solomon <matt@mattsolomon.dev>
Date: Thu, 10 Aug 2023 09:20:35 -0700
Subject: [PATCH] feat: add support for Governor Alpha, the Gitcoin governor
There is at least one spot where the logic is hardcoded to be specific
to Gitcoin, where we call the gtc method to get the voting token
address. This will need to be changed if we want to support other
GovernorAlpha instances. Also note this commit overrides the normal
behavior to only run proposal 65
---
checks/check-targets-no-selfdestruct.ts | 2 +-
index.ts | 1 +
types.d.ts | 2 +-
utils/clients/tenderly.ts | 23 ++++-
utils/contracts/governor-alpha.ts | 106 ++++++++++++++++++++++++
utils/contracts/governor.ts | 17 ++++
6 files changed, 145 insertions(+), 6 deletions(-)
create mode 100644 utils/contracts/governor-alpha.ts
diff --git a/checks/check-targets-no-selfdestruct.ts b/checks/check-targets-no-selfdestruct.ts
index aec340b..1787be2 100644
--- a/checks/check-targets-no-selfdestruct.ts
+++ b/checks/check-targets-no-selfdestruct.ts
@@ -78,7 +78,7 @@ async function checkNoSelfdestruct(
addr: string,
provider: JsonRpcProvider
): Promise<'safe' | 'eoa' | 'empty' | 'selfdestruct' | 'delegatecall' | 'trusted'> {
- if (trustedAddrs.map(addr => addr.toLowerCase()).includes(addr.toLowerCase())) return 'trusted'
+ if (trustedAddrs.map((addr) => addr.toLowerCase()).includes(addr.toLowerCase())) return 'trusted'
const [code, nonce] = await Promise.all([provider.getCode(addr), provider.getTransactionCount(addr)])
diff --git a/index.ts b/index.ts
index b54c318..976fabe 100644
--- a/index.ts
+++ b/index.ts
@@ -78,6 +78,7 @@ async function main() {
)
for (const simProposal of simProposals) {
+ if (simProposal.id.toNumber() != 65) continue
if (simProposal.simType === 'new') throw new Error('Simulation type "new" is not supported in this branch')
// Determine if this proposal is already `executed` or currently in-progress (`proposed`)
console.log(` Simulating ${DAO_NAME} proposal ${simProposal.id}...`)
diff --git a/types.d.ts b/types.d.ts
index 9ecc722..0191244 100644
--- a/types.d.ts
+++ b/types.d.ts
@@ -4,7 +4,7 @@ import { JsonRpcProvider } from '@ethersproject/providers'
// --- Simulation configurations ---
// TODO Consider refactoring to an enum instead of string.
-export type GovernorType = 'oz' | 'bravo'
+export type GovernorType = 'oz' | 'bravo' | 'alpha'
interface SimulationConfigBase {
type: 'executed' | 'proposed' | 'new'
diff --git a/utils/clients/tenderly.ts b/utils/clients/tenderly.ts
index 0e2f442..6b28628 100644
--- a/utils/clients/tenderly.ts
+++ b/utils/clients/tenderly.ts
@@ -296,7 +296,10 @@ async function simulateProposed(config: SimulationConfigProposed): Promise<Simul
// For Bravo governors, we use the block right after the proposal ends, and for OZ
// governors we arbitrarily use the next block number.
- const simBlock = governorType === 'bravo' ? proposal.endBlock!.add(1) : BigNumber.from(latestBlock.number + 1)
+ const simBlock =
+ governorType === 'bravo' || governorType === 'alpha'
+ ? proposal.endBlock!.add(1)
+ : BigNumber.from(latestBlock.number + 1)
// For OZ governors we are given the earliest possible execution time. For Bravo governors, we
// Compute the approximate earliest possible execution time based on governance parameters. This
@@ -306,7 +309,7 @@ async function simulateProposed(config: SimulationConfigProposed): Promise<Simul
// proposals call methods that pass in a start timestamp that must be lower than the current
// block timestamp (represented by the `simTimestamp` variable below)
const simTimestamp =
- governorType === 'bravo'
+ governorType === 'bravo' || governorType === 'alpha'
? BigNumber.from(latestBlock.timestamp).add(simBlock.sub(proposal.endBlock!).mul(12))
: proposal.endTime!.add(1)
const eta = simTimestamp // set proposal eta to be equal to the timestamp we simulate at
@@ -332,7 +335,17 @@ async function simulateProposed(config: SimulationConfigProposed): Promise<Simul
const proposalIdBn = BigNumber.from(proposalId)
let governorStateOverrides: Record<string, string> = {}
- if (governorType === 'bravo') {
+ if (governorType === 'alpha') {
+ const proposalKey = `proposals[${proposalIdBn.toString()}]`
+ governorStateOverrides = {
+ proposalCount: proposalId.toString(),
+ [`${proposalKey}.eta`]: eta.toString(),
+ [`${proposalKey}.canceled`]: 'false',
+ [`${proposalKey}.executed`]: 'false',
+ [`${proposalKey}.forVotes`]: votingTokenSupply.toString(),
+ [`${proposalKey}.againstVotes`]: '0',
+ }
+ } else if (governorType === 'bravo') {
const proposalKey = `proposals[${proposalIdBn.toString()}]`
governorStateOverrides = {
proposalCount: proposalId.toString(),
@@ -377,7 +390,9 @@ async function simulateProposed(config: SimulationConfigProposed): Promise<Simul
// ensure Tenderly properly parses the simulation payload
const descriptionHash = keccak256(toUtf8Bytes(description))
const executeInputs =
- governorType === 'bravo' ? [proposalId.toString()] : [targets, values, calldatas, descriptionHash]
+ governorType === 'bravo' || governorType === 'alpha'
+ ? [proposalId.toString()]
+ : [targets, values, calldatas, descriptionHash]
let simulationPayload: TenderlyPayload = {
network_id: '1',
diff --git a/utils/contracts/governor-alpha.ts b/utils/contracts/governor-alpha.ts
new file mode 100644
index 0000000..c149e9c
--- /dev/null
+++ b/utils/contracts/governor-alpha.ts
@@ -0,0 +1,106 @@
+import { BigNumber, BigNumberish, Contract } from 'ethers'
+import { hexZeroPad } from '@ethersproject/bytes'
+import { provider } from '../clients/ethers'
+import { getSolidityStorageSlotUint, to32ByteHexString } from '../utils'
+
+const GOVERNOR_ALPHA_ABI = [
+ 'constructor(address timelock_, address gtc_)',
+ 'event ProposalCanceled(uint256 id)',
+ 'event ProposalCreated(uint256 id, address proposer, address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, uint256 startBlock, uint256 endBlock, string description)',
+ 'event ProposalExecuted(uint256 id)',
+ 'event ProposalQueued(uint256 id, uint256 eta)',
+ 'event VoteCast(address voter, uint256 proposalId, bool support, uint256 votes)',
+ 'function BALLOT_TYPEHASH() view returns (bytes32)',
+ 'function DOMAIN_TYPEHASH() view returns (bytes32)',
+ 'function cancel(uint256 proposalId)',
+ 'function castVote(uint256 proposalId, bool support)',
+ 'function castVoteBySig(uint256 proposalId, bool support, uint8 v, bytes32 r, bytes32 s)',
+ 'function execute(uint256 proposalId) payable',
+ 'function getActions(uint256 proposalId) view returns (address[] targets, uint256[] values, string[] signatures, bytes[] calldatas)',
+ 'function getReceipt(uint256 proposalId, address voter) view returns (tuple(bool hasVoted, bool support, uint96 votes))',
+ 'function gtc() view returns (address)',
+ 'function latestProposalIds(address) view returns (uint256)',
+ 'function name() view returns (string)',
+ 'function proposalCount() view returns (uint256)',
+ 'function proposalMaxOperations() pure returns (uint256)',
+ 'function proposalThreshold() pure returns (uint256)',
+ 'function proposals(uint256) view returns (uint256 id, address proposer, uint256 eta, uint256 startBlock, uint256 endBlock, uint256 forVotes, uint256 againstVotes, bool canceled, bool executed)',
+ 'function propose(address[] targets, uint256[] values, string[] signatures, bytes[] calldatas, string description) returns (uint256)',
+ 'function queue(uint256 proposalId)',
+ 'function quorumVotes() pure returns (uint256)',
+ 'function state(uint256 proposalId) view returns (uint8)',
+ 'function timelock() view returns (address)',
+ 'function votingDelay() pure returns (uint256)',
+ 'function votingPeriod() pure returns (uint256)',
+]
+
+export const governorAlpha = (address: string) => new Contract(address, GOVERNOR_ALPHA_ABI, provider)
+
+// All possible states a proposal might be in.
+// These are defined by the `ProposalState` enum so when we fetch the state of a proposal ID
+// we receive an integer response, and use this to map that integer to the state
+export const PROPOSAL_STATES = {
+ '0': 'Pending',
+ '1': 'Active',
+ '2': 'Canceled',
+ '3': 'Defeated',
+ '4': 'Succeeded',
+ '5': 'Queued',
+ '6': 'Expired',
+ '7': 'Executed',
+}
+
+/**
+ * @notice Returns an object containing various GovernorAlpha slots
+ * @param id Proposal ID
+ */
+export function getAlphaSlots(proposalId: BigNumberish) {
+ // Proposal struct slot offsets, based on the governor's proposal struct
+ // struct Proposal {
+ // uint id;
+ // address proposer;
+ // uint eta;
+ // address[] targets;
+ // uint[] values;
+ // string[] signatures;
+ // bytes[] calldatas;
+ // uint startBlock;
+ // uint endBlock;
+ // uint forVotes;
+ // uint againstVotes;
+ // uint abstainVotes;
+ // bool canceled;
+ // bool executed;
+ // mapping (address => Receipt) receipts;
+ // }
+ const etaOffset = 2
+ const targetsOffset = 3
+ const valuesOffset = 4
+ const signaturesOffset = 5
+ const calldatasOffset = 6
+ const forVotesOffset = 9
+ const againstVotesOffset = 10
+ const abstainVotesOffset = 11
+ const canceledSlotOffset = 12 // this is packed with `executed`
+
+ // Compute and return slot numbers
+ const proposalsMapSlot = '0xa' // proposals ID to proposal struct mapping
+ const proposalSlot = getSolidityStorageSlotUint(proposalsMapSlot, proposalId)
+
+ throw new Error('TODO: implement getAlphaSlots')
+ // return {
+ // proposalCount: to32ByteHexString('0x7'), // slot of the proposalCount storage variable
+ // votingToken: '0x9', // slot of voting token, e.g. UNI, COMP (getter is named after token, so can't generalize it that way),
+ // proposalsMap: proposalsMapSlot,
+ // proposal: proposalSlot,
+ // canceled: hexZeroPad(BigNumber.from(proposalSlot).add(canceledSlotOffset).toHexString(), 32),
+ // eta: hexZeroPad(BigNumber.from(proposalSlot).add(etaOffset).toHexString(), 32),
+ // forVotes: hexZeroPad(BigNumber.from(proposalSlot).add(forVotesOffset).toHexString(), 32),
+ // againstVotes: hexZeroPad(BigNumber.from(proposalSlot).add(againstVotesOffset).toHexString(), 32),
+ // abstainVotes: hexZeroPad(BigNumber.from(proposalSlot).add(abstainVotesOffset).toHexString(), 32),
+ // targets: hexZeroPad(BigNumber.from(proposalSlot).add(targetsOffset).toHexString(), 32),
+ // values: hexZeroPad(BigNumber.from(proposalSlot).add(valuesOffset).toHexString(), 32),
+ // signatures: hexZeroPad(BigNumber.from(proposalSlot).add(signaturesOffset).toHexString(), 32),
+ // calldatas: hexZeroPad(BigNumber.from(proposalSlot).add(calldatasOffset).toHexString(), 32),
+ // }
+}
diff --git a/utils/contracts/governor.ts b/utils/contracts/governor.ts
index b45cacb..4da9d23 100644
--- a/utils/contracts/governor.ts
+++ b/utils/contracts/governor.ts
@@ -4,6 +4,7 @@ import { toUtf8Bytes } from '@ethersproject/strings'
import { keccak256 } from '@ethersproject/keccak256'
import { defaultAbiCoder } from '@ethersproject/abi'
import { provider } from '../clients/ethers'
+import { governorAlpha, getAlphaSlots } from './governor-alpha'
import { governorBravo, getBravoSlots } from './governor-bravo'
import { governorOz, getOzSlots } from './governor-oz'
import { timelock } from './timelock'
@@ -11,6 +12,8 @@ import { GovernorType, ProposalEvent, ProposalStruct } from '../../types'
// --- Exported methods ---
export async function inferGovernorType(address: string): Promise<GovernorType> {
+ if (address === '0xDbD27635A534A3d3169Ef0498beB56Fb9c937489') return 'alpha'
+
const abi = ['function initialProposalId() external view returns (uint256)']
const governor = new Contract(address, abi, provider)
@@ -26,6 +29,7 @@ export async function inferGovernorType(address: string): Promise<GovernorType>
}
export function getGovernor(governorType: GovernorType, address: string) {
+ if (governorType === 'alpha') return governorAlpha(address)
if (governorType === 'bravo') return governorBravo(address)
if (governorType === 'oz') return governorOz(address)
throw new Error(`Unknown governor type: ${governorType}`)
@@ -37,6 +41,7 @@ export async function getProposal(
proposalId: BigNumberish
): Promise<ProposalStruct> {
const governor = getGovernor(governorType, address)
+ if (governorType === 'alpha') return governor.proposals(proposalId)
if (governorType === 'bravo') return governor.proposals(proposalId)
// Piece together the struct for OZ Governors.
@@ -63,12 +68,14 @@ export async function getProposal(
export async function getTimelock(governorType: GovernorType, address: string) {
const governor = getGovernor(governorType, address)
+ if (governorType === 'alpha') return timelock(await governor.timelock())
if (governorType === 'bravo') return timelock(await governor.admin())
return timelock(await governor.timelock())
}
export async function getVotingToken(governorType: GovernorType, address: string, proposalId: BigNumberish) {
const governor = getGovernor(governorType, address)
+ if (governorType === 'alpha') return erc20(await governor.gtc()) // Only supports gitcoin
if (governorType === 'bravo') {
// Get voting token and total supply
const govSlots = getBravoSlots(proposalId)
@@ -81,6 +88,7 @@ export async function getVotingToken(governorType: GovernorType, address: string
}
export function getGovSlots(governorType: GovernorType, proposalId: BigNumberish) {
+ if (governorType === 'alpha') return getAlphaSlots(proposalId)
if (governorType === 'bravo') return getBravoSlots(proposalId)
return getOzSlots(proposalId)
}
@@ -90,6 +98,14 @@ export async function getProposalIds(
address: string,
latestBlockNum: number
): Promise<BigNumber[]> {
+ if (governorType === 'alpha') {
+ // Fetch all proposal IDs
+ const governor = governorAlpha(address)
+ const proposalCreatedLogs = await governor.queryFilter(governor.filters.ProposalCreated(), 0, latestBlockNum)
+ const allProposalIds = proposalCreatedLogs.map((logs) => (logs.args as unknown as ProposalEvent).id!)
+ return allProposalIds
+ }
+
if (governorType === 'bravo') {
// Fetch all proposal IDs
const governor = governorBravo(address)
@@ -129,6 +145,7 @@ export async function generateProposalId(
description: '',
}
): Promise<BigNumber> {
+ if (governorType === 'alpha') throw new Error('generateProposalId not supported for GovernorAlpha')
// Fetch proposal count from the contract and increment it by 1.
if (governorType === 'bravo') {
const count: BigNumber = await governorBravo(address).proposalCount()
--
2.39.2 (Apple Git-143)

The report was generated by patching Seatbelt to support Governor Alpha. There is at least one spot where the logic is hardcoded to be specific to Gitcoin, where we call the .gtc() method to get the voting token address. This will need to be changed if we want to support other GovernorAlpha instances.

To patch seatbelt yourself to reproduce these results:

  1. Follow the standard setup instructions in the Seatbelt repo
  2. Download the attached 0001-feat-add-support-for-Governor-Alpha-the-Gitcoin-gove.patch file
  3. Run git apply 0001-feat-add-support-for-Governor-Alpha-the-Gitcoin-gove.patch

A few things were manually tweaked in the above report:

  1. The title was not found, so Upgrade to Governor Bravo was manually added.
  2. The decoded __acceptAdmin() call was originally not decoded by Tenderly and had the raw 0xb9a61961 function selector.
  3. The warning about adress 0xD73a92Be73EfbFcF3854433A5FcbAbF9c1316073 being an unused EOA that might have code later can be safely ignored—this is the default from address we use in simulations.

Upgrade to Governor Bravo

Updated as of block 17885543 at 8/10/2023, 12:00:59 PM ET

Table of contents

Proposal Text

Upgrade to Governor Bravo

Checks

Reports all state changes from the proposal ✅ Passed

Info:

  • Timelock at 0x57a8865cfB1eCEf7253c27da6B4BC3dAEE5Be518
    • admin changed from 0xdbd27635a534a3d3169ef0498beb56fb9c937489 to 0x9d4c63565d5618310271bf3f3c01b2954c1d1639

Decodes target calldata into a human-readable format ✅ Passed

Info:

  • On contract 0x57a8865cfB1eCEf7253c27da6B4BC3dAEE5Be518, call setPendingAdmin(address pendingAdmin_)() with arguments pendingAdmin_=0x9d4c63565d5618310271bf3f3c01b2954c1d1639 (generic)
  • On contract 0x9D4C63565D5618310271bF3F3c01b2954C1D1639, call __acceptAdmin() (generic)

Reports all events emitted from the proposal ✅ Passed

Info:

  • Timelock at 0x57a8865cfB1eCEf7253c27da6B4BC3dAEE5Be518
    • NewPendingAdmin(newPendingAdmin: 0x9d4c63565d5618310271bf3f3c01b2954c1d1639)
    • NewAdmin(newAdmin: 0x9d4c63565d5618310271bf3f3c01b2954c1d1639)

Check all targets are verified on Etherscan ✅ Passed

Info:

Check all touched contracts are verified on Etherscan ✅ Passed

Info:

Check all targets do not contain selfdestruct ✅ Passed

Info:

Check all touched contracts do not contain selfdestruct ❗❗ Passed with warnings

Warnings:

Info:

Reports on whether the caller needs to send ETH with the call ✅ Passed

Info:

No ETH is required to be sent by the account that executes this proposal.

Runs solc against the verified contracts ✅ Passed

Info:

Compiler warnings for GitcoinGovernor at 0x9D4C63565D5618310271bF3F3c01b2954C1D1639

INFO:CryticCompile:'solc --standard-json --allow-paths /Users/mds/Documents/projects/governance-seatbelt/crytic-export/etherscan-contracts/0x9D4C63565D5618310271bF3F3c01b2954C1D1639-GitcoinGovernor' running

Runs slither against the verified contracts ✅ Passed

Info:

Slither report for GitcoinGovernor at 0x9D4C63565D5618310271bF3F3c01b2954C1D1639

'solc --standard-json --allow-paths /Users/mds/Documents/projects/governance-seatbelt/crytic-export/etherscan-contracts/0x9D4C63565D5618310271bF3F3c01b2954C1D1639-GitcoinGovernor' running
INFO:Detectors:
Governor._execute(uint256,address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#316-328) sends eth to arbitrary user
	Dangerous calls:
	- (success,returndata) = targets[i].call{value: values[i]}(calldatas[i]) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#325)
Governor.relay(address,uint256,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#543-550) sends eth to arbitrary user
	Dangerous calls:
	- (success,returndata) = target.call{value: value}(data) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#548)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations
INFO:Detectors:
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- denominator = denominator / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102)
	- inverse = (3 * denominator) ^ 2 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#117)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- denominator = denominator / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102)
	- inverse *= 2 - denominator * inverse (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#121)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- denominator = denominator / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102)
	- inverse *= 2 - denominator * inverse (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#122)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- denominator = denominator / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102)
	- inverse *= 2 - denominator * inverse (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#123)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- denominator = denominator / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102)
	- inverse *= 2 - denominator * inverse (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#124)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- denominator = denominator / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102)
	- inverse *= 2 - denominator * inverse (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#125)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- denominator = denominator / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#102)
	- inverse *= 2 - denominator * inverse (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#126)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) performs a multiplication on the result of a division:
	- prod0 = prod0 / twos (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#105)
	- result = prod0 * inverse (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#132)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply
INFO:Detectors:
ERC20Votes._writeCheckpoint(ERC20Votes.Checkpoint[],function(uint256,uint256) returns(uint256),uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#239-256) uses a dangerous strict equality:
	- pos > 0 && oldCkpt.fromBlock == block.number (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#251)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities
INFO:Detectors:
Governor._execute(uint256,address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#316-328) ignores return value by Address.verifyCallResult(success,returndata,errorMessage) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#326)
Governor.relay(address,uint256,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#543-550) ignores return value by Address.verifyCallResult(success,returndata,Governor: relay reverted without message) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#549)
GovernorTimelockCompound.queue(address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#91-114) ignores return value by _timelock.queueTransaction(targets[i],values[i],,calldatas[i],eta) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#108)
GovernorTimelockCompound._execute(uint256,address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#119-132) ignores return value by _timelock.executeTransaction(targets[i],values[i],,calldatas[i],eta) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#130)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return
INFO:Detectors:
ERC20Permit.constructor(string).name (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#44) shadows:
	- ERC20.name() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol#62-64) (function)
	- IERC20Metadata.name() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol#17) (function)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing
INFO:Detectors:
Governor.relay(address,uint256,bytes).target (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#544) lacks a zero-check on :
		- (success,returndata) = target.call{value: value}(data) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#548)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation
INFO:Detectors:
GovernorTimelockCompound.queue(address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#91-114) has external calls inside a loop: require(bool,string)(! _timelock.queuedTransactions(keccak256(bytes)(abi.encode(targets[i],values[i],,calldatas[i],eta))),GovernorTimelockCompound: identical proposal action already queued) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#104-107)
GovernorTimelockCompound.queue(address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#91-114) has external calls inside a loop: _timelock.queueTransaction(targets[i],values[i],,calldatas[i],eta) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#108)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop
INFO:Detectors:
Reentrancy in GovernorTimelockCompound.queue(address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#91-114):
	External calls:
	- _timelock.queueTransaction(targets[i],values[i],,calldatas[i],eta) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#108)
	Event emitted after the call(s):
	- ProposalQueued(proposalId,eta) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#111)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3
INFO:Detectors:
GovernorTimelockCompound.state(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#57-72) uses timestamp for comparisons
	Dangerous comparisons:
	- block.timestamp >= eta + _timelock.GRACE_PERIOD() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#67)
GovernorTimelockCompound.queue(address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#91-114) uses timestamp for comparisons
	Dangerous comparisons:
	- require(bool,string)(! _timelock.queuedTransactions(keccak256(bytes)(abi.encode(targets[i],values[i],,calldatas[i],eta))),GovernorTimelockCompound: identical proposal action already queued) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#104-107)
ERC20Votes.delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#146-163) uses timestamp for comparisons
	Dangerous comparisons:
	- require(bool,string)(block.timestamp <= expiry,ERC20Votes: signature expired) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#154)
ERC20Permit.permit(address,address,uint256,uint256,uint8,bytes32,bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#49-68) uses timestamp for comparisons
	Dangerous comparisons:
	- require(bool,string)(block.timestamp <= deadline,ERC20Permit: expired deadline) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#58)
Timers.isPending(Timers.Timestamp) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#34-36) uses timestamp for comparisons
	Dangerous comparisons:
	- timer._deadline > block.timestamp (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#35)
Timers.isExpired(Timers.Timestamp) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#38-40) uses timestamp for comparisons
	Dangerous comparisons:
	- isStarted(timer) && timer._deadline <= block.timestamp (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#39)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp
INFO:Detectors:
ERC20Votes._unsafeAccess(ERC20Votes.Checkpoint[],uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#266-271) uses assembly
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#267-270)
Address._revert(bytes,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#231-243) uses assembly
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#236-239)
Strings.toString(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#18-38) uses assembly
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#24-26)
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#30-32)
ECDSA.tryRecover(bytes32,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#55-72) uses assembly
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#63-67)
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) uses assembly
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#66-70)
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#86-93)
	- INLINE ASM (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#100-109)
GovernorCountingFractional._decodePackedVotes(bytes) (lib/flexible-voting/src/GovernorCountingFractional.sol#238-252) uses assembly
	- INLINE ASM (lib/flexible-voting/src/GovernorCountingFractional.sol#247-251)
GovernorCountingFractional.castVoteWithReasonAndParamsBySig(uint256,uint8,string,bytes,uint8,bytes32,bytes32) (lib/flexible-voting/src/GovernorCountingFractional.sol#269-344) uses assembly
	- INLINE ASM (lib/flexible-voting/src/GovernorCountingFractional.sol#312-327)
	- INLINE ASM (lib/flexible-voting/src/GovernorCountingFractional.sol#338-340)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage
INFO:Detectors:
Different versions of Solidity are used:
	- Version used: ['^0.8.0', '^0.8.1', '^0.8.17', '^0.8.4']
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/IGovernor.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/compatibility/GovernorCompatibilityBravo.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/compatibility/IGovernorCompatibilityBravo.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorSettings.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorVotesComp.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/IGovernorTimelock.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol#3)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20VotesComp.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Context.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Counters.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#4)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#5)
	- ^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/vendor/compound/ICompoundTimelock.sol#4)
	- ^0.8.0 (lib/flexible-voting/src/GovernorCountingFractional.sol#4)
	- ^0.8.1 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#4)
	- ^0.8.17 (src/GitcoinGovernor.sol#2)
	- ^0.8.4 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#3)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used
INFO:Detectors:
Address.functionCall(address,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#85-87) is never used and should be removed
Address.functionCall(address,bytes,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#95-101) is never used and should be removed
Address.functionCallWithValue(address,bytes,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#114-120) is never used and should be removed
Address.functionCallWithValue(address,bytes,uint256,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#128-137) is never used and should be removed
Address.functionDelegateCall(address,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#170-172) is never used and should be removed
Address.functionDelegateCall(address,bytes,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#180-187) is never used and should be removed
Address.functionStaticCall(address,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#145-147) is never used and should be removed
Address.functionStaticCall(address,bytes,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#155-162) is never used and should be removed
Address.isContract(address) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#36-42) is never used and should be removed
Address.verifyCallResultFromTarget(address,bool,bytes,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#195-211) is never used and should be removed
Counters.decrement(Counters.Counter) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Counters.sol#32-38) is never used and should be removed
Counters.reset(Counters.Counter) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Counters.sol#40-42) is never used and should be removed
DoubleEndedQueue.at(DoubleEndedQueue.Bytes32Deque,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#135-140) is never used and should be removed
DoubleEndedQueue.back(DoubleEndedQueue.Bytes32Deque) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#120-127) is never used and should be removed
DoubleEndedQueue.front(DoubleEndedQueue.Bytes32Deque) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#109-113) is never used and should be removed
DoubleEndedQueue.length(DoubleEndedQueue.Bytes32Deque) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#156-162) is never used and should be removed
DoubleEndedQueue.popBack(DoubleEndedQueue.Bytes32Deque) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#66-75) is never used and should be removed
DoubleEndedQueue.pushFront(DoubleEndedQueue.Bytes32Deque,bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#80-87) is never used and should be removed
ECDSA.recover(bytes32,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#88-92) is never used and should be removed
ECDSA.recover(bytes32,bytes32,bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#116-124) is never used and should be removed
ECDSA.toEthSignedMessageHash(bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#197-199) is never used and should be removed
ECDSA.toEthSignedMessageHash(bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#183-187) is never used and should be removed
ECDSA.tryRecover(bytes32,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#55-72) is never used and should be removed
ECDSA.tryRecover(bytes32,bytes32,bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#101-109) is never used and should be removed
ERC20._burn(address,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol#285-301) is never used and should be removed
ERC20._mint(address,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol#259-272) is never used and should be removed
ERC20Votes._add(uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#258-260) is never used and should be removed
ERC20Votes._burn(address,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#185-189) is never used and should be removed
ERC20Votes._maxSupply() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#168-170) is never used and should be removed
ERC20Votes._mint(address,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#175-180) is never used and should be removed
ERC20Votes._subtract(uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#262-264) is never used and should be removed
ERC20VotesComp._maxSupply() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20VotesComp.sol#43-45) is never used and should be removed
GitcoinGovernor._cancel(address[],uint256[],bytes[],bytes32) (src/GitcoinGovernor.sol#121-128) is never used and should be removed
GovernorTimelockCompound._cancel(address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#138-155) is never used and should be removed
Math.ceilDiv(uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#45-48) is never used and should be removed
Math.log10(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#258-290) is never used and should be removed
Math.log10(uint256,Math.Rounding) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#296-301) is never used and should be removed
Math.log2(uint256,Math.Rounding) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#247-252) is never used and should be removed
Math.log256(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#309-333) is never used and should be removed
Math.log256(uint256,Math.Rounding) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#339-344) is never used and should be removed
Math.max(uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#19-21) is never used and should be removed
Math.mulDiv(uint256,uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#55-135) is never used and should be removed
Math.mulDiv(uint256,uint256,uint256,Math.Rounding) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#140-151) is never used and should be removed
Math.sqrt(uint256,Math.Rounding) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#194-199) is never used and should be removed
SafeCast.toInt104(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#901-904) is never used and should be removed
SafeCast.toInt112(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#883-886) is never used and should be removed
SafeCast.toInt120(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#865-868) is never used and should be removed
SafeCast.toInt128(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#847-850) is never used and should be removed
SafeCast.toInt136(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#829-832) is never used and should be removed
SafeCast.toInt144(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#811-814) is never used and should be removed
SafeCast.toInt152(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#793-796) is never used and should be removed
SafeCast.toInt16(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1099-1102) is never used and should be removed
SafeCast.toInt160(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#775-778) is never used and should be removed
SafeCast.toInt168(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#757-760) is never used and should be removed
SafeCast.toInt176(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#739-742) is never used and should be removed
SafeCast.toInt184(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#721-724) is never used and should be removed
SafeCast.toInt192(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#703-706) is never used and should be removed
SafeCast.toInt200(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#685-688) is never used and should be removed
SafeCast.toInt208(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#667-670) is never used and should be removed
SafeCast.toInt216(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#649-652) is never used and should be removed
SafeCast.toInt224(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#631-634) is never used and should be removed
SafeCast.toInt232(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#613-616) is never used and should be removed
SafeCast.toInt24(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1081-1084) is never used and should be removed
SafeCast.toInt240(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#595-598) is never used and should be removed
SafeCast.toInt248(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#577-580) is never used and should be removed
SafeCast.toInt256(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1131-1135) is never used and should be removed
SafeCast.toInt32(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1063-1066) is never used and should be removed
SafeCast.toInt40(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1045-1048) is never used and should be removed
SafeCast.toInt48(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1027-1030) is never used and should be removed
SafeCast.toInt56(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1009-1012) is never used and should be removed
SafeCast.toInt64(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#991-994) is never used and should be removed
SafeCast.toInt72(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#973-976) is never used and should be removed
SafeCast.toInt8(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#1117-1120) is never used and should be removed
SafeCast.toInt80(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#955-958) is never used and should be removed
SafeCast.toInt88(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#937-940) is never used and should be removed
SafeCast.toInt96(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#919-922) is never used and should be removed
SafeCast.toUint104(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#341-344) is never used and should be removed
SafeCast.toUint112(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#324-327) is never used and should be removed
SafeCast.toUint120(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#307-310) is never used and should be removed
SafeCast.toUint136(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#273-276) is never used and should be removed
SafeCast.toUint144(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#256-259) is never used and should be removed
SafeCast.toUint152(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#239-242) is never used and should be removed
SafeCast.toUint16(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#528-531) is never used and should be removed
SafeCast.toUint160(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#222-225) is never used and should be removed
SafeCast.toUint168(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#205-208) is never used and should be removed
SafeCast.toUint176(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#188-191) is never used and should be removed
SafeCast.toUint184(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#171-174) is never used and should be removed
SafeCast.toUint192(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#154-157) is never used and should be removed
SafeCast.toUint200(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#137-140) is never used and should be removed
SafeCast.toUint208(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#120-123) is never used and should be removed
SafeCast.toUint216(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#103-106) is never used and should be removed
SafeCast.toUint232(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#69-72) is never used and should be removed
SafeCast.toUint24(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#511-514) is never used and should be removed
SafeCast.toUint240(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#52-55) is never used and should be removed
SafeCast.toUint248(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#35-38) is never used and should be removed
SafeCast.toUint256(int256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#559-562) is never used and should be removed
SafeCast.toUint40(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#477-480) is never used and should be removed
SafeCast.toUint48(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#460-463) is never used and should be removed
SafeCast.toUint56(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#443-446) is never used and should be removed
SafeCast.toUint72(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#409-412) is never used and should be removed
SafeCast.toUint8(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#545-548) is never used and should be removed
SafeCast.toUint80(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#392-395) is never used and should be removed
SafeCast.toUint88(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#375-378) is never used and should be removed
Strings.toHexString(address) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#67-69) is never used and should be removed
Strings.toHexString(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#43-47) is never used and should be removed
Strings.toHexString(uint256,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#52-62) is never used and should be removed
Strings.toString(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#18-38) is never used and should be removed
Timers.isExpired(Timers.BlockNumber) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#70-72) is never used and should be removed
Timers.isExpired(Timers.Timestamp) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#38-40) is never used and should be removed
Timers.isPending(Timers.BlockNumber) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#66-68) is never used and should be removed
Timers.isPending(Timers.Timestamp) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#34-36) is never used and should be removed
Timers.isStarted(Timers.BlockNumber) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#62-64) is never used and should be removed
Timers.isStarted(Timers.Timestamp) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#30-32) is never used and should be removed
Timers.isUnset(Timers.Timestamp) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#26-28) is never used and should be removed
Timers.reset(Timers.BlockNumber) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#54-56) is never used and should be removed
Timers.reset(Timers.Timestamp) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#22-24) is never used and should be removed
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code
INFO:Detectors:
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/IGovernor.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/compatibility/GovernorCompatibilityBravo.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/compatibility/IGovernorCompatibilityBravo.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorSettings.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorVotesComp.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/IGovernorTimelock.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/utils/IVotes.sol#3) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20VotesComp.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol#4) allows old versions
Pragma version^0.8.1 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Context.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Counters.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Strings.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Timers.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/Math.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol#5) allows old versions
Pragma version^0.8.4 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/structs/DoubleEndedQueue.sol#3) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/lib/openzeppelin-contracts/contracts/vendor/compound/ICompoundTimelock.sol#4) allows old versions
Pragma version^0.8.0 (lib/flexible-voting/src/GovernorCountingFractional.sol#4) allows old versions
Pragma version^0.8.17 (src/GitcoinGovernor.sol#2) allows old versions
solc-0.8.17 is not recommended for deployment
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity
INFO:Detectors:
Low level call in Governor._execute(uint256,address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#316-328):
	- (success,returndata) = targets[i].call{value: values[i]}(calldatas[i]) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#325)
Low level call in Governor.relay(address,uint256,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#543-550):
	- (success,returndata) = target.call{value: value}(data) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#548)
Low level call in Address.sendValue(address,uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#60-65):
	- (success) = recipient.call{value: amount}() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#63)
Low level call in Address.functionCallWithValue(address,bytes,uint256,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#128-137):
	- (success,returndata) = target.call{value: value}(data) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#135)
Low level call in Address.functionStaticCall(address,bytes,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#155-162):
	- (success,returndata) = target.staticcall(data) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#160)
Low level call in Address.functionDelegateCall(address,bytes,string) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#180-187):
	- (success,returndata) = target.delegatecall(data) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/Address.sol#185)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls
INFO:Detectors:
Function IGovernor.COUNTING_MODE() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/IGovernor.sol#107) is not in mixedCase
Function GovernorCompatibilityBravo.COUNTING_MODE() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/compatibility/GovernorCompatibilityBravo.sol#44-46) is not in mixedCase
Function GovernorTimelockCompound.__acceptAdmin() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/GovernorTimelockCompound.sol#168-170) is not in mixedCase
Function ERC20Permit.DOMAIN_SEPARATOR() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#81-83) is not in mixedCase
Variable ERC20Permit._PERMIT_TYPEHASH_DEPRECATED_SLOT (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-ERC20Permit.sol#37) is not in mixedCase
Function IERC20Permit.DOMAIN_SEPARATOR() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol#59) is not in mixedCase
Variable EIP712._CACHED_DOMAIN_SEPARATOR (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#31) is not in mixedCase
Variable EIP712._CACHED_CHAIN_ID (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#32) is not in mixedCase
Variable EIP712._CACHED_THIS (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#33) is not in mixedCase
Variable EIP712._HASHED_NAME (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#35) is not in mixedCase
Variable EIP712._HASHED_VERSION (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#36) is not in mixedCase
Variable EIP712._TYPE_HASH (lib/flexible-voting/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol#37) is not in mixedCase
Function ICompoundTimelock.GRACE_PERIOD() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/vendor/compound/ICompoundTimelock.sol#41) is not in mixedCase
Function ICompoundTimelock.MINIMUM_DELAY() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/vendor/compound/ICompoundTimelock.sol#44) is not in mixedCase
Function ICompoundTimelock.MAXIMUM_DELAY() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/vendor/compound/ICompoundTimelock.sol#47) is not in mixedCase
Function GovernorCountingFractional.COUNTING_MODE() (lib/flexible-voting/src/GovernorCountingFractional.sol#54-56) is not in mixedCase
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions
INFO:Detectors:
GovernorCompatibilityBravo (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/compatibility/GovernorCompatibilityBravo.sol#21-285) does not implement functions:
	- Governor._getVotes(address,uint256,bytes) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/Governor.sol#213-217)
	- IGovernorTimelock.proposalEta(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/IGovernorTimelock.sol#18)
	- IGovernorTimelock.queue(address[],uint256[],bytes[],bytes32) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/IGovernorTimelock.sol#20-25)
	- IGovernor.quorum(uint256) (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/IGovernor.sol#164)
	- IGovernorTimelock.timelock() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/extensions/IGovernorTimelock.sol#16)
	- IGovernor.votingDelay() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/IGovernor.sol#146)
	- IGovernor.votingPeriod() (lib/flexible-voting/lib/openzeppelin-contracts/contracts/governance/IGovernor.sol#155)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions
INFO:Slither:0x9D4C63565D5618310271bF3F3c01b2954C1D1639 analyzed (33 contracts with 88 detectors), 207 result(s) found
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment