Skip to content

vesting dao mint#404

Open
andrewnguyen22 wants to merge 5 commits into
mainfrom
review/vesting-dao-mint
Open

vesting dao mint#404
andrewnguyen22 wants to merge 5 commits into
mainfrom
review/vesting-dao-mint

Conversation

@andrewnguyen22
Copy link
Copy Markdown
Collaborator

@andrewnguyen22 andrewnguyen22 commented May 21, 2026

Summary

This PR adds vesting-aware account support and a mint option for DAO transfer proposals.

What Changed

Vesting accounts

  • Added vesting metadata to accounts:
    • vestingAmount
    • vestingStartHeight
    • vestingCliffHeight
    • vestingEndHeight
  • Added vesting-aware send support so a transfer can create or extend a recipient vesting schedule.
  • Enforced spendable-balance checks in the FSM so locked vesting funds cannot be spent.
  • Updated RPC/account JSON handling so vesting fields are preserved in responses and serialization.
  • Fixed faucet top-up behavior to use spendable balance rather than raw total balance.

DAO transfer minting

  • Added mint: bool to MessageDAOTransfer.
  • When mint=true, the FSM mints amount into the DAO pool immediately before executing the DAO transfer.
  • This allows validator-approved one-off treasury mint events for grants.

Why

Vesting

The chain needs to distinguish between:

  • total account balance
  • vesting-restricted balance
  • currently spendable balance

This PR keeps total ownership at the storage layer while enforcing spendability dynamically based on vesting schedule and height.

DAO minting

This gives validators a controlled way to approve exceptional treasury grant events that require new issuance, without creating a separate
governance message type.

Testing

Covered with focused tests for:

  • vesting spendable accounting
  • vesting JSON round-trip preservation
  • RPC account responses with spendable amount and vesting metadata
  • DAO transfer behavior
  • DAO mint-then-transfer behavior

@andrewnguyen22 andrewnguyen22 self-assigned this May 21, 2026
@andrewnguyen22 andrewnguyen22 added the FSM Finite State Machine module label May 21, 2026
@andrewnguyen22 andrewnguyen22 changed the title Review/vesting dao mint vesting dao mint May 21, 2026
@rem1niscence
Copy link
Copy Markdown
Collaborator

is it ready? @andrewnguyen22 as some tests are failing on the CI

Comment thread fsm/message.go
Comment thread fsm/account.go Outdated
@andrewnguyen22
Copy link
Copy Markdown
Collaborator Author

Review re-requested @rem1niscence @pablocampogo @ezeike

Copy link
Copy Markdown
Collaborator

@rem1niscence rem1niscence left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everything looks all right in general, just set it as request changes to enforce the response of the comments. Also in general, I'm pretty sure you did but just to double confirm, as there's a possibly high amount of places where account balances are manipulated in general, did you make sure that all these places have the checks for vesting in place? wether to view those accounts or manipulate them in any way

Comment thread cmd/cli/cli.go
)

func init() {
flag.Parse()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to make sure, did you remove this because cobra is being used here? this won't any any other command right?

Comment thread fsm/account.go
Comment on lines +132 to +138
locked := s.AccountLockedAmount(account)
// check for invariant
if locked >= account.Amount {
return 0
}
// return spendable amount
return account.Amount - locked
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
locked := s.AccountLockedAmount(account)
// check for invariant
if locked >= account.Amount {
return 0
}
// return spendable amount
return account.Amount - locked
// return spendable amount
return max(0, account.Amount - s.AccountLockedAmount(account))

minor refactor to simplify the check, other functions like AccountLockedAmount could have something similar but this could be objected in favour of being explicit on what's happening

Comment thread cmd/rpc/query.go
if account == nil {
return nil
}
view := *account
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning on my linter here:

assignment copies lock value to view: github.com/canopy-network/canopy/fsm.Account contains google.golang.org/protobuf/runtime/protoimpl.MessageState contains sync.Mutex (copylocks default)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FSM Finite State Machine module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants