Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #40

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f90a787
Feature/bump deps (#10)
bryzettler Nov 6, 2023
efcf883
add scripts to package.json
bryzettler Nov 6, 2023
a7facc2
chore(release): publish 0.0.6
bryzettler Nov 6, 2023
1c39345
bump deps
bryzettler Nov 7, 2023
5ee87b2
chore(release): publish 0.0.7
bryzettler Nov 7, 2023
896a808
bump deps
bryzettler Nov 10, 2023
1208f11
chore(release): publish 0.0.8
bryzettler Nov 10, 2023
e6cffa4
Merge remote-tracking branch 'origin/main' into develop
ChewingGlass Jan 31, 2024
bdc8e69
Add devnet feature
ChewingGlass Jan 31, 2024
eaa16fb
chore(release): publish 0.0.9
ChewingGlass Mar 13, 2024
af9b632
Merge remote-tracking branch 'origin/main' into develop
ChewingGlass Mar 13, 2024
f96bb03
Merge remote-tracking branch 'origin/main' into develop
ChewingGlass Apr 15, 2024
71326dd
Add recursive delegation for nft-style voting schems (#11)
ChewingGlass Aug 9, 2024
7cf5ec1
conflicts
bryzettler Aug 12, 2024
c369fdb
Chore/publish 0.0.12 (#33)
bryzettler Aug 12, 2024
b6f50ec
Fix mod gov package.json
ChewingGlass Sep 6, 2024
21a23ba
chore(release): publish 0.0.13
ChewingGlass Sep 6, 2024
678073c
Bump version
ChewingGlass Sep 6, 2024
af34eb9
Merge branch 'main' into develop
ChewingGlass Oct 21, 2024
c7bcf86
[HIP-124]: Implement abstain vote (#37)
ChewingGlass Oct 23, 2024
46b2a82
chore(release): publish 0.0.14
ChewingGlass Oct 24, 2024
a5a886b
Bump version
ChewingGlass Oct 24, 2024
ab7c272
bump squads
ChewingGlass Oct 24, 2024
3d4e674
get another release for state controller
ChewingGlass Oct 24, 2024
6065c0f
Add fallbacks for smart contracts used by HPL (#38)
ChewingGlass Dec 6, 2024
9e64627
chore(release): publish 0.0.15
ChewingGlass Dec 6, 2024
ebf582e
Fix bugs in nft and token voter (#39)
ChewingGlass Dec 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge remote-tracking branch 'origin/main' into develop
  • Loading branch information
ChewingGlass committed Jan 31, 2024
commit e6cffa45fd41d17f3b527bed23d7988e7474e416
27 changes: 3 additions & 24 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: Tests
on:
push:
branches:
- master
- main
pull_request:
branches:
- master
- main
- develop
env:
SOLANA_CLI_VERSION: 1.16.13
Expand Down Expand Up @@ -59,27 +59,6 @@ jobs:
with:
testing: true

test-devflow:
needs: build
name: Test Development Workflow
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/actions/build-anchor/
with:
testing: true
- uses: ./.github/actions/setup-ts/
- name: Start Anchor Localnet
run: ~/.cargo/bin/anchor localnet --skip-build --provider.wallet ~/.config/solana/id.json & sleep 2
- name: Wait for localnet to start
run: |
while [[ "$(curl -s http://localhost:8899/health)" != "ok" ]]; do
echo "Waiting for local Anchor network to start..."
sleep 5
done
- name: Run bootstrap script
run: ./scripts/bootstrap.sh

test-contracts:
needs: build
name: Test Anchor Contracts
Expand Down Expand Up @@ -112,4 +91,4 @@ jobs:
env:
TESTING: true
TEST: ${{ matrix.test }}
ANCHOR_PROVIDER_URL: http://localhost:8899
ANCHOR_PROVIDER_URL: http://127.0.0.1:8899
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

This file was deleted.

2 changes: 2 additions & 0 deletions programs/proposal/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ use anchor_lang::prelude::*;
pub enum ErrorCode {
#[msg("Error in arithmetic")]
ArithmeticError,
#[msg("String exceeds limits")]
StringTooLong,
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ pub struct InitializeProposalConfigArgsV0 {
pub struct InitializeProposalConfigV0<'info> {
#[account(mut)]
pub payer: Signer<'info>,
/// Every proposal config must have an owner to prevent seed collision
pub owner: Signer<'info>,
#[account(
init,
payer = payer,
seeds = [b"proposal_config", args.name.as_bytes()],
space = 8 + 60 + args.name.len() + ProposalConfigV0::INIT_SPACE,
space = 8 + 60 + ProposalConfigV0::INIT_SPACE,
bump
)]
pub proposal_config: Box<Account<'info, ProposalConfigV0>>,
Expand Down
25 changes: 24 additions & 1 deletion programs/proposal/src/instructions/initialize_proposal_v0.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::errors::ErrorCode;
use crate::state::*;
use anchor_lang::prelude::*;

Expand Down Expand Up @@ -44,7 +45,16 @@ pub struct InitializeProposalV0<'info> {
init,
payer = payer,
seeds = [b"proposal", namespace.key().as_ref(), &args.seed[..]],
space = 8 + 60 + args.seed.len() + ProposalV0::INIT_SPACE + args.choices.len() * Choice::INIT_SPACE,
space = 8 + 60 +
args.seed.len() + // Seed length
std::mem::size_of::<ProposalV0>() +
args.name.len() + // Name
args.uri.len() + // Url
8 + (2 * args.choices.len()) + // Max space for ProposalState when Resolved
args.choices.iter().map(|choice| {
std::mem::size_of::<Choice>() + choice.name.len() + choice.uri.as_ref().map_or(0, |uri| uri.len())
}).sum::<usize>() +// Space for each choice,
4 + args.tags.iter().map(|tag| tag.len()).sum::<usize>(), // tags,
bump
)]
pub proposal: Box<Account<'info, ProposalV0>>,
Expand All @@ -55,6 +65,19 @@ pub struct InitializeProposalV0<'info> {
}

pub fn handler(ctx: Context<InitializeProposalV0>, args: InitializeProposalArgsV0) -> Result<()> {
require_gt!(args.choices.len(), 0);
require_gt!(200, args.name.len(), ErrorCode::StringTooLong);
require_gt!(200, args.uri.len(), ErrorCode::StringTooLong);
for tag in args.tags.iter() {
require_gt!(200, tag.len(), ErrorCode::StringTooLong);
}
for choice in args.choices.iter() {
require_gt!(200, choice.name.len(), ErrorCode::StringTooLong);
if let Some(uri) = &choice.uri {
require_gt!(200, uri.len(), ErrorCode::StringTooLong);
}
}

ctx.accounts.proposal.set_inner(ProposalV0 {
namespace: ctx.accounts.namespace.key(),
owner: ctx.accounts.owner.key(),
Expand Down
3 changes: 2 additions & 1 deletion programs/proposal/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ pub struct ProposalConfigV0 {
/// the vote eagerly. For most use cases, this should just be the owner of the state controller.
/// WARNING: This program has full authority to set the outcome of votes, make sure you trust it
pub on_vote_hook: Pubkey,
#[max_len(200)]
// Limited to 32 because it's used as a seed
#[max_len(32)]
pub name: String,
pub bump_seed: u8,
}
Expand Down
3 changes: 2 additions & 1 deletion programs/state_controller/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "state-controller"
version = "0.1.0"
version = "0.1.1"
description = "Created with Anchor"
edition = "2021"

Expand All @@ -19,3 +19,4 @@ default = []
anchor-lang = { git = "https://github.com/ChewingGlass/anchor", branch = "bugfix/cpi-polymorphism" }
anchor-spl = { git = "https://github.com/ChewingGlass/anchor", branch = "bugfix/cpi-polymorphism" }
proposal = { path = "../proposal", features = ["no-entrypoint", "cpi"] }

10 changes: 10 additions & 0 deletions programs/state_controller/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,14 @@ use anchor_lang::prelude::*;
pub enum ErrorCode {
#[msg("Proposal was already resolved. Call resolve_v0")]
ProposalAlreadyResolved,
#[msg("Resolved choices must not be empty")]
ChoicesEmpty,
#[msg("End timestamp has already passed")]
EndTimestampPassed,
#[msg("Offset must be a positive integer")]
InvalidOffset,
#[msg("Percentage may not be less than 0 or greater than PERCENTAGE_DIVISOR")]
InvalidPercentage,
#[msg("Top n must be greater than 0")]
InvalidTopN,
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct InitializeResolutionSettingsV0<'info> {
#[account(
init,
payer = payer,
space = 8 + 60 + std::mem::size_of::<ResolutionSettingsV0>() + args.settings.nodes.iter().map(|node| node.size()).sum::<usize>(),
space = 8 + 60 + std::mem::size_of::<ResolutionSettingsV0>() + args.name.len() + args.settings.nodes.iter().map(|node| node.size()).sum::<usize>(),
seeds = [b"resolution_settings", args.name.as_bytes()],
bump
)]
Expand All @@ -28,6 +28,7 @@ pub fn handler(
ctx: Context<InitializeResolutionSettingsV0>,
args: InitializeResolutionSettingsArgsV0,
) -> Result<()> {
args.settings.validate()?;
ctx
.accounts
.resolution_settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,20 @@ pub struct UpdateStateArgsV0 {

/// Allow the owner to update ths state of the proposal when it is not resolved or voting.
#[derive(Accounts)]
#[instruction(args: UpdateStateArgsV0)]
pub struct UpdateStateV0<'info> {
pub owner: Signer<'info>,
#[account(
mut,
owner = proposal_program.key(),
has_one = owner,
has_one = proposal_config,
constraint = !matches!(proposal.state, CpiProposalState::Voting { .. } | CpiProposalState::Resolved { .. })
constraint = match proposal.state {
// Voting can only go to state cancelled.
CpiProposalState::Voting { .. } => args.new_state == ProposalState::Cancelled,
CpiProposalState::Resolved { .. } => false,
_ => true
}
)]
pub proposal: Account<'info, ProposalV0>,
#[account(
Expand Down
45 changes: 40 additions & 5 deletions programs/state_controller/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use std::collections::HashSet;
use anchor_lang::prelude::*;
use proposal::{ProposalState, ProposalV0};

pub const PERCENTAGE_DIVISOR: u32 = 1000000000;
use crate::error::ErrorCode;

pub const PERCENTAGE_DIVISOR: i32 = 1000000000;

/// Allow building complex operations to decide resolution.
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
Expand All @@ -12,8 +14,8 @@ pub enum ResolutionNode {
Resolved {
choices: Vec<u16>,
},
/// Simple: At the specified end timestamp, the proposal is resolved with the choice
/// that has the most vote weight
/// Simple: At the specified end timestamp, the proposal is resolved with all choices. Combine with Top
/// to select the highest weight choice at the end of the proposal.
EndTimestamp {
end_ts: i64,
},
Expand Down Expand Up @@ -48,6 +50,8 @@ impl Default for ResolutionNode {
}
}

pub const TESTING: bool = std::option_env!("TESTING").is_some();

impl ResolutionNode {
pub fn size(&self) -> usize {
match self {
Expand All @@ -56,12 +60,35 @@ impl ResolutionNode {
ResolutionNode::OffsetFromStartTs { .. } => 8,
ResolutionNode::ChoiceVoteWeight { .. } => 16,
ResolutionNode::ChoicePercentage { .. } => 4,
ResolutionNode::Top { .. } => 4,
ResolutionNode::Top { .. } => 2,
ResolutionNode::And => 0,
ResolutionNode::Or => 0,
ResolutionNode::NumResolved { .. } => 4,
}
}

pub fn validate(&self) -> Result<()> {
match self {
ResolutionNode::Resolved { choices } if choices.is_empty() => {
Err(error!(ErrorCode::ChoicesEmpty))
}
ResolutionNode::EndTimestamp { end_ts }
if *end_ts < Clock::get()?.unix_timestamp && !TESTING =>
{
Err(error!(ErrorCode::EndTimestampPassed))
}
ResolutionNode::OffsetFromStartTs { offset } if *offset <= 0 => {
Err(error!(ErrorCode::InvalidOffset))
}
ResolutionNode::ChoicePercentage { percentage }
if *percentage < 0 || *percentage > PERCENTAGE_DIVISOR =>
{
Err(error!(ErrorCode::InvalidPercentage))
}
ResolutionNode::Top { n } if *n == 0 => Err(error!(ErrorCode::InvalidTopN)),
_ => Ok(()),
}
}
}

/// Reverse polish notation calculator
Expand Down Expand Up @@ -90,6 +117,14 @@ pub fn union<T: std::cmp::Eq + std::hash::Hash + Clone>(a: Vec<T>, b: Vec<T>) ->
}

impl ResolutionStrategy {
pub fn validate(&self) -> Result<()> {
for node in self.nodes.iter() {
node.validate()?
}

Ok(())
}

pub fn resolution(&self, proposal: &ProposalV0) -> Option<Vec<u16>> {
let mut stack: Vec<Option<Vec<u16>>> = vec![];
for input in &self.nodes {
Expand Down Expand Up @@ -219,7 +254,7 @@ impl ResolutionStrategy {
stack.push(ret)
}
ResolutionNode::NumResolved { n } => {
let curr = stack.get(0).unwrap();
let curr = stack.first().unwrap();
match curr {
Some(vec) if vec.len() >= *n as usize => stack.push(Some(vec.clone())),
_ => stack.push(None),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub fn handler(
DataV2 {
name: String::from("Token Voter Receipts"),
symbol: String::from("TVR"),
uri: args.collection_uri.clone(),
uri: args.collection_uri,
seller_fee_basis_points: 0,
creators: None,
collection: None,
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.