Skip to content
This repository was archived by the owner on Feb 8, 2026. It is now read-only.

Fees logic separation#145

Closed
garry-sharp wants to merge 1 commit into
mainfrom
fees-v2
Closed

Fees logic separation#145
garry-sharp wants to merge 1 commit into
mainfrom
fees-v2

Conversation

@garry-sharp

@garry-sharp garry-sharp commented Jul 30, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Introduced distinct phases for fee processing: loading, transacting, and post-transaction status checks, each with configurable scheduling and concurrency.
    • Enhanced fee run tracking with new status states and improved transaction handling.
    • Added post-transaction monitoring to automatically update fee statuses after blockchain confirmation.
  • Configuration

    • Updated fee configuration to support Ethereum provider settings, chain ID, and granular job scheduling.
  • Bug Fixes

    • Improved error handling and logging throughout the fee processing lifecycle.
  • Database & Migration

    • Updated schema to use transaction hashes instead of transaction IDs for fee runs.
    • Expanded database support for querying and managing fee runs and associated fees.
  • Refactor

    • Modularized fee processing logic for better maintainability and clarity.
    • Streamlined policy retrieval and transaction proposal processes.

Copilot AI review requested due to automatic review settings July 30, 2025 21:00
@coderabbitai

coderabbitai Bot commented Jul 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

This change refactors the fee collection system by splitting fee handling into three asynchronous job types: loading fees, transacting fees, and post-transaction status checks. It introduces new configuration options, updates database schema and access methods, modularizes plugin logic, and adds helper utilities for Ethereum transactions. The configuration and migration files are updated to match the new workflow.

Changes

Cohort / File(s) Change Summary
Main Fee Worker and Job Scheduling
cmd/fees/worker/main.go
Introduces three helper functions for fee job scheduling, replaces a single handler with three, and sets up separate cron jobs for each fee job type.
Fee Plugin Modularization
plugin/fees/fees.go, plugin/fees/transaction.go, plugin/fees/post_tx.go, plugin/fees/helper.go, plugin/fees/constraints.go
Refactors plugin logic into separate methods for loading fees, handling transactions, and post-transaction checks; adds Ethereum transaction helpers; splits task types; introduces concurrency controls and synchronization.
Fee Plugin Configuration
plugin/fees/config.go, etc/vultisig/fee.yml
Refactors configuration struct and YAML: new fields for Ethereum provider, chain ID, and job scheduling; removes obsolete fields; adds job concurrency and cron expressions.
Database Interface and Implementation
storage/db.go, storage/postgres/fees.go, storage/postgres/policy.go
Expands and updates database interfaces and implementations: new/renamed methods for fee runs and policies, changes from tx_id (UUID) to tx_hash (string), adds fee management methods.
Database Schema and Migration
storage/postgres/migrations/plugin/20250630152230_fee_runs.sql, storage/postgres/schema/schema.sql
Alters schema: replaces tx_id (UUID, FK) with tx_hash (string), updates views, removes related foreign key constraint.
Fee Types and State
internal/types/fees.go
Extends fee run states, changes FeeRun struct to use TxHash instead of TxID, and adds a Fees field.
Verifier API Enhancements
internal/verifierapi/fees.go, internal/verifierapi/verifierapi.go
Adds method for marking fees as collected and a generic authenticated POST helper.
Policy Service
service/policy.go
Updates to use the new GetPluginPolicies method for retrieving plugin policies.

Sequence Diagram(s)

sequenceDiagram
    participant Cron as Cron Scheduler
    participant Worker as Fee Worker
    participant Plugin as FeePlugin
    participant DB as Database
    participant Eth as Ethereum Node
    participant Verifier as Verifier API

    %% Loading Fees
    Cron->>Worker: Trigger Load Fees Job
    Worker->>Plugin: LoadFees()
    Plugin->>DB: Fetch Fee Policies
    Plugin->>Verifier: Get Pending Fees
    Plugin->>DB: Create/Update FeeRuns

    %% Transacting Fees
    Cron->>Worker: Trigger Transact Fees Job
    Worker->>Plugin: HandleTransactions()
    Plugin->>DB: Fetch Draft FeeRuns
    Plugin->>Eth: Propose & Sign Transactions
    Plugin->>DB: Update FeeRun with TxHash

    %% Post-Transaction Checks
    Cron->>Worker: Trigger Post-Tx Job
    Worker->>Plugin: HandlePostTx()
    Plugin->>DB: Fetch Sent FeeRuns
    Plugin->>Eth: Get Tx Receipt
    Plugin->>Verifier: Mark Fee as Collected
    Plugin->>DB: Update FeeRun Status
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • johnnyluo

Poem

Three jobs now hop where once was one,
Fees load, transact, and check when done.
Ethereum hashes, not UUIDs,
Dance in the schema with nimble ease.
Configs refactored, helpers abound—
The fee bunny’s workflow is newly profound!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2bd2a77 and 49d4ad1.

📒 Files selected for processing (17)
  • cmd/fees/worker/main.go (3 hunks)
  • etc/vultisig/fee.yml (1 hunks)
  • internal/types/fees.go (2 hunks)
  • internal/verifierapi/fees.go (2 hunks)
  • internal/verifierapi/verifierapi.go (2 hunks)
  • plugin/fees/config.go (4 hunks)
  • plugin/fees/constraints.go (1 hunks)
  • plugin/fees/fees.go (8 hunks)
  • plugin/fees/helper.go (1 hunks)
  • plugin/fees/post_tx.go (1 hunks)
  • plugin/fees/transaction.go (6 hunks)
  • service/policy.go (1 hunks)
  • storage/db.go (1 hunks)
  • storage/postgres/fees.go (2 hunks)
  • storage/postgres/migrations/plugin/20250630152230_fee_runs.sql (2 hunks)
  • storage/postgres/policy.go (1 hunks)
  • storage/postgres/schema/schema.sql (2 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fees-v2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the fee collection system to separate the logic into distinct phases: loading fees from the verifier, executing transactions, and post-transaction status checking. The changes implement a more robust fee collection workflow with better error handling and transaction tracking.

  • Splits fee collection into three separate async jobs: loading fees, handling transactions, and post-transaction processing
  • Replaces transaction ID references with transaction hash strings for better blockchain integration
  • Adds new database methods for comprehensive fee run management and status tracking

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
storage/postgres/policy.go Adds method to get all fee policies and renames existing method for clarity
storage/postgres/migrations/plugin/20250630152230_fee_runs.sql Updates database schema to use tx_hash instead of tx_id
storage/postgres/fees.go Expands fee management with new methods for status updates and comprehensive querying
storage/db.go Updates interface to reflect new fee management methods
service/policy.go Updates method call to use renamed policy retrieval function
plugin/fees/transaction.go Refactors transaction handling with better error handling and hash tracking
plugin/fees/post_tx.go New file implementing post-transaction status checking and verification
plugin/fees/helper.go New file with utility functions for transaction decoding and hash generation
plugin/fees/fees.go Major refactor splitting fee collection into separate loading and transaction phases
plugin/fees/constraints.go Updates task type constants for the new three-phase workflow
plugin/fees/config.go Adds Ethereum provider and confirmation configuration options
internal/verifierapi/verifierapi.go Adds POST request support for authenticated API calls
internal/verifierapi/fees.go Implements fee collection marking functionality
internal/types/fees.go Updates fee run structure to use transaction hash and adds new status types
etc/vultisig/fee.yml Adds Ethereum provider configuration
cmd/fees/worker/main.go Implements cron-based scheduling for the three-phase fee collection workflow

Comment thread storage/postgres/policy.go
Comment thread storage/postgres/fees.go
Comment thread plugin/fees/transaction.go Outdated
return fmt.Errorf("failed to decode tx: %w", err)
}

fp.logger.Info("33333")

Copilot AI Jul 30, 2025

Copy link

Choose a reason for hiding this comment

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

This appears to be debug logging that should be removed from production code.

Suggested change
fp.logger.Info("33333")
// Removed unnecessary debug log statement.

Copilot uses AI. Check for mistakes.
Comment thread plugin/fees/post_tx.go Outdated
Comment thread plugin/fees/post_tx.go Outdated
Comment thread plugin/fees/fees.go Outdated
Comment thread plugin/fees/fees.go Outdated
Comment thread internal/verifierapi/verifierapi.go Outdated
Comment thread etc/vultisig/fee.yml
Comment thread plugin/fees/fees.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Nitpick comments (6)
plugin/fees/helper.go (1)

37-41: Remove unused JSON tags

The JSON tags on this internal struct are not used anywhere in the codebase.

 type erc20tx struct {
-	to     ecommon.Address `json:"to"`
-	amount *big.Int        `json:"amount"`
-	token  ecommon.Address `json:"token"`
+	to     ecommon.Address
+	amount *big.Int
+	token  ecommon.Address
 }
plugin/fees/post_tx.go (3)

33-33: Remove misleading TODO comment

The code is already implementing concurrent processing with goroutines and semaphore. The TODO comment is no longer applicable.

-	//TODO go routine this
	sem := semaphore.NewWeighted(10)

61-63: Remove redundant nil check

This check is already performed in HandlePostTx before calling this function.

-	if run.TxHash == nil || run.Status == types.FeeRunStateDraft {
-		return nil
-	}

74-74: Use constant for transaction success status

Replace magic number with a named constant for better readability.

-	if receipt.Status == 1 {
+	if receipt.Status == etypes.ReceiptStatusSuccessful {
plugin/fees/fees.go (1)

249-249: Consider filtering fee runs at the database level

The function retrieves all fee runs but then filters them in the loop. Consider passing the status filter to GetAllFeeRuns for better performance.

-	runs, err := fp.db.GetAllFeeRuns(ctx)
+	runs, err := fp.db.GetAllFeeRuns(ctx, types.FeeRunStateDraft)
storage/postgres/fees.go (1)

176-194: Inconsistent behavior between GetFeeRuns and GetAllFeeRuns

GetFeeRuns doesn't populate the Fees field in the returned FeeRun structs, while GetAllFeeRuns does. This inconsistency could confuse API users.

Consider either:

  1. Documenting this difference clearly
  2. Making both methods consistent by having GetFeeRuns also load fees
  3. Renaming methods to clarify the difference (e.g., GetFeeRunsWithFees vs GetFeeRunsWithoutFees)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d07390 and b88abfe.

📒 Files selected for processing (16)
  • cmd/fees/worker/main.go (3 hunks)
  • etc/vultisig/fee.yml (1 hunks)
  • internal/types/fees.go (2 hunks)
  • internal/verifierapi/fees.go (2 hunks)
  • internal/verifierapi/verifierapi.go (2 hunks)
  • plugin/fees/config.go (4 hunks)
  • plugin/fees/constraints.go (1 hunks)
  • plugin/fees/fees.go (7 hunks)
  • plugin/fees/helper.go (1 hunks)
  • plugin/fees/post_tx.go (1 hunks)
  • plugin/fees/transaction.go (6 hunks)
  • service/policy.go (1 hunks)
  • storage/db.go (1 hunks)
  • storage/postgres/fees.go (2 hunks)
  • storage/postgres/migrations/plugin/20250630152230_fee_runs.sql (2 hunks)
  • storage/postgres/policy.go (1 hunks)
🧰 Additional context used
🧠 Learnings (16)
📓 Common learnings
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: webpiratt
PR: vultisig/plugin#141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local `IsAlreadyProposed` check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.
etc/vultisig/fee.yml (4)

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

internal/verifierapi/verifierapi.go (1)

Learnt from: RaghavSood
PR: #36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path github.com/vultisig/verifier/plugin refers to an external dependency that provides the plugin interface, and should not be changed to github.com/vultisig/plugin/plugin as these are distinct packages with different purposes.

plugin/fees/constraints.go (7)

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

internal/types/fees.go (2)

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

internal/verifierapi/fees.go (2)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

cmd/fees/worker/main.go (2)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

storage/postgres/migrations/plugin/20250630152230_fee_runs.sql (1)

Learnt from: webpiratt
PR: #89
File: storage/postgres/migrations/plugin/20250603181247_tx_indexer.sql:13-13
Timestamp: 2025-06-11T18:42:54.241Z
Learning: In the tx_indexer table (storage/postgres/migrations/plugin/*_tx_indexer.sql), the policy_id column is intentionally not defined with a foreign-key constraint to plugin_policies(id).

plugin/fees/config.go (3)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

plugin/fees/helper.go (7)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.

Learnt from: webpiratt
PR: #125
File: plugin/payroll/transaction.go:186-197
Timestamp: 2025-07-09T22:22:36.651Z
Learning: In plugin/payroll/transaction.go, the getTokenID function is designed to return evm.ZeroAddress.Hex() when no "token" parameter constraint is found, rather than returning an error. This is expected behavior according to the team's design intent, even though the token parameter is marked as required in the recipe specification.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:510-514
Timestamp: 2025-06-18T18:20:59.510Z
Learning: The erc20ABI constant is defined in plugin/payroll/constants.go within the payroll package, making it accessible to other files in the same package like transaction.go.

storage/postgres/policy.go (4)

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

plugin/fees/post_tx.go (2)

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

storage/db.go (6)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: RaghavSood
PR: #75
File: storage/postgres/db_plugin.go:25-40
Timestamp: 2025-05-30T02:44:31.711Z
Learning: The embed.FS directive //go:embed migrations/plugin/*.sql in storage/postgres/db_plugin.go correctly embeds plugin migration files that exist in the storage/postgres/migrations/plugin/ directory. The path "migrations/plugin" passed to goose.Up() references the embedded filesystem structure, not the physical file system path.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: RaghavSood
PR: #36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path github.com/vultisig/verifier/plugin refers to an external dependency that provides the plugin interface, and should not be changed to github.com/vultisig/plugin/plugin as these are distinct packages with different purposes.

plugin/fees/fees.go (9)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.

Learnt from: RaghavSood
PR: #36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path github.com/vultisig/verifier/plugin refers to an external dependency that provides the plugin interface, and should not be changed to github.com/vultisig/plugin/plugin as these are distinct packages with different purposes.

Learnt from: johnnyluo
PR: #108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.

Learnt from: johnnyluo
PR: #108
File: Dockerfile.Payroll.server:14-19
Timestamp: 2025-07-02T04:55:36.331Z
Learning: In the vultisig/plugin repository, the team maintains both the main repository and the go-wrappers dependency repository, so they are comfortable downloading from the master branch rather than pinning to specific commits.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

plugin/fees/transaction.go (11)

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Learnt from: RaghavSood
PR: #36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path github.com/vultisig/verifier/plugin refers to an external dependency that provides the plugin interface, and should not be changed to github.com/vultisig/plugin/plugin as these are distinct packages with different purposes.

Learnt from: webpiratt
PR: #105
File: plugin/dca/dca.go:734-736
Timestamp: 2025-07-01T17:35:35.277Z
Learning: The DCA plugin in the vultisig/plugin codebase is currently not fully implemented. Methods like getCompletedSwapTransactionsCount() return placeholder values (e.g., 0) with TODO comments, which is expected behavior during the development phase. The plugin implementation is intentionally incomplete while other parts of the system are being refactored.

Learnt from: webpiratt
PR: #125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

Learnt from: webpiratt
PR: #125
File: plugin/payroll/transaction.go:186-197
Timestamp: 2025-07-09T22:22:36.651Z
Learning: In plugin/payroll/transaction.go, the getTokenID function is designed to return evm.ZeroAddress.Hex() when no "token" parameter constraint is found, rather than returning an error. This is expected behavior according to the team's design intent, even though the token parameter is marked as required in the recipe specification.

Learnt from: webpiratt
PR: #127
File: internal/keysign/signer.go:134-142
Timestamp: 2025-07-19T12:28:15.328Z
Learning: In internal/keysign/signer.go, the continue statement in the CheckKeysignComplete error handling (around line 140) is intentional. The code should attempt to check all messages in each polling iteration, even if some CheckKeysignComplete calls fail, before proceeding to the next polling cycle. This provides resilience for temporary failures on individual messages.

storage/postgres/fees.go (5)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: RaghavSood
PR: #36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path github.com/vultisig/verifier/plugin refers to an external dependency that provides the plugin interface, and should not be changed to github.com/vultisig/plugin/plugin as these are distinct packages with different purposes.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

🧬 Code Graph Analysis (5)
internal/verifierapi/fees.go (1)
internal/verifierapi/verifierapi.go (1)
  • VerifierApi (26-31)
cmd/fees/worker/main.go (1)
plugin/fees/constraints.go (3)
  • TypeFeeLoad (6-6)
  • TypeFeeTransact (7-7)
  • TypeFeePostTx (8-8)
storage/postgres/policy.go (1)
storage/postgres/db.go (1)
  • PostgresBackend (15-17)
plugin/fees/fees.go (1)
internal/types/fees.go (2)
  • FeeRunStateDraft (14-14)
  • FeeRun (29-39)
storage/postgres/fees.go (3)
storage/postgres/db.go (1)
  • PostgresBackend (15-17)
internal/types/fees.go (5)
  • FeeRunState (11-11)
  • FeeRun (29-39)
  • FeeRunStateSent (15-15)
  • FeeRunStateSuccess (16-16)
  • Fee (21-26)
internal/verifierapi/fees.go (1)
  • FeeDto (12-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (30)
service/policy.go (1)

133-133: LGTM! Method call updated to align with database layer refactoring.

The change from GetAllPluginPolicies to GetPluginPolicies correctly reflects the database layer refactoring while maintaining the same interface contract.

internal/verifierapi/fees.go (2)

7-7: LGTM! Time import correctly added for the new method.

The time package import is properly added to support the time.Time parameter in the new MarkFeeAsCollected method.


60-84: LGTM! Well-implemented method with proper error handling.

The MarkFeeAsCollected method follows established patterns in the codebase:

  • Clear parameter types and purpose
  • Proper JSON request body structure
  • Comprehensive error handling with descriptive messages
  • Correct HTTP status code validation
  • Proper resource cleanup with deferred Body.Close()
storage/postgres/migrations/plugin/20250630152230_fee_runs.sql (2)

9-9: LGTM! Correct column type for Ethereum transaction hashes.

VARCHAR(66) is the appropriate size for Ethereum transaction hashes (2 characters for "0x" prefix + 64 hex characters).


28-28: LGTM! View correctly updated to reflect schema changes.

The fee_run_with_totals view is properly updated to select tx_hash instead of tx_id and includes it in the GROUP BY clause, maintaining consistency with the table schema changes.

Also applies to: 34-34

internal/types/fees.go (3)

14-18: LGTM! Well-structured state constants.

The addition of FeeRunStateSuccess and FeeRunStateFailed constants provides clear completion states for the fee processing workflow. The naming follows the established "fee" singular convention.


34-34: LGTM! Transaction hash as string is more appropriate.

Changing from TxID *uuid.UUID to TxHash *string is the correct approach for storing Ethereum transaction hashes, which are hex strings, not UUIDs.


38-38: LGTM! Embedded fees provide convenient access.

Adding the Fees []Fee slice allows direct access to individual fees within a fee run, supporting the modular processing workflow described in the PR objectives.

plugin/fees/config.go (4)

41-42: LGTM! Configuration supports new transaction confirmation workflow.

The addition of EthProvider and SuccessConfirmations fields properly extends the configuration to support the post-transaction confirmation logic described in the PR objectives.


55-55: LGTM! Reasonable default for confirmation threshold.

Setting the default SuccessConfirmations to 20 is appropriate for Ethereum mainnet, providing a good balance between security and processing time.


93-105: LGTM! Configuration option functions follow established patterns.

The WithEthClient and WithSuccessConfirmations functions maintain consistency with existing configuration option patterns in the codebase.


175-177: LGTM! Proper validation for required configuration.

Adding validation for the EthProvider field ensures the configuration is complete before the plugin operates, preventing runtime failures.

cmd/fees/worker/main.go (5)

25-40: LGTM! Well-structured fee loading orchestration.

The startLoadingFees function properly marshals the fee collection configuration and enqueues the task with appropriate retry and timeout settings.


42-51: LGTM! Clean transaction orchestration.

The startTransactingFees function correctly enqueues the transaction task with empty payload, as the handler will determine which fee runs to process.


53-62: LGTM! Appropriate post-transaction monitoring.

The startPostTx function properly enqueues the status checking task to monitor transaction confirmations.


176-178: LGTM! Task handlers aligned with new workflow phases.

The three separate task handlers (TypeFeeLoad, TypeFeeTransact, TypeFeePostTx) properly implement the separated fee processing workflow described in the PR objectives.


180-199: LGTM! Well-designed cron schedules for different phases.

The cron schedules are appropriately configured:

  • Loading fees every 10 minutes ensures regular fee discovery
  • Transacting fees weekly on Fridays provides batch processing
  • Post-transaction checks every 5 minutes enables timely confirmation monitoring
storage/postgres/policy.go (2)

41-71: LGTM! Well-designed fee-specific policy retrieval.

The GetAllFeePolicies method properly implements fee-specific policy retrieval with:

  • Correct filtering for the fee plugin ID 'vultisig-fees-feee'
  • DISTINCT ON(public_key) with ORDER BY created_at DESC to get the latest policy per public key
  • Proper error handling and row scanning

73-114: LGTM! Preserved functionality with proper validation.

The GetPluginPolicies method maintains the original functionality while adding the essential nil pool check that prevents runtime panics.

plugin/fees/helper.go (2)

18-35: LGTM!

The getHash function correctly reconstructs a signed Ethereum transaction from its components.


110-115: LGTM!

The utility function correctly handles hex strings with or without the "0x" prefix.

storage/db.go (6)

19-19: Method renamed appropriately for clarity.

The renaming from GetAllPluginPolicies to GetPluginPolicies better reflects that this method can filter policies by parameters rather than always returning all policies.


20-20: New method follows naming convention correctly.

The GetAllFeePolicies method name correctly uses "Fee" (singular) as per the established naming convention for this codebase.


25-25: Variadic parameter change improves API usability.

The change from fees []verifierapi.FeeDto to fees ...verifierapi.FeeDto makes the method more convenient to call with individual fee arguments while maintaining backward compatibility.


27-32: New fee run management methods provide comprehensive CRUD operations.

The newly added methods create a complete interface for fee run lifecycle management:

  • SetFeeRunSuccess: Updates run status to successful
  • GetAllFeeRuns: Retrieves runs with optional status filtering
  • GetFees: Fetches fees by IDs
  • GetPendingFeeRun: Gets pending run for a policy
  • CreateFee: Creates individual fee entries
  • GetFeeRuns: Gets runs by specific state

The naming consistently uses "Fee" (singular) following the established convention.


28-28: GetAllFeeRuns variadic handling is correct
The implementation checks len(statuses) == 0 and issues an unfiltered query when no statuses are passed, matching the documented behavior.


26-26: Verified SetFeeRunSent call sites updated

All usages of SetFeeRunSent now pass a string-based transaction hash. In particular:

  • Interface and implementation in
    • storage/db.go
    • storage/postgres/fees.go
      both define SetFeeRunSent(ctx context.Context, runId uuid.UUID, txHash string) error.
  • The sole call in plugin/fees/transaction.go now correctly uses tx.Hash().Hex() (string) when invoking fp.db.SetFeeRunSent.

No callers remain passing a UUID for the transaction identifier.

plugin/fees/fees.go (1)

95-98: LGTM! Proper Ethereum client initialization

The Ethereum client is correctly initialized with proper error handling.

plugin/fees/transaction.go (2)

158-160: No external references to FeePlugin.ProposeTransactions; stub is safe
Ran a search for ProposeTransactions( outside of plugin/fees and only found calls to the local implementations in:

  • plugin/dca/dca.go (DCAPlugin.ProposeTransactions)
  • plugin/payroll/transaction.go (Plugin.ProposeTransactions)

There are no invocations of FeePlugin.ProposeTransactions elsewhere, so the “not implemented” stub won’t break external callers.


279-281: No external dependencies call FeePlugin.SigningComplete

A grep search (rg -A 3 'SigningComplete\(' --glob '!plugin/fees/*') found no references to the stub in plugin/fees/transaction.go outside its own package. The SigningComplete method in the fees plugin isn’t invoked elsewhere in this repo.

Comment thread etc/vultisig/fee.yml
Comment thread internal/verifierapi/verifierapi.go Outdated
Comment thread internal/verifierapi/verifierapi.go Outdated
Comment thread plugin/fees/constraints.go
Comment thread plugin/fees/fees.go
Comment thread plugin/fees/post_tx.go
Comment thread plugin/fees/post_tx.go Outdated
Comment thread plugin/fees/post_tx.go Outdated
Comment thread plugin/fees/transaction.go Outdated
Comment thread storage/postgres/fees.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
plugin/fees/fees.go (3)

143-145: Use proper context and structured logging.

The semaphore acquisition should use the passed context instead of context.Background(), and structured logging should replace error handling patterns.

-			if err := sem.Acquire(context.Background(), 1); err != nil {
-				return fmt.Errorf("failed to acquire semaphore: %w", err)
+			if err := sem.Acquire(ctx, 1); err != nil {
+				fp.logger.WithError(err).Error("Failed to acquire semaphore")
+				return fmt.Errorf("failed to acquire semaphore: %w", err)

224-224: Handle CreateFee error properly.

The error returned by CreateFee is not being handled, which could lead to silent failures.

-				fp.db.CreateFee(ctx, run.ID, fee)
+				if err := fp.db.CreateFee(ctx, run.ID, fee); err != nil {
+					return fmt.Errorf("failed to create fee: %w", err)
+				}

287-289: Use proper context instead of Background.

Same issue with semaphore acquisition using context.Background() instead of the passed context.

-			if err := sem.Acquire(context.Background(), 1); err != nil {
-				return fmt.Errorf("failed to acquire semaphore: %w", err)
+			if err := sem.Acquire(ctx, 1); err != nil {
+				fp.logger.WithError(err).Error("Failed to acquire semaphore")
+				return fmt.Errorf("failed to acquire semaphore: %w", err)
🧹 Nitpick comments (1)
etc/vultisig/fee.yml (1)

10-10: Add newline at end of file.

The file is missing a newline character at the end, which violates YAML formatting standards.

-eth_provider: https://rpc.ankr.com/eth
+eth_provider: https://rpc.ankr.com/eth
+
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b88abfe and f093bb2.

📒 Files selected for processing (17)
  • cmd/fees/worker/main.go (3 hunks)
  • etc/vultisig/fee.yml (1 hunks)
  • internal/types/fees.go (2 hunks)
  • internal/verifierapi/fees.go (2 hunks)
  • internal/verifierapi/verifierapi.go (2 hunks)
  • plugin/fees/config.go (4 hunks)
  • plugin/fees/constraints.go (1 hunks)
  • plugin/fees/fees.go (7 hunks)
  • plugin/fees/helper.go (1 hunks)
  • plugin/fees/post_tx.go (1 hunks)
  • plugin/fees/transaction.go (6 hunks)
  • service/policy.go (1 hunks)
  • storage/db.go (1 hunks)
  • storage/postgres/fees.go (2 hunks)
  • storage/postgres/migrations/plugin/20250630152230_fee_runs.sql (2 hunks)
  • storage/postgres/policy.go (1 hunks)
  • storage/postgres/schema/schema.sql (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
  • service/policy.go
  • internal/verifierapi/fees.go
  • storage/postgres/migrations/plugin/20250630152230_fee_runs.sql
  • plugin/fees/constraints.go
  • internal/verifierapi/verifierapi.go
  • plugin/fees/config.go
  • internal/types/fees.go
  • plugin/fees/post_tx.go
  • cmd/fees/worker/main.go
  • plugin/fees/helper.go
  • storage/postgres/policy.go
  • storage/postgres/fees.go
  • storage/db.go
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: webpiratt
PR: vultisig/plugin#141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local `IsAlreadyProposed` check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.
storage/postgres/schema/schema.sql (2)

Learnt from: webpiratt
PR: #89
File: storage/postgres/migrations/plugin/20250603181247_tx_indexer.sql:13-13
Timestamp: 2025-06-11T18:42:54.241Z
Learning: In the tx_indexer table (storage/postgres/migrations/plugin/*_tx_indexer.sql), the policy_id column is intentionally not defined with a foreign-key constraint to plugin_policies(id).

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

plugin/fees/fees.go (8)

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.

Learnt from: RaghavSood
PR: #36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path github.com/vultisig/verifier/plugin refers to an external dependency that provides the plugin interface, and should not be changed to github.com/vultisig/plugin/plugin as these are distinct packages with different purposes.

Learnt from: johnnyluo
PR: #108
File: cmd/payroll/worker/main.go:84-84
Timestamp: 2025-07-02T04:58:30.139Z
Learning: VaultServiceConfig is defined as a field of type vault_config.Config from the external package "github.com/vultisig/verifier/vault_config" in worker configuration structs across the vultisig/plugin codebase (cmd/payroll/worker/config.go, cmd/fees/worker/config.go, cmd/dca/worker/config.go). The vault_config.Config struct contains an EncryptionSecret field that can be accessed via cfg.VaultServiceConfig.EncryptionSecret.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

plugin/fees/transaction.go (10)

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:0-0
Timestamp: 2025-06-18T18:23:20.077Z
Learning: In the payroll plugin (plugin/payroll/transaction.go), signRequest.Transaction is stored with the "0x" prefix, making it compatible with gcommon.FromHex which requires 0x-prefixed hex strings.

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Learnt from: RaghavSood
PR: #36
File: api/server.go:21-33
Timestamp: 2025-05-07T08:23:45.882Z
Learning: The import path github.com/vultisig/verifier/plugin refers to an external dependency that provides the plugin interface, and should not be changed to github.com/vultisig/plugin/plugin as these are distinct packages with different purposes.

Learnt from: webpiratt
PR: #125
File: plugin/payroll/policy.go:160-160
Timestamp: 2025-07-09T22:23:17.348Z
Learning: In plugin/payroll/policy.go, the "token" case in the checkRule method intentionally does not call validateToken() as this is a temporary implementation that will be replaced with generic schema validation. The missing validation call is expected behavior during this transition period.

Learnt from: webpiratt
PR: #105
File: plugin/dca/dca.go:734-736
Timestamp: 2025-07-01T17:35:35.277Z
Learning: The DCA plugin in the vultisig/plugin codebase is currently not fully implemented. Methods like getCompletedSwapTransactionsCount() return placeholder values (e.g., 0) with TODO comments, which is expected behavior during the development phase. The plugin implementation is intentionally incomplete while other parts of the system are being refactored.

Learnt from: webpiratt
PR: #125
File: plugin/payroll/transaction.go:186-197
Timestamp: 2025-07-09T22:22:36.651Z
Learning: In plugin/payroll/transaction.go, the getTokenID function is designed to return evm.ZeroAddress.Hex() when no "token" parameter constraint is found, rather than returning an error. This is expected behavior according to the team's design intent, even though the token parameter is marked as required in the recipe specification.

Learnt from: webpiratt
PR: #127
File: internal/keysign/signer.go:134-142
Timestamp: 2025-07-19T12:28:15.328Z
Learning: In internal/keysign/signer.go, the continue statement in the CheckKeysignComplete error handling (around line 140) is intentional. The code should attempt to check all messages in each polling iteration, even if some CheckKeysignComplete calls fail, before proceeding to the next polling cycle. This provides resilience for temporary failures on individual messages.

etc/vultisig/fee.yml (5)

Learnt from: webpiratt
PR: #126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant vtypes.PluginVultisigFees_feee in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Learnt from: webpiratt
PR: #96
File: plugin/payroll/transaction.go:43-44
Timestamp: 2025-06-18T18:22:06.358Z
Learning: In the vultisig/plugin codebase, the hardcoded ethereumEvmChainID = big.NewInt(1) in plugin/payroll/transaction.go is intentional for the current implementation phase. The team is implementing ETH first, with plans to add other EVM chains later. The functions/methods are already designed to work with all EVM chains.

Learnt from: webpiratt
PR: #141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local IsAlreadyProposed check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Learnt from: garry-sharp
PR: #117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

🪛 YAMLlint (1.37.1)
etc/vultisig/fee.yml

[error] 10-10: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (14)
storage/postgres/schema/schema.sql (2)

74-74: LGTM! Well-designed schema change for transaction hash tracking.

The replacement of tx_id (UUID) with tx_hash (varchar(66)) properly accommodates Ethereum transaction hashes including the "0x" prefix. The length of 66 characters is correct for this purpose.


84-90: View update is consistent with schema change.

The fee_run_with_totals view correctly uses tx_hash instead of tx_id in both the SELECT and GROUP BY clauses, maintaining consistency with the table schema changes.

plugin/fees/fees.go (5)

6-6: LGTM! Good additions for concurrency control.

The sync and semaphore imports support the new concurrency control mechanisms introduced in the refactoring.

Also applies to: 18-18


49-51: Well-designed synchronization and Ethereum client integration.

The transactingMutex provides proper synchronization between fee loading and transaction handling phases, and the ethClient field enables direct Ethereum interaction.


96-100: Proper Ethereum client initialization.

The ethClient initialization using the EthProvider configuration is correctly implemented with appropriate error handling.


122-156: Excellent separation of concerns in LoadFees method.

The LoadFees method properly separates fee loading from transaction handling, uses appropriate concurrency controls with semaphores, and implements good error handling patterns. The mutex lock ensures no conflicts with transaction processing.


242-306: Well-structured HandleTransactions method with good concurrency control.

The HandleTransactions method properly coordinates transaction processing with mutex synchronization, appropriate filtering of fee runs, and concurrent execution with semaphore limits.

plugin/fees/transaction.go (7)

7-7: Good additions for error handling and type definitions.

The errors import and internal types import support the refactored transaction handling logic.

Also applies to: 30-30


33-156: Well-implemented proposeTransactions method.

The new internal proposeTransactions method properly generates unsigned ERC20 transfer transactions based on fee run data. The logic correctly validates policy-run matching, extracts recipient and token constraints, and constructs the transaction with appropriate error handling.


158-160: Appropriate stub for deprecated method.

The ProposeTransactions method is correctly stubbed as the functionality has been moved to the internal proposeTransactions method used by the new workflow.


181-228: Excellent refactoring of initSign method.

The initSign method now handles the complete transaction lifecycle including decoding, signing, broadcasting via Ethereum client, and status updates. The comprehensive logging and proper error handling make this a robust implementation.


187-194: Good error aggregation pattern.

The use of errors.Join to aggregate multiple potential decoding errors is a clean approach to error handling.


206-212: Comprehensive transaction logging.

The structured logging with transaction details (hash, recipient, amount, token) provides excellent visibility for debugging and monitoring fee collection transactions.


277-279: Appropriate stub for deprecated SigningComplete.

The SigningComplete method is correctly stubbed as its functionality has been integrated into the initSign method in the new workflow.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
fees.md (3)

1-5: Use singular “fee” to stay consistent with project-wide convention

Per long-term learning, the vultisig/plugin codebase (code and docs) should consistently use “fee” (singular). The title and the opening sentence still use “Fees”.

Proposed tweak:

-# Fees System v2 - Comprehensive Analysis
+# Fee System v2 - Comprehensive Analysis
...
-This document provides a comprehensive analysis of the fees system implementation in the fees-v2 branch,
+This document provides a comprehensive analysis of the fee system implementation in the fee-v2 branch,

11-18: Function names in snippet violate the singular “fee” guideline

The example shows LoadFees, HandleTransactions, HandlePostTx. Consider aligning the snippet (and eventually the code) with the singular convention to avoid confusion.

-LoadFees()         // Phase 1: Load fees from verifier into database
-HandleTransactions() // Phase 2: Process fee runs and create transactions
-HandlePostTx()     // Phase 3: Monitor and finalize transactions
+LoadFee()            // Phase 1: Load fee data from verifier into database
+HandleTransaction()  // Phase 2: Process fee runs and create transactions
+HandlePostTx()       // Phase 3: Monitor and finalize transactions

If the underlying functions remain plural for external-API compatibility, add a brief note explaining the exception.


127-133: Hard-coded semaphore weight should be documented as temporary or made configurable

The doc already flags the magic number 10, but consider inserting a TODO block or config excerpt showing the intended parameter, so readers don’t assume the constant is final.

-sem := semaphore.NewWeighted(10)
-// Why 10? Should be configurable
+// Concurrency limit – TODO: move to config (`fee.max_concurrent_tx_process`)
+sem := semaphore.NewWeighted(fp.config.MaxConcurrentTxProcess)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f093bb2 and 2bd2a77.

📒 Files selected for processing (1)
  • fees.md (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.
Learnt from: webpiratt
PR: vultisig/plugin#141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local `IsAlreadyProposed` check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.
📚 Learning: for the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not...
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/constraints.go:3-3
Timestamp: 2025-07-04T10:50:42.832Z
Learning: For the vultisig/plugin project, use "fee" (singular) throughout the codebase wherever possible, not "fees" (plural). This applies to all naming conventions including plugin types, variable names, function names, comments, and documentation.

Applied to files:

  • fees.md
📚 Learning: for the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are in...
Learnt from: garry-sharp
PR: vultisig/plugin#117
File: plugin/fees/policy.go:46-47
Timestamp: 2025-07-04T10:47:47.927Z
Learning: For the fee plugin in plugin/fees/policy.go, the resource validation and recipe specification are intentionally configured to accept only USDC transfers ("ethereum.usdc.transfer"), not general ERC20 transfers ("ethereum.erc20.transfer"), as fees are only collected in USDC.

Applied to files:

  • fees.md
📚 Learning: the constant `vtypes.pluginvultisigfees_feee` in the vultisig/plugin project is correctly spelled wi...
Learnt from: webpiratt
PR: vultisig/plugin#126
File: plugin/fees/policy.go:26-26
Timestamp: 2025-07-10T20:41:44.025Z
Learning: The constant `vtypes.PluginVultisigFees_feee` in the vultisig/plugin project is correctly spelled with "feee" (including the extra 'e'). This is the actual constant name defined in the external dependency github.com/vultisig/verifier/types and should not be changed to "fee" singular, as this is how it's defined in the external package.

Applied to files:

  • fees.md
📚 Learning: in the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been mo...
Learnt from: webpiratt
PR: vultisig/plugin#141
File: plugin/payroll/transaction.go:208-267
Timestamp: 2025-07-24T19:34:47.441Z
Learning: In the vultisig/plugin codebase, duplicate transaction prevention for the payroll plugin has been moved to the verifier side, so the local `IsAlreadyProposed` check in plugin/payroll/transaction.go is no longer needed. The validation flow has changed and is now handled by the verifier rather than within the plugin itself.

Applied to files:

  • fees.md

@garry-sharp

Copy link
Copy Markdown
Contributor Author

Going to reopen elsewhere with cleaner history

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants