From 6cf85009b31f371dcad20d8245dd23fa6d20fa27 Mon Sep 17 00:00:00 2001 From: solimander Date: Sun, 14 Jan 2024 23:40:54 -0700 Subject: [PATCH 1/4] Checkpointable ERC721 implementation --- .../contracts/starknet/src/common/power.cairo | 1 + .../ethereum_checkpointable_erc721.cairo | 67 +++++++ .../starknet/src/common/utils/constants.cairo | 2 + .../deployments/goerli.json | 1 + .../deployments/mainnet.json | 1 + packages/prop-house-protocol/src/addresses.ts | 3 + packages/prop-house-sdk/src/constants.ts | 6 + .../handlers/checkpointable-erc721.ts | 173 ++++++++++++++++++ .../src/gov-power/handlers/index.ts | 1 + .../prop-house-sdk/src/gov-power/manager.ts | 3 +- .../prop-house-sdk/src/gql/evm/graphql.ts | 1 + .../prop-house-sdk/src/gql/query-wrapper.ts | 9 + packages/prop-house-sdk/src/gql/types.ts | 9 +- packages/prop-house-sdk/src/types.ts | 10 +- packages/prop-house-subgraph/schema.graphql | 1 + .../prop-house-subgraph/src/lib/constants.ts | 1 + packages/prop-house-subgraph/src/lib/utils.ts | 3 + 17 files changed, 289 insertions(+), 3 deletions(-) create mode 100644 packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_checkpointable_erc721.cairo create mode 100644 packages/prop-house-sdk/src/gov-power/handlers/checkpointable-erc721.ts diff --git a/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo b/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo index 3e7d2548e..c420d9916 100644 --- a/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo +++ b/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo @@ -2,4 +2,5 @@ mod allowlist; mod ethereum_balance_of_erc20; mod ethereum_balance_of_erc1155; mod ethereum_balance_of; +mod ethereum_checkpointable_erc721 mod vanilla; diff --git a/packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_checkpointable_erc721.cairo b/packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_checkpointable_erc721.cairo new file mode 100644 index 000000000..54b87a26c --- /dev/null +++ b/packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_checkpointable_erc721.cairo @@ -0,0 +1,67 @@ +#[starknet::contract] +mod EthereumCheckpointableERC721GovernancePowerStrategy { + use starknet::ContractAddress; + use prop_house::common::utils::constants::{MASK_96, TWO_POW_32}; + use prop_house::common::utils::traits::IGovernancePowerStrategy; + use prop_house::common::libraries::single_slot_proof::SingleSlotProof; + use prop_house::common::utils::storage::{get_slot_key, get_nested_slot_key}; + use array::{ArrayTrait, SpanTrait}; + use option::OptionTrait; + use zeroable::Zeroable; + use traits::Into; + + #[storage] + struct Storage {} + + #[constructor] + fn constructor(ref self: ContractState, fact_registry: ContractAddress, ethereum_block_registry: ContractAddress) { + let mut ssp_state = SingleSlotProof::unsafe_new_contract_state(); + SingleSlotProof::initializer(ref ssp_state, fact_registry, ethereum_block_registry); + } + + #[external(v0)] + impl EthereumCheckpointableERC721GovernancePowerStrategy of IGovernancePowerStrategy { + /// Returns the governance power of the user at the given timestamp. + /// * `timestamp` - The timestamp at which to get the governance power. + /// * `user` - The address of the user. + /// * `params` - The params, containing the contract address and the slot indices. + /// * `user_params` - The user params, containing the slots and MPT proofs. + fn get_power( + self: @ContractState, timestamp: u64, user: felt252, params: Span, mut user_params: Span, + ) -> u256 { + let params_len = params.len(); + + // Expects contract_address, num_checkpoints_slot_index, and checkpoints_slot_index, with an optional governance_power_multiplier + assert(params_len == 3 || params_len == 4, 'EthC721: Bad param length'); + + let contract_address = *params.at(0); + let num_checkpoints_slot_index = *params.at(1); + let checkpoints_slot_index = *params.at(2); + + let (num_checkpoints_user_params, latest_checkpoint_user_params) = Serde::<(Span, Span)>::deserialize(ref user_params).unwrap(); + + let num_checkpoints_slot = get_slot_key(num_checkpoints_slot_index.into(), user.into()); + let num_checkpoints = SingleSlotProof::get_slot_value( + @SingleSlotProof::unsafe_new_contract_state(), timestamp, contract_address, num_checkpoints_slot, params, num_checkpoints_user_params + ); + assert(num_checkpoints.is_non_zero(), 'EthC721: No checkpoints'); + + let latest_checkpoint_slot = get_nested_slot_key(checkpoints_slot_index.into(), array![user.into(), num_checkpoints - 1].span()); + let latest_checkpoint = SingleSlotProof::get_slot_value( + @SingleSlotProof::unsafe_new_contract_state(), timestamp, contract_address, latest_checkpoint_slot, params, latest_checkpoint_user_params + ); + let governance_power = (latest_checkpoint / TWO_POW_32) & MASK_96; + + assert(governance_power.is_non_zero(), 'EthC721: No governance power'); + + if params_len == 3 { + return governance_power; + } + + let governance_power_multiplier = *params.at(3); + assert(governance_power_multiplier.is_non_zero(), 'EthC721: Invalid multiplier'); + + governance_power * governance_power_multiplier.into() + } + } +} diff --git a/packages/prop-house-protocol/contracts/starknet/src/common/utils/constants.cairo b/packages/prop-house-protocol/contracts/starknet/src/common/utils/constants.cairo index 047350b79..a6aacc1d7 100644 --- a/packages/prop-house-protocol/contracts/starknet/src/common/utils/constants.cairo +++ b/packages/prop-house-protocol/contracts/starknet/src/common/utils/constants.cairo @@ -4,12 +4,14 @@ const MASK_8: u256 = 0xFF; const MASK_16: u256 = 0xFFFF; const MASK_32: u256 = 0xFFFFFFFF; const MASK_64: u256 = 0xFFFFFFFFFFFFFFFF; +const MASK_96: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFF; const MASK_160: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; const MASK_192: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; const MASK_250: u256 = 0x03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; const TWO_POW_8: u256 = 0x100; const TWO_POW_24: u256 = 0x1000000; +const TWO_POW_32: u256 = 0x100000000; const TWO_POW_72: u256 = 0x1000000000000000000; const TWO_POW_88: u256 = 0x10000000000000000000000; const TWO_POW_152: u256 = 0x100000000000000000000000000000000000000; diff --git a/packages/prop-house-protocol/deployments/goerli.json b/packages/prop-house-protocol/deployments/goerli.json index cb67bb450..5f7ef2a0a 100644 --- a/packages/prop-house-protocol/deployments/goerli.json +++ b/packages/prop-house-protocol/deployments/goerli.json @@ -27,6 +27,7 @@ "ethBalanceOfGovPowerStrategy": "0x4ff2eee9b0d91eda2ae6dd620d34f5c6ddf11990d948088753acb2a3cca2f93", "ethBalanceOfErc20GovPowerStrategy": "0x000000000000000000000000000000000000000000000000000000000000000", "ethBalanceOfErc1155GovPowerStrategy": "0x3016c4e41fe92c2ce5cc1a4686c7c22ba5d810e7686546c8a44e8c78a4ba154", + "ethCheckpointableErc721GovPowerStrategy": "0x000000000000000000000000000000000000000000000000000000000000000", "herodotus": { "factRegistry": "0x5e6c5b45485f2eb7609a27e413aad727536b3590a64e18ceb5950e30852288f", "l1HeadersStore": "0x1d9b36a00d7d5300e5da456c56d09c46dfefbc91b3a6b1552b6f2a34d6e34c4" diff --git a/packages/prop-house-protocol/deployments/mainnet.json b/packages/prop-house-protocol/deployments/mainnet.json index 58f1d8900..5c8823914 100644 --- a/packages/prop-house-protocol/deployments/mainnet.json +++ b/packages/prop-house-protocol/deployments/mainnet.json @@ -27,6 +27,7 @@ "ethBalanceOfGovPowerStrategy": "0x6ddcc94a4225843546a9b118a2733fd924d6b8a6467279cbe6a1aea79daca54", "ethBalanceOfErc20GovPowerStrategy": "0x196cf5ceba8e98abe1e633d6184cd28c1e1ebd09ea71f89867dd4c5fda97bbe", "ethBalanceOfErc1155GovPowerStrategy": "0x6d22f17522d6992eb479deb850e96f9454fc2f6c127993ab2ef9d411f467e8", + "ethCheckpointableErc721GovPowerStrategy": "0x10f7529ec5df9069a06191deb7cd2c4158c2b59879e2544cb45dc221daff429", "herodotus": { "factRegistry": "0x002081b2d3de51f295e7516257f68bd9f06acbc7f19ba49410c100afbe57540f", "l1HeadersStore": "0x008caacc818a97ef9122aa67b3b0e14d10e2959b262e7e785f47e20a36ef0ce0" diff --git a/packages/prop-house-protocol/src/addresses.ts b/packages/prop-house-protocol/src/addresses.ts index b6bf8f862..1105d1cb9 100644 --- a/packages/prop-house-protocol/src/addresses.ts +++ b/packages/prop-house-protocol/src/addresses.ts @@ -22,6 +22,7 @@ export interface GovPowerStrategies { balanceOf: string; balanceOfErc20: string; balanceOfErc1155: string; + checkpointableErc721: string; vanilla: string; } @@ -89,6 +90,7 @@ export const contracts: Record = { balanceOf: goerli.starknet.address.ethBalanceOfGovPowerStrategy, balanceOfErc20: goerli.starknet.address.ethBalanceOfErc20GovPowerStrategy, balanceOfErc1155: goerli.starknet.address.ethBalanceOfErc1155GovPowerStrategy, + checkpointableErc721: goerli.starknet.address.ethCheckpointableErc721GovPowerStrategy, vanilla: goerli.starknet.address.vanillaGovPowerStrategy, }, auth: { @@ -132,6 +134,7 @@ export const contracts: Record = { balanceOf: mainnet.starknet.address.ethBalanceOfGovPowerStrategy, balanceOfErc20: mainnet.starknet.address.ethBalanceOfErc20GovPowerStrategy, balanceOfErc1155: mainnet.starknet.address.ethBalanceOfErc1155GovPowerStrategy, + checkpointableErc721: mainnet.starknet.address.ethCheckpointableErc721GovPowerStrategy, vanilla: constants.HashZero, }, auth: { diff --git a/packages/prop-house-sdk/src/constants.ts b/packages/prop-house-sdk/src/constants.ts index 5fa95c072..cf5fc6455 100644 --- a/packages/prop-house-sdk/src/constants.ts +++ b/packages/prop-house-sdk/src/constants.ts @@ -17,6 +17,12 @@ export const BALANCE_OF_FUNC = 'function balanceOf(address account) external vie // prettier-ignore export const BALANCE_OF_ERC1155_FUNC = 'function balanceOf(address account, uint256 id) external view returns (uint256)'; +/** + * The `getCurrentVotes` function signature. + */ +// prettier-ignore +export const GET_CURRENT_VOTES_FUNC = 'function getCurrentVotes(address account) external view returns (uint96)'; + /** * The address used to query `balanceOf` functions to detect the slot index. */ diff --git a/packages/prop-house-sdk/src/gov-power/handlers/checkpointable-erc721.ts b/packages/prop-house-sdk/src/gov-power/handlers/checkpointable-erc721.ts new file mode 100644 index 000000000..ed9e43277 --- /dev/null +++ b/packages/prop-house-sdk/src/gov-power/handlers/checkpointable-erc721.ts @@ -0,0 +1,173 @@ +import { ChainConfig, GovPowerStrategyType, GovPowerConfig, AccountField, CheckpointableERC721Config } from '../../types'; +import { SingleSlotProofHandler } from './base'; +import { encoding, splitUint256, storageProofs } from '../../utils'; +import { BigNumber } from '@ethersproject/bignumber'; +import { Contract } from '@ethersproject/contracts'; +import { GET_CURRENT_VOTES_FUNC } from '../../constants'; +import { Call } from 'starknet'; + +export class CheckpointableERC721Handler extends SingleSlotProofHandler { + /** + * Information about the Nouns mainnet ERC721 token + */ + private static readonly _NOUNS = { + ADDRESS: '0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03', + NUM_CHECKPOINTS_SLOT_INDEX: '0x0d', + CHECKPOINTS_SLOT_INDEX: '0x0c', + }; + + /** + * Returns a `BalanceOfHandler` instance for the provided chain configuration + * @param config The chain config + */ + public static for(config: ChainConfig) { + return new CheckpointableERC721Handler(config); + } + + /** + * The governance power strategy type + */ + public get type() { + return GovPowerStrategyType.CHECKPOINTABLE_ERC721; + } + + /** + * The governance power strategy address + */ + public get address() { + return this._addresses.starknet.govPower.checkpointableErc721; + } + + /** + * @notice Get the governance power strategy params that will be shared amongst all users + * @param strategy The governance power strategy information + */ + public async getStrategyParams(strategy: CheckpointableERC721Config): Promise { + if (strategy.address.toLowerCase() !== CheckpointableERC721Handler._NOUNS.ADDRESS) { + throw new Error('This handler currently only supports the Nouns ERC721 token'); + } + if (strategy.multiplier && BigNumber.from(strategy.multiplier).gt(1)) { + return [ + strategy.address, + CheckpointableERC721Handler._NOUNS.NUM_CHECKPOINTS_SLOT_INDEX, + CheckpointableERC721Handler._NOUNS.CHECKPOINTS_SLOT_INDEX, + strategy.multiplier.toString() + ]; + } + return [ + strategy.address, + CheckpointableERC721Handler._NOUNS.NUM_CHECKPOINTS_SLOT_INDEX, + CheckpointableERC721Handler._NOUNS.CHECKPOINTS_SLOT_INDEX, + ]; + } + + public async getUserParams(account: string, timestamp: string, strategyId: string) { + const strategy = await this.getStrategyAddressAndParams(strategyId); + const [contractAddress, numCheckpointsSlotIndex, checkpointsSlotIndex] = strategy.params; + + const numCheckpointsSlotKey = encoding.getSlotKey(account, numCheckpointsSlotIndex); + const numCheckpointsSlotKeyU256 = splitUint256.SplitUint256.fromHex(numCheckpointsSlotKey); + + const checkpointsSlotKey = encoding.getSlotKey(account, checkpointsSlotIndex); + const checkpointsSlotKeyU256 = splitUint256.SplitUint256.fromHex(checkpointsSlotKey); + + const block = await this.getBlockNumberForTimestamp(timestamp); + const [numCheckpointsProofInputs, checkpointsProofInputs] = await Promise.all([ + this.fetchProofInputs(contractAddress, numCheckpointsSlotKey, block), + this.fetchProofInputs(contractAddress, checkpointsSlotKey, block), + ]); + + const numCheckpointsUserParams = [ + // Storage Key (u256) + numCheckpointsSlotKeyU256.low, + numCheckpointsSlotKeyU256.high, + // Storage Proof + `0x${numCheckpointsProofInputs.storageProofSubArrayLength.toString(16)}`, + ...numCheckpointsProofInputs.storageProof, + ]; + const checkpointsUserParams = [ + // Storage Key (u256) + checkpointsSlotKeyU256.low, + checkpointsSlotKeyU256.high, + // Storage Proof + `0x${checkpointsProofInputs.storageProofSubArrayLength.toString(16)}`, + ...checkpointsProofInputs.storageProof, + ]; + + + return [ + `0x${numCheckpointsUserParams.length.toString(16)}`, + ...numCheckpointsUserParams, + `0x${checkpointsUserParams.length.toString(16)}`, + ...checkpointsUserParams, + ] + } + + public async getStrategyPreCalls( + account: string, + timestamp: string, + strategyId: string, + ): Promise { + const strategy = await this.getStrategyAddressAndParams(strategyId); + const [contractAddress, numCheckpointsSlotIndex] = strategy.params; + + // Only the account proof is used, so it's okay to only query with the first slot key. + const slotKey = encoding.getSlotKey(account, numCheckpointsSlotIndex); + + const block = await this.getBlockNumberForTimestamp(timestamp); + const storageHash = await this.getStorageHash(contractAddress, block); + + // We only need to prove the account if the storage hash hasn't been populated. + if (storageHash.isZero()) { + const [proofInputs, processBlockInputs] = await Promise.all([ + this.fetchProofInputs(contractAddress, slotKey, block), + storageProofs.getProcessBlockInputsForBlockNumber( + this.provider, + block, + this._evmChainId, + ), + ]); + return [ + { + contractAddress: this._addresses.starknet.herodotus.factRegistry, + entrypoint: 'prove_account', + calldata: [ + // Account Fields + 1, + AccountField.StorageHash, + // Block Header RLP + processBlockInputs.headerInts.length, + ...processBlockInputs.headerInts, + // Account + contractAddress, + // Proof + proofInputs.accountProofSubArrayLength, + ...proofInputs.accountProof, + ], + }, + ]; + } + return []; + } + + /** + * Get the total governance power for the provided config + * @param config The governance power strategy config information + */ + public async getPower(config: GovPowerConfig): Promise { + const block = await this.getBlockNumberForTimestamp(config.timestamp); + const token = BigNumber.from(config.params[0]).toHexString(); + const balance = await this.contractFor(token).getCurrentVotes(config.user, { + blockTag: block, + }); + return balance.mul(config.params?.[3] ?? 1); + } + + /** + * Returns a contract instance for the provided token address + * @param token The token address + */ + private contractFor(token: string) { + return new Contract(token, [GET_CURRENT_VOTES_FUNC], this._evm); + } +} diff --git a/packages/prop-house-sdk/src/gov-power/handlers/index.ts b/packages/prop-house-sdk/src/gov-power/handlers/index.ts index 8994a8f5a..e8893dd30 100644 --- a/packages/prop-house-sdk/src/gov-power/handlers/index.ts +++ b/packages/prop-house-sdk/src/gov-power/handlers/index.ts @@ -3,4 +3,5 @@ export { AllowlistHandler } from './allowlist'; export { BalanceOfHandler } from './balance-of'; export { BalanceOfERC20Handler } from './balance-of-erc20'; export { BalanceOfERC1155Handler } from './balance-of-erc1155'; +export { CheckpointableERC721Handler } from './checkpointable-erc721'; export { VanillaHandler } from './vanilla'; diff --git a/packages/prop-house-sdk/src/gov-power/manager.ts b/packages/prop-house-sdk/src/gov-power/manager.ts index 5377bff1e..7a741968a 100644 --- a/packages/prop-house-sdk/src/gov-power/manager.ts +++ b/packages/prop-house-sdk/src/gov-power/manager.ts @@ -12,13 +12,14 @@ import { BalanceOfHandler, BalanceOfERC1155Handler, BalanceOfERC20Handler, + CheckpointableERC721Handler, VanillaHandler, AllowlistHandler, StrategyHandlerBase, } from './handlers'; export class GovPowerManager { - private readonly _defaults = [BalanceOfHandler, BalanceOfERC20Handler, BalanceOfERC1155Handler, VanillaHandler, AllowlistHandler]; + private readonly _defaults = [BalanceOfHandler, BalanceOfERC20Handler, BalanceOfERC1155Handler, CheckpointableERC721Handler, VanillaHandler, AllowlistHandler]; private readonly _all: StrategyHandlerBase>[]; constructor(private readonly _config: GovPowerChainConfig) { diff --git a/packages/prop-house-sdk/src/gql/evm/graphql.ts b/packages/prop-house-sdk/src/gql/evm/graphql.ts index 6bc000ec9..ba70ae346 100644 --- a/packages/prop-house-sdk/src/gql/evm/graphql.ts +++ b/packages/prop-house-sdk/src/gql/evm/graphql.ts @@ -853,6 +853,7 @@ export enum GovPowerStrategyType { Allowlist = 'ALLOWLIST', BalanceOf = 'BALANCE_OF', BalanceOfErc1155 = 'BALANCE_OF_ERC1155', + CheckpointableErc721 = 'CHECKPOINTABLE_ERC721', Unknown = 'UNKNOWN', Vanilla = 'VANILLA', } diff --git a/packages/prop-house-sdk/src/gql/query-wrapper.ts b/packages/prop-house-sdk/src/gql/query-wrapper.ts index 1a8909795..153c2bbac 100644 --- a/packages/prop-house-sdk/src/gql/query-wrapper.ts +++ b/packages/prop-house-sdk/src/gql/query-wrapper.ts @@ -960,6 +960,15 @@ export class QueryWrapper { ...(multiplier ? { multiplier: Number(multiplier) } : {}), }; }; + case GovPowerStrategyType.CHECKPOINTABLE_ERC721: { + const [address, , , multiplier] = strategy.params; + return { + id: strategy.id, + strategyType: GovPowerStrategyType.CHECKPOINTABLE_ERC721, + tokenAddress: `0x${BigInt(address).toString(16)}`, + ...(multiplier ? { multiplier: Number(multiplier) } : {}), + }; + }; case GovPowerStrategyType.ALLOWLIST: { const cid = encoding.stringFromLE(strategy.params.slice(1).map(p => p.toString())); const allowlist: AllowlistJson = await ipfs.getJSON(cid); diff --git a/packages/prop-house-sdk/src/gql/types.ts b/packages/prop-house-sdk/src/gql/types.ts index 64f9532a8..2177c8f9a 100644 --- a/packages/prop-house-sdk/src/gql/types.ts +++ b/packages/prop-house-sdk/src/gql/types.ts @@ -50,6 +50,13 @@ export interface BalanceOfERC1155Strategy { multiplier?: number; } +export interface CheckpointableERC721Strategy { + id: string; + strategyType: GovPowerStrategyType.CHECKPOINTABLE_ERC721; + tokenAddress: string; + multiplier?: number; +} + export interface AllowlistStrategy { id: string; strategyType: GovPowerStrategyType.ALLOWLIST; @@ -65,7 +72,7 @@ export interface UnknownStrategy extends GovPowerStrategyWithID { strategyType: GovPowerStrategyType.UNKNOWN; } -export type ParsedGovPowerStrategy = BalanceOfStrategy | BalanceOfERC20Strategy | BalanceOfERC1155Strategy | AllowlistStrategy | VanillaStrategy | UnknownStrategy; +export type ParsedGovPowerStrategy = BalanceOfStrategy | BalanceOfERC20Strategy | BalanceOfERC1155Strategy | CheckpointableERC721Strategy | AllowlistStrategy | VanillaStrategy | UnknownStrategy; export type ProposingStrategy = ParsedGovPowerStrategy; export type VotingStrategy = ParsedGovPowerStrategy; diff --git a/packages/prop-house-sdk/src/types.ts b/packages/prop-house-sdk/src/types.ts index 4e265612b..7a863e627 100644 --- a/packages/prop-house-sdk/src/types.ts +++ b/packages/prop-house-sdk/src/types.ts @@ -452,6 +452,7 @@ export enum GovPowerStrategyType { BALANCE_OF_ERC1155 = 'BALANCE_OF_ERC1155', BALANCE_OF_ERC20 = 'BALANCE_OF_ERC20', BALANCE_OF = 'BALANCE_OF', + CHECKPOINTABLE_ERC721 = 'CHECKPOINTABLE_ERC721', ALLOWLIST = 'ALLOWLIST', VANILLA = 'VANILLA', UNKNOWN = 'UNKNOWN', @@ -486,6 +487,13 @@ export interface BalanceOfERC1155Config { multiplier?: number; } +export interface CheckpointableERC721Config { + strategyType: GovPowerStrategyType.CHECKPOINTABLE_ERC721; + assetType: AssetType.ERC721; + address: string; + multiplier?: number; +} + export interface AllowlistMember { address: string; govPower: string; @@ -504,7 +512,7 @@ export interface Custom { strategyType: string; } -export type DefaultGovPowerConfigs = BalanceOfConfig | BalanceOfERC20Config | BalanceOfERC1155Config | AllowlistConfig | VanillaConfig; +export type DefaultGovPowerConfigs = BalanceOfConfig | BalanceOfERC20Config | BalanceOfERC1155Config | CheckpointableERC721Config | AllowlistConfig | VanillaConfig; // prettier-ignore export type GovPowerStrategyConfig = C extends void ? DefaultGovPowerConfigs : DefaultGovPowerConfigs | C; diff --git a/packages/prop-house-subgraph/schema.graphql b/packages/prop-house-subgraph/schema.graphql index a0d466c25..6caca2889 100644 --- a/packages/prop-house-subgraph/schema.graphql +++ b/packages/prop-house-subgraph/schema.graphql @@ -11,6 +11,7 @@ enum GovPowerStrategyType { BALANCE_OF BALANCE_OF_ERC20 BALANCE_OF_ERC1155 + CHECKPOINTABLE_ERC721 UNKNOWN } diff --git a/packages/prop-house-subgraph/src/lib/constants.ts b/packages/prop-house-subgraph/src/lib/constants.ts index 9a6f083fb..df92efb23 100644 --- a/packages/prop-house-subgraph/src/lib/constants.ts +++ b/packages/prop-house-subgraph/src/lib/constants.ts @@ -25,6 +25,7 @@ export namespace GovPowerStrategyType { export const BALANCE_OF = 'BALANCE_OF'; export const BALANCE_OF_ERC20 = 'BALANCE_OF_ERC20'; export const BALANCE_OF_ERC1155 = 'BALANCE_OF_ERC1155'; + export const CHECKPOINTABLE_ERC721 = 'CHECKPOINTABLE_ERC721'; export const UNKNOWN = 'UNKNOWN'; } diff --git a/packages/prop-house-subgraph/src/lib/utils.ts b/packages/prop-house-subgraph/src/lib/utils.ts index c1ff5979f..06714588e 100644 --- a/packages/prop-house-subgraph/src/lib/utils.ts +++ b/packages/prop-house-subgraph/src/lib/utils.ts @@ -102,6 +102,9 @@ export function getGovPowerStrategyType(addr: string): string { if (addr == '0x6d22f17522d6992eb479deb850e96f9454fc2f6c127993ab2ef9d411f467e8') { return GovPowerStrategyType.BALANCE_OF_ERC1155; } + if (addr == '0x10f7529ec5df9069a06191deb7cd2c4158c2b59879e2544cb45dc221daff429') { + return GovPowerStrategyType.CHECKPOINTABLE_ERC721; + } if (addr == '0x3daa40ef909961a576f9ba58eb063d5ebc85411063a8b29435f05af6167079c') { return GovPowerStrategyType.ALLOWLIST; } From 44fe7fe338c29bf96d61be3f9b3470d43419a77a Mon Sep 17 00:00:00 2001 From: solimander Date: Sun, 14 Jan 2024 23:44:14 -0700 Subject: [PATCH 2/4] Add missing semicolon --- .../contracts/starknet/src/common/power.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo b/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo index c420d9916..53cc1093d 100644 --- a/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo +++ b/packages/prop-house-protocol/contracts/starknet/src/common/power.cairo @@ -2,5 +2,5 @@ mod allowlist; mod ethereum_balance_of_erc20; mod ethereum_balance_of_erc1155; mod ethereum_balance_of; -mod ethereum_checkpointable_erc721 +mod ethereum_checkpointable_erc721; mod vanilla; From e3e7d092ca7bf767fb3356ad4c1f5a01199409d1 Mon Sep 17 00:00:00 2001 From: solimander Date: Sun, 14 Jan 2024 23:48:31 -0700 Subject: [PATCH 3/4] Bump package versions --- packages/prop-house-protocol/package.json | 2 +- packages/prop-house-sdk-react/package.json | 4 +-- packages/prop-house-sdk/package.json | 4 +-- yarn.lock | 38 ++++++++++++++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/prop-house-protocol/package.json b/packages/prop-house-protocol/package.json index 2d5d3e470..9f695f457 100644 --- a/packages/prop-house-protocol/package.json +++ b/packages/prop-house-protocol/package.json @@ -1,6 +1,6 @@ { "name": "@prophouse/protocol", - "version": "1.0.7", + "version": "1.0.8", "license": "GPL-3.0", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", diff --git a/packages/prop-house-sdk-react/package.json b/packages/prop-house-sdk-react/package.json index 402d4f41f..bbb280842 100644 --- a/packages/prop-house-sdk-react/package.json +++ b/packages/prop-house-sdk-react/package.json @@ -1,6 +1,6 @@ { "name": "@prophouse/sdk-react", - "version": "1.0.16", + "version": "1.0.17", "description": "Useful tools for interacting with the Prop House protocol from React applications", "author": "solimander", "homepage": "https://prop.house", @@ -18,7 +18,7 @@ "wagmi": ">=0.9.2" }, "dependencies": { - "@prophouse/sdk": "1.0.21" + "@prophouse/sdk": "1.0.22" }, "devDependencies": { "react": "^17.0.2", diff --git a/packages/prop-house-sdk/package.json b/packages/prop-house-sdk/package.json index 6715705ca..6242c180d 100644 --- a/packages/prop-house-sdk/package.json +++ b/packages/prop-house-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@prophouse/sdk", - "version": "1.0.22", + "version": "1.0.23", "description": "Useful tools for interacting with the Prop House protocol", "author": "solimander", "homepage": "https://prop.house", @@ -32,7 +32,7 @@ "@ethersproject/strings": "~5.7.0", "@ethersproject/wallet": "^5.7.0", "@pinata/sdk": "^2.1.0", - "@prophouse/protocol": "1.0.6", + "@prophouse/protocol": "1.0.7", "bn.js": "^5.2.1", "ethereumjs-fork-block": "^4.2.4", "ethereumjs-fork-common": "^3.1.3", diff --git a/yarn.lock b/yarn.lock index e0e724e92..f9b965014 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5978,6 +5978,13 @@ dependencies: ethers "~5.7.2" +"@prophouse/protocol@1.0.7": + version "1.0.7" + resolved "https://registry.npmjs.org/@prophouse/protocol/-/protocol-1.0.7.tgz#27001fa8b29c469fe26d343f84a99c09c406da15" + integrity sha512-lkMwsYzM6AYxUXSdRmuw6YSmsDxurasi1rg20wvPZmtuMb5jDe5Zei8SMTEJpPW+sPwqecnb6t7/bMUkOttWVw== + dependencies: + ethers "~5.7.2" + "@prophouse/sdk-react@1.0.15": version "1.0.15" resolved "https://registry.npmjs.org/@prophouse/sdk-react/-/sdk-react-1.0.15.tgz#a9df1ee3363d0c7f0fe9bcba04a2103f090acf7d" @@ -6016,6 +6023,37 @@ starknet "5.19.5" time-ts "^0.1.0" +"@prophouse/sdk@1.0.22": + version "1.0.22" + resolved "https://registry.npmjs.org/@prophouse/sdk/-/sdk-1.0.22.tgz#276f502f8cb1e9303796072bfba09ba7edf7769c" + integrity sha512-Pq0f+kn6hQfa+Mb2YotFxVern/Dqi+Co5xkomVR1P/tfvUY5Pa2TKmCsQT1AdRBhL8H6KH1vvnq85n3a3iQTgw== + dependencies: + "@ethersproject/abi" "~5.7.0" + "@ethersproject/abstract-provider" "~5.7.0" + "@ethersproject/abstract-signer" "~5.7.0" + "@ethersproject/address" "~5.7.0" + "@ethersproject/bignumber" "~5.7.0" + "@ethersproject/bytes" "~5.7.0" + "@ethersproject/constants" "~5.7.0" + "@ethersproject/contracts" "~5.7.0" + "@ethersproject/keccak256" "~5.7.0" + "@ethersproject/providers" "~5.7.0" + "@ethersproject/solidity" "~5.7.0" + "@ethersproject/strings" "~5.7.0" + "@ethersproject/wallet" "^5.7.0" + "@pinata/sdk" "^2.1.0" + "@prophouse/protocol" "1.0.7" + bn.js "^5.2.1" + ethereumjs-fork-block "^4.2.4" + ethereumjs-fork-common "^3.1.3" + graphql "^16.5.0" + graphql-request "5.0.0" + merkletreejs "^0.3.11" + micro-starknet "^0.2.3" + randombytes "^2.1.0" + starknet "5.19.5" + time-ts "^0.1.0" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" From a8e4bdcfa284fe41a0f2a4989b723678fedcb175 Mon Sep 17 00:00:00 2001 From: solimander Date: Mon, 15 Jan 2024 13:03:41 -0700 Subject: [PATCH 4/4] ERC1155 bug fix, full ERC721 checkpointable support --- .../power/ethereum_balance_of_erc1155.cairo | 2 +- .../deployments/mainnet.json | 2 +- packages/prop-house-protocol/package.json | 2 +- packages/prop-house-sdk-react/package.json | 4 +- packages/prop-house-sdk/package.json | 4 +- packages/prop-house-sdk/src/constants.ts | 6 ++ .../gov-power/handlers/balance-of-erc1155.ts | 4 +- .../handlers/checkpointable-erc721.ts | 13 ++-- packages/prop-house-subgraph/src/lib/utils.ts | 2 +- packages/prop-house-webapp/package.json | 2 +- .../HouseManager/AddVoter/index.tsx | 4 +- .../ProposingStrategiesDisplay/index.tsx | 11 ++++ .../VotingStrategiesDisplay/index.tsx | 11 ++++ .../src/hooks/useTokenNames.ts | 3 +- .../src/utils/createVoterStrategy.ts | 14 ++++- yarn.lock | 59 +++++-------------- 16 files changed, 79 insertions(+), 64 deletions(-) diff --git a/packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_balance_of_erc1155.cairo b/packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_balance_of_erc1155.cairo index 4116f186e..739b3d1b0 100644 --- a/packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_balance_of_erc1155.cairo +++ b/packages/prop-house-protocol/contracts/starknet/src/common/power/ethereum_balance_of_erc1155.cairo @@ -36,7 +36,7 @@ mod EthereumBalanceOfERC1155GovernancePowerStrategy { let slot_index = *params.at(1); let token_id = *params.at(2); - let mut mapping_keys = array![user.into(), token_id.into()]; + let mut mapping_keys = array![token_id.into(), user.into()]; let valid_slot = get_nested_slot_key(slot_index.into(), mapping_keys.span()); let governance_power = SingleSlotProof::get_slot_value( diff --git a/packages/prop-house-protocol/deployments/mainnet.json b/packages/prop-house-protocol/deployments/mainnet.json index 5c8823914..85ad2e970 100644 --- a/packages/prop-house-protocol/deployments/mainnet.json +++ b/packages/prop-house-protocol/deployments/mainnet.json @@ -26,7 +26,7 @@ "allowlistGovPowerStrategy": "0x3daa40ef909961a576f9ba58eb063d5ebc85411063a8b29435f05af6167079c", "ethBalanceOfGovPowerStrategy": "0x6ddcc94a4225843546a9b118a2733fd924d6b8a6467279cbe6a1aea79daca54", "ethBalanceOfErc20GovPowerStrategy": "0x196cf5ceba8e98abe1e633d6184cd28c1e1ebd09ea71f89867dd4c5fda97bbe", - "ethBalanceOfErc1155GovPowerStrategy": "0x6d22f17522d6992eb479deb850e96f9454fc2f6c127993ab2ef9d411f467e8", + "ethBalanceOfErc1155GovPowerStrategy": "0x44e3bdffcb6ce36596d0faa4316932c5dc47005b9eaaf0f7ce0f455c98b2e75", "ethCheckpointableErc721GovPowerStrategy": "0x10f7529ec5df9069a06191deb7cd2c4158c2b59879e2544cb45dc221daff429", "herodotus": { "factRegistry": "0x002081b2d3de51f295e7516257f68bd9f06acbc7f19ba49410c100afbe57540f", diff --git a/packages/prop-house-protocol/package.json b/packages/prop-house-protocol/package.json index 9f695f457..9bd437da1 100644 --- a/packages/prop-house-protocol/package.json +++ b/packages/prop-house-protocol/package.json @@ -1,6 +1,6 @@ { "name": "@prophouse/protocol", - "version": "1.0.8", + "version": "1.0.9", "license": "GPL-3.0", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", diff --git a/packages/prop-house-sdk-react/package.json b/packages/prop-house-sdk-react/package.json index bbb280842..e9c965cc0 100644 --- a/packages/prop-house-sdk-react/package.json +++ b/packages/prop-house-sdk-react/package.json @@ -1,6 +1,6 @@ { "name": "@prophouse/sdk-react", - "version": "1.0.17", + "version": "1.0.18", "description": "Useful tools for interacting with the Prop House protocol from React applications", "author": "solimander", "homepage": "https://prop.house", @@ -18,7 +18,7 @@ "wagmi": ">=0.9.2" }, "dependencies": { - "@prophouse/sdk": "1.0.22" + "@prophouse/sdk": "1.0.23" }, "devDependencies": { "react": "^17.0.2", diff --git a/packages/prop-house-sdk/package.json b/packages/prop-house-sdk/package.json index 6242c180d..cead132f8 100644 --- a/packages/prop-house-sdk/package.json +++ b/packages/prop-house-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@prophouse/sdk", - "version": "1.0.23", + "version": "1.0.24", "description": "Useful tools for interacting with the Prop House protocol", "author": "solimander", "homepage": "https://prop.house", @@ -32,7 +32,7 @@ "@ethersproject/strings": "~5.7.0", "@ethersproject/wallet": "^5.7.0", "@pinata/sdk": "^2.1.0", - "@prophouse/protocol": "1.0.7", + "@prophouse/protocol": "1.0.8", "bn.js": "^5.2.1", "ethereumjs-fork-block": "^4.2.4", "ethereumjs-fork-common": "^3.1.3", diff --git a/packages/prop-house-sdk/src/constants.ts b/packages/prop-house-sdk/src/constants.ts index cf5fc6455..06b4ae660 100644 --- a/packages/prop-house-sdk/src/constants.ts +++ b/packages/prop-house-sdk/src/constants.ts @@ -23,6 +23,12 @@ export const BALANCE_OF_ERC1155_FUNC = 'function balanceOf(address account, uint // prettier-ignore export const GET_CURRENT_VOTES_FUNC = 'function getCurrentVotes(address account) external view returns (uint96)'; +/** + * The `numCheckpoints` function signature. + */ +// prettier-ignore +export const NUM_CHECKPOINTS_FUNC = 'function numCheckpoints(address account) external view returns (uint32)'; + /** * The address used to query `balanceOf` functions to detect the slot index. */ diff --git a/packages/prop-house-sdk/src/gov-power/handlers/balance-of-erc1155.ts b/packages/prop-house-sdk/src/gov-power/handlers/balance-of-erc1155.ts index 4d265ddd0..492673062 100644 --- a/packages/prop-house-sdk/src/gov-power/handlers/balance-of-erc1155.ts +++ b/packages/prop-house-sdk/src/gov-power/handlers/balance-of-erc1155.ts @@ -75,7 +75,7 @@ export class BalanceOfERC1155Handler extends SingleSlotProofHandler { @@ -68,10 +68,15 @@ export class CheckpointableERC721Handler extends SingleSlotProofHandler ); + if (stratType === GovPowerStrategyType.CHECKPOINTABLE_ERC721) + copy = ( + <> + Owners or delegates of the{' '} + + {display(strat.tokenAddress)} + {' '} + token can propose. {propThreshold > 1 && `${propThreshold} tokens required`} + + ); + if (stratType === GovPowerStrategyType.UNKNOWN) copy = <>Error reading proposing strategy; return formattedContent(copy); diff --git a/packages/prop-house-webapp/src/components/VotingStrategiesDisplay/index.tsx b/packages/prop-house-webapp/src/components/VotingStrategiesDisplay/index.tsx index 5cbeb128a..f44207bd9 100644 --- a/packages/prop-house-webapp/src/components/VotingStrategiesDisplay/index.tsx +++ b/packages/prop-house-webapp/src/components/VotingStrategiesDisplay/index.tsx @@ -81,6 +81,17 @@ const VotingStrategiesDisplay: React.FC<{ ); + if (stratType === GovPowerStrategyType.CHECKPOINTABLE_ERC721) + copy = ( + <> + Owners or delegates of the{' '} + + {display(strat.tokenAddress)} + {' '} + token can vote. {strat.multiplier ? strat.multiplier : 1} vote per token. + + ); + if (stratType === GovPowerStrategyType.UNKNOWN) copy = <>Error reading voting strategy; return formattedContent(copy); diff --git a/packages/prop-house-webapp/src/hooks/useTokenNames.ts b/packages/prop-house-webapp/src/hooks/useTokenNames.ts index e74be1bd7..1e1cf000c 100644 --- a/packages/prop-house-webapp/src/hooks/useTokenNames.ts +++ b/packages/prop-house-webapp/src/hooks/useTokenNames.ts @@ -27,7 +27,8 @@ const useTokenNames = (strategies: ParsedGovPowerStrategy[]): UseTokenNamesResul const contracts = strategies .map(strategy => { const isErc20OrErc721 = strategy.strategyType === GovPowerStrategyType.BALANCE_OF || - strategy.strategyType === GovPowerStrategyType.BALANCE_OF_ERC20; + strategy.strategyType === GovPowerStrategyType.BALANCE_OF_ERC20 || + strategy.strategyType === GovPowerStrategyType.CHECKPOINTABLE_ERC721; if (isErc20OrErc721) return { diff --git a/packages/prop-house-webapp/src/utils/createVoterStrategy.ts b/packages/prop-house-webapp/src/utils/createVoterStrategy.ts index ec76a03b1..8224719f7 100644 --- a/packages/prop-house-webapp/src/utils/createVoterStrategy.ts +++ b/packages/prop-house-webapp/src/utils/createVoterStrategy.ts @@ -6,10 +6,22 @@ import { } from '@prophouse/sdk-react'; import { NewVoter } from '../components/HouseManager/VotersConfig'; +/** + * Known ERC721 checkpointable tokens. + */ +const ERC721_CHECKPOINTABLE_TOKENS = ['0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03' /* Nouns */]; + const createVoterStrategy = (voter: NewVoter): GovPowerStrategyConfig | null => { let s: GovPowerStrategyConfig | null = null; - if (voter.type === VotingStrategyType.BALANCE_OF_ERC1155) { + if (voter.type === VotingStrategyType.CHECKPOINTABLE_ERC721 || ERC721_CHECKPOINTABLE_TOKENS.includes(voter.address?.toLowerCase())) { + s = { + strategyType: VotingStrategyType.CHECKPOINTABLE_ERC721, + assetType: AssetType.ERC721, + address: voter.address, + multiplier: voter.multiplier, + }; + } else if (voter.type === VotingStrategyType.BALANCE_OF_ERC1155) { s = { strategyType: voter.type, assetType: AssetType.ERC1155, diff --git a/yarn.lock b/yarn.lock index f9b965014..b21797f1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5978,55 +5978,24 @@ dependencies: ethers "~5.7.2" -"@prophouse/protocol@1.0.7": - version "1.0.7" - resolved "https://registry.npmjs.org/@prophouse/protocol/-/protocol-1.0.7.tgz#27001fa8b29c469fe26d343f84a99c09c406da15" - integrity sha512-lkMwsYzM6AYxUXSdRmuw6YSmsDxurasi1rg20wvPZmtuMb5jDe5Zei8SMTEJpPW+sPwqecnb6t7/bMUkOttWVw== +"@prophouse/protocol@1.0.8": + version "1.0.8" + resolved "https://registry.npmjs.org/@prophouse/protocol/-/protocol-1.0.8.tgz#745869a4932df727221514ece06563ed7a93a011" + integrity sha512-XSYA5iqrbD2pyZFD3bSoJKFOeQs/9LgElddZ1cOj6UzQhe2xA0e5ZW5aTwGqEW4eIq8Ed6Am8ruNF8SwyAcphA== dependencies: ethers "~5.7.2" -"@prophouse/sdk-react@1.0.15": - version "1.0.15" - resolved "https://registry.npmjs.org/@prophouse/sdk-react/-/sdk-react-1.0.15.tgz#a9df1ee3363d0c7f0fe9bcba04a2103f090acf7d" - integrity sha512-CJakH5gWbyi3GVw2sZ29BnHqmow36/urenjKmrwXohTML0EAtYDy8No+fClMRL32UHWvDxMMYBqNR1yU3gEYXg== - dependencies: - "@prophouse/sdk" "1.0.21" - -"@prophouse/sdk@1.0.21": - version "1.0.21" - resolved "https://registry.npmjs.org/@prophouse/sdk/-/sdk-1.0.21.tgz#c83c532d77d2a696c5795be3ff8880bbb53a4c82" - integrity sha512-ADUwQir+5QezJ/rTTcwTXCy8Ge3SAalV9dAsFOrGhenuW6E7ROUTx4PvC8BXsXdPiY5LgOivLPBYr29KbRQmdw== +"@prophouse/sdk-react@1.0.17": + version "1.0.17" + resolved "https://registry.npmjs.org/@prophouse/sdk-react/-/sdk-react-1.0.17.tgz#5d4b31962156d243197c7144dcf5db5ffee81381" + integrity sha512-96udnh5fIefG7+eYG/n+2WevYYogcQyE4fxYCNxBGy9zyhjUVSuieMWegwzYzRTI8GWPxHCUxFyXpaWXghCaxQ== dependencies: - "@ethersproject/abi" "~5.7.0" - "@ethersproject/abstract-provider" "~5.7.0" - "@ethersproject/abstract-signer" "~5.7.0" - "@ethersproject/address" "~5.7.0" - "@ethersproject/bignumber" "~5.7.0" - "@ethersproject/bytes" "~5.7.0" - "@ethersproject/constants" "~5.7.0" - "@ethersproject/contracts" "~5.7.0" - "@ethersproject/keccak256" "~5.7.0" - "@ethersproject/providers" "~5.7.0" - "@ethersproject/solidity" "~5.7.0" - "@ethersproject/strings" "~5.7.0" - "@ethersproject/wallet" "^5.7.0" - "@pinata/sdk" "^2.1.0" - "@prophouse/protocol" "1.0.6" - bn.js "^5.2.1" - ethereumjs-fork-block "^4.2.4" - ethereumjs-fork-common "^3.1.3" - graphql "^16.5.0" - graphql-request "5.0.0" - merkletreejs "^0.3.11" - micro-starknet "^0.2.3" - randombytes "^2.1.0" - starknet "5.19.5" - time-ts "^0.1.0" + "@prophouse/sdk" "1.0.23" -"@prophouse/sdk@1.0.22": - version "1.0.22" - resolved "https://registry.npmjs.org/@prophouse/sdk/-/sdk-1.0.22.tgz#276f502f8cb1e9303796072bfba09ba7edf7769c" - integrity sha512-Pq0f+kn6hQfa+Mb2YotFxVern/Dqi+Co5xkomVR1P/tfvUY5Pa2TKmCsQT1AdRBhL8H6KH1vvnq85n3a3iQTgw== +"@prophouse/sdk@1.0.23": + version "1.0.23" + resolved "https://registry.npmjs.org/@prophouse/sdk/-/sdk-1.0.23.tgz#c24716ec419d5ff3acce985c148bfbe6e381c924" + integrity sha512-N/tlB+BHeUmycroErHpu8ZoP+GXFvXgc2Uowbd0HkX+JIqU5GfOP2up4dCJ+3fz6I5rPdqUA5i+G66e2+q73kA== dependencies: "@ethersproject/abi" "~5.7.0" "@ethersproject/abstract-provider" "~5.7.0" @@ -6042,7 +6011,7 @@ "@ethersproject/strings" "~5.7.0" "@ethersproject/wallet" "^5.7.0" "@pinata/sdk" "^2.1.0" - "@prophouse/protocol" "1.0.7" + "@prophouse/protocol" "1.0.8" bn.js "^5.2.1" ethereumjs-fork-block "^4.2.4" ethereumjs-fork-common "^3.1.3"