-
Notifications
You must be signed in to change notification settings - Fork 909
feat(gov): add Deposit and CancelProposal txs and tests #3004
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
base: main
Are you sure you want to change the base?
Conversation
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThe pull request introduces substantial updates to the governance precompile in the blockchain application. Key changes include the addition of Changes
Possibly related PRs
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Outside diff range and nitpick comments (14)
precompiles/gov/errors.go (1)
32-35
: Consider aligning error constant name with its messageThe error constant
ErrInvalidCoin
uses singular form while its message refers to "coins" (plural). Consider either:
- Renaming to
ErrInvalidCoins
to match the message, or- Updating the message to "invalid coin %s" for consistency
- // ErrInvalidCoin invalid coin. - ErrInvalidCoin = "invalid coins %s " + // ErrInvalidCoins invalid coins. + ErrInvalidCoins = "invalid coins %s "precompiles/gov/events.go (1)
27-38
: Consider standardizing the field naming convention.The
ProposalId
field in both structs uses non-standard Go naming convention. Consider renaming toProposalID
to follow Go's convention for abbreviations.Apply this diff:
- ProposalId uint64 `json:"proposalId"` //nolint:revive,stylecheck + ProposalID uint64 `json:"proposalId"` //nolint:revive,stylecheckprecompiles/gov/IGov.sol (2)
128-150
: Consider enhancing method documentation with validation requirements.While the methods are well-structured, the documentation could be enhanced by specifying:
- Parameter validation requirements (e.g., valid proposal ID ranges, non-zero deposit amounts)
- Conditions under which the operations might fail
- Access control requirements (if any)
Example enhancement for the deposit method:
/// @dev deposit defines a method to add a deposit to a proposal /// @param depositor The address of the depositor /// @param proposalId The proposal id /// @param amount The deposit amount /// @return success Whether the transaction was successful or not +/// @notice The proposal must be in the deposit period +/// @notice The amount must be non-zero and in accepted denomination
Line range hint
1-150
: Consider architectural improvements for better maintainability and standardization.The interface could benefit from the following architectural improvements:
- Consider splitting into sub-interfaces (e.g.,
IGovTransactions
,IGovQueries
) for better separation of concerns- Consider implementing or aligning with governance standards like ERC-3000 for better interoperability
- Consider adding events for error cases to improve observability
precompiles/gov/events_test.go (2)
172-244
: Consider adding error test cases for Deposit eventsWhile the happy path test case is well implemented, consider adding test cases for common error scenarios such as:
- Invalid deposit amount
- Non-existent proposal ID
- Insufficient funds
246-313
: Consider adding error test cases for CancelProposal eventsThe success path is well tested, but consider adding test cases for:
- Non-existent proposal
- Unauthorized cancellation (non-proposer attempt)
- Already canceled proposal
precompiles/gov/tx_test.go (1)
399-486
: Enhance proposal cancellation verificationWhile the test cases cover the basic scenarios, the success case could be more comprehensive:
Consider enhancing the success test case to verify:
- Events emitted during cancellation
- State changes before and after cancellation
- Any refunds or side effects
func() { + // Verify proposal exists before cancellation + found, err := s.network.App.GovKeeper.Proposals.Has(s.network.GetContext(), proposalID) + s.Require().NoError(err) + s.Require().True(found) + + // Get initial state if needed (e.g., deposits, votes) + initialDeposits, err := s.network.App.GovKeeper.GetDeposits(ctx, proposalID) + s.Require().NoError(err) + found, err := s.network.App.GovKeeper.Proposals.Has(s.network.GetContext(), proposalID) s.Require().NoError(err) s.Require().False(found) + + // Verify any expected side effects (e.g., deposit refunds) + // TODO: Add specific assertions based on the expected behavior }precompiles/gov/integration_test.go (2)
213-235
: Consider adding error test cases for CancelProposal.While the happy path is well tested, consider adding test cases for important error scenarios:
- Attempting to cancel a proposal by a non-proposer
- Attempting to cancel a non-existent proposal
- Attempting to cancel a proposal that's already in a final state (e.g., passed, rejected)
237-271
: Enhance deposit test coverage and improve maintainability.
Consider adding test cases for important error scenarios:
- Attempting to deposit with insufficient balance
- Attempting to deposit to a non-existent proposal
- Attempting to deposit with invalid coin denominations
- Attempting to deposit when proposal is in final state
The initial deposit amount (100 wei) should be defined as a constant at the package level for better maintainability and clarity.
// Add at the package level +const ( + // InitialProposalDeposit represents the initial deposit amount for test proposals + InitialProposalDeposit = 100 +) // Update the test to use the constant -expectedAmount := big.NewInt(0).Add(big.NewInt(100), depositAmount) +expectedAmount := big.NewInt(0).Add(big.NewInt(InitialProposalDeposit), depositAmount)precompiles/gov/tx.go (2)
115-117
: Refactor redundant origin checks into a helper functionThe logic for checking whether the origin matches the depositor address is repeated across methods. Refactoring this into a helper function enhances code maintainability and reduces duplication.
For example, implement a helper function:
func (p Precompile) validateOrigin(origin, caller, address common.Address, errMsg string) error { isContractCaller := caller == address && caller != origin if !isContractCaller && origin != address { return fmt.Errorf(errMsg, origin.String(), address.String()) } return nil }And then use it in your methods.
156-159
: Refactor repeated origin check logic into a helper functionThe origin check logic is repeated in multiple methods (
Vote
,VoteWeighted
,Deposit
,CancelProposal
). Refactoring this logic into a reusable helper function will improve code readability and maintainability.You can create a helper function as suggested earlier and replace the origin checks in your methods.
precompiles/gov/types.go (3)
Line range hint
273-299
: Improve error handling inVotesOutput.FromResponse
methodIn the
FromResponse
method forVotesOutput
, when an error occurs during address conversion, the function returnsnil
without providing error context. This may make debugging difficult.Consider returning an error to provide more context:
func (vo *VotesOutput) FromResponse(res *v1.QueryVotesResponse) (*VotesOutput, error) { vo.Votes = make([]WeightedVote, len(res.Votes)) for i, v := range res.Votes { hexAddr, err := utils.Bech32ToHexAddr(v.Voter) if err != nil { - return nil + return nil, fmt.Errorf("failed to convert voter address: %w", err) } // Existing code... } // Existing code... - return vo + return vo, nil }Adjust the function signature and handle the error accordingly.
Line range hint
402-421
: Enhance error handling inDepositOutput.FromResponse
methodSimilar to the previous comment, if there's an error converting the depositor address, returning
nil
without context can hinder debugging.Modify the method to return an error with more information:
func (do *DepositOutput) FromResponse(res *v1.QueryDepositResponse) (*DepositOutput, error) { hexDepositor, err := utils.Bech32ToHexAddr(res.Deposit.Depositor) if err != nil { - return nil + return nil, fmt.Errorf("failed to convert depositor address: %w", err) } // Existing code... - return do + return do, nil }Update the function signature and handle the error accordingly.
Line range hint
584-620
: Consistent error handling inProposalsOutput.FromResponse
methodIn the loop, if an error occurs during address conversion, the method returns
nil
. It's better to return an error to provide context.Apply this diff to improve error handling:
func (po *ProposalsOutput) FromResponse(res *v1.QueryProposalsResponse) (*ProposalsOutput, error) { po.Proposals = make([]ProposalData, len(res.Proposals)) for i, p := range res.Proposals { // Existing code... proposer, err := utils.Bech32ToHexAddr(p.Proposer) if err != nil { - return nil + return nil, fmt.Errorf("failed to convert proposer address: %w", err) } po.Proposals[i] = ProposalData{ // Existing code... } } // Existing code... - return po + return po, nil }Ensure the function signature reflects the error return value.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (11)
CHANGELOG.md
(1 hunks)precompiles/gov/IGov.sol
(2 hunks)precompiles/gov/abi.json
(2 hunks)precompiles/gov/errors.go
(2 hunks)precompiles/gov/events.go
(2 hunks)precompiles/gov/events_test.go
(3 hunks)precompiles/gov/gov.go
(2 hunks)precompiles/gov/integration_test.go
(2 hunks)precompiles/gov/tx.go
(3 hunks)precompiles/gov/tx_test.go
(2 hunks)precompiles/gov/types.go
(19 hunks)
🔇 Additional comments (21)
precompiles/gov/errors.go (2)
8-11
: LGTM! Well-structured error messages for origin validation.
The new error constants follow consistent naming patterns and provide clear, specific messages for origin address validation in proposal and deposit operations.
Line range hint 8-35
: Verify error handling implementation
Let's ensure these new error constants are properly utilized in the transaction implementations.
✅ Verification successful
Error constants are properly implemented and used consistently
The verification shows that the error constants are properly utilized in the codebase:
ErrDifferentOriginProposer
andErrDifferentOriginDepositor
are used intx.go
for origin address validationErrInvalidProposer
is used intypes.go
for proposal-related validations- Error handling follows consistent patterns across the governance package:
- Origin address validation using
ErrDifferentOrigin*
family - Input validation using
ErrInvalid*
family - Proper error formatting with relevant context
- Origin address validation using
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check usage of new error constants in the codebase
# Search for usage of new error constants
echo "Checking usage of new error constants:"
rg "ErrDifferentOriginProposer|ErrDifferentOriginDepositor|ErrInvalidProposer|ErrInvalidCoin" \
--type go \
-B 2 -A 2
# Look for potential error handling patterns we should match
echo -e "\nChecking existing error handling patterns in gov package:"
rg "return.*Err.*Origin|return.*Err.*Invalid" \
--type go \
-g 'precompiles/gov/*.go' \
-B 2 -A 2
Length of output: 14491
precompiles/gov/gov.go (2)
148-148
: LGTM! Verify method constants.
The new methods are correctly identified as transactions, ensuring proper gas calculation and execution flow.
Let's verify the method constants are properly defined:
✅ Verification successful
Method constants are properly defined and used
All method constants (VoteMethod
, VoteWeightedMethod
, DepositMethod
, and CancelProposalMethod
) are correctly defined in precompiles/gov/tx.go
and consistently used in the switch cases throughout the codebase.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for the method constant definitions
# Expected: Should find constant definitions for DepositMethod and CancelProposalMethod
# Search for method constant definitions
echo "Searching for method constant definitions..."
rg -A 1 'const \(\s*DepositMethod|CancelProposalMethod\s*=\s*"'
Length of output: 251
Script:
#!/bin/bash
# Let's also check for DepositMethod constant and verify all method constants used in the switch case
echo "Searching for all method constants..."
rg "const.*(?:Vote|Deposit|CancelProposal).*Method.*=" -A 1
echo -e "\nVerifying usage in switch case..."
rg "case.*(?:Vote|Deposit|CancelProposal).*Method.*:" -A 1
Length of output: 1603
Script:
#!/bin/bash
# Let's check the tx.go file for all method constant definitions to ensure completeness
echo "Checking tx.go for all method constants..."
rg "^const \(" -A 15 precompiles/gov/tx.go
Length of output: 765
105-108
: LGTM! Verify method implementations.
The new methods are properly integrated into the Run
function following the established pattern. The implementation is consistent with other transaction methods in terms of error handling and gas management.
Let's verify the method implementations are present:
✅ Verification successful
Let me try a different search pattern since the previous one might have been too specific.
Implementation verified successfully
The search results confirm that both methods are properly implemented in precompiles/gov/tx.go
. Additionally, the implementations are well-supported with:
- Unit tests in
precompiles/gov/tx_test.go
- Event handling in
precompiles/gov/events.go
- Event tests in
precompiles/gov/events_test.go
- Type handling in
precompiles/gov/types.go
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for the implementation of Deposit and CancelProposal methods
# Expected: Should find method implementations in the same package
# Search for Deposit method implementation
echo "Searching for Deposit method implementation..."
ast-grep --pattern 'func (p Precompile) Deposit(ctx sdk.Context, origin common.Address, contract *vm.Contract, stateDB *storetypes.KVStore, method *abi.Method, args []interface{}) '
# Search for CancelProposal method implementation
echo "Searching for CancelProposal method implementation..."
ast-grep --pattern 'func (p Precompile) CancelProposal(ctx sdk.Context, origin common.Address, contract *vm.Contract, stateDB *storetypes.KVStore, method *abi.Method, args []interface{}) '
Length of output: 594
Script:
#!/bin/bash
# Search for Deposit and CancelProposal method implementations with a more flexible pattern
echo "Searching for Deposit method..."
ast-grep --pattern 'func $_ Deposit($_) {
$$$
}'
echo -e "\nSearching for CancelProposal method..."
ast-grep --pattern 'func $_ CancelProposal($_) {
$$$
}'
# Fallback to ripgrep for additional context
echo -e "\nSearching with ripgrep..."
rg "func.*(?:Deposit|CancelProposal).*\(" -A 2
Length of output: 6879
precompiles/gov/events.go (3)
21-24
: LGTM! Event type constants are well-defined.
The new event type constants follow the existing pattern and are properly documented.
147-180
: Verify the design choice of empty event data.
The implementation sets Data: nil
which differs from other events that pack some data. While this is valid, let's verify this is intentional and matches the Solidity event definition.
✅ Verification successful
Empty data field is correct per event definition
The CancelProposal
event definition in IGov.sol
shows:
event CancelProposal(uint64 indexed proposalId, address indexed proposer);
Both parameters are marked as indexed
, which means they are included in the topics rather than the data field. Therefore, the current implementation with Data: nil
is correct as there are no non-indexed parameters to pack.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify CancelProposal event definition
# Search for the CancelProposal event definition in Solidity files
rg -A 2 'event\s+CancelProposal\s*\(' --type solidity
# Check if there are any non-indexed parameters that should be packed as data
ast-grep --pattern 'event CancelProposal($_) { $$$ }'
Length of output: 144
Script:
#!/bin/bash
# Let's try searching for the event definition in all files since the .sol extension might not be recognized
rg -A 2 'event\s+CancelProposal\s*\('
# Also search for the ABI definition which would show the event structure
rg -A 5 'EventTypeCancelProposal\s*='
# Let's also check the interface or contract definition that might contain this event
rg -A 10 'interface.*Gov'
Length of output: 1501
104-145
: LGTM! Verify event signature matches Solidity contract.
The implementation correctly handles event emission with proper indexing and data packing. Let's verify the event signature matches the Solidity contract definition.
✅ Verification successful
Event signature matches the Solidity interface definition
The implementation in EmitDepositEvent
correctly matches the event signature from IGov.sol
:
- Event name:
Deposit
- Indexed parameters:
proposalId (uint64)
,depositor (address)
- Data parameter:
amount (Coin[])
The topics array and data packing in the implementation align perfectly with this definition:
- Topic[0]: Event signature hash
- Topic[1]: Indexed proposalId
- Topic[2]: Indexed depositor address
- Data: Packed amount as Coin array
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify event signature matches Solidity definition
# Search for the Deposit event definition in Solidity files
rg -A 2 'event\s+Deposit\s*\(' --type solidity
Length of output: 81
Script:
#!/bin/bash
# Search for Deposit event definition in all files, focusing on contract interfaces and definitions
rg -A 2 'event\s+Deposit\s*\('
# Also search specifically in contract-related directories that might contain the interface
fd -e sol . contracts precompiles interfaces 2>/dev/null
# Backup search for ABI definitions that might contain event definitions
fd -g "*abi*.go" . | xargs rg "EventTypeDeposit"
Length of output: 2249
Script:
#!/bin/bash
# Let's find the ABI definition for the Deposit event to compare with implementation
rg -B 2 -A 2 'EventTypeDeposit.*=|const.*EventTypeDeposit' precompiles/gov/
# Also get the ABI construction to see event definition
ast-grep --pattern 'abi.NewEvent($$$)'
Length of output: 530
Script:
#!/bin/bash
# Let's find the ABI method that constructs the events
rg -A 10 'Methods.*Events.*=.*map\[string\]abi.Event' precompiles/gov/
Length of output: 72
Script:
#!/bin/bash
# Search for the ABI definition in the gov precompile
rg -A 20 'var.*ABI.*=.*abi\.JSON' precompiles/gov/
# Also check the contract interface definition again but with more context
rg -B 2 -A 5 'event\s+Deposit' precompiles/gov/IGov.sol
Length of output: 548
precompiles/gov/IGov.sol (1)
90-100
: LGTM! Well-structured events with appropriate parameter indexing.
The new events are well-documented and follow best practices:
- Correct use of indexing for filtering capabilities
- Clear documentation
- Consistent naming convention
precompiles/gov/events_test.go (3)
6-8
: LGTM: Import changes are appropriate
The addition of the math package from cosmos-sdk is necessary for the new deposit functionality.
155-156
: LGTM: Improved struct initialization clarity
The explicit use of gov.WeightedVoteOption
type in the initialization improves code readability. The weights are properly balanced, summing to 1.0.
171-313
: Verify test coverage for new governance transactions
The implementation aligns with the PR objectives by adding tests for both Deposit and CancelProposal events. Let's verify the test coverage:
✅ Verification successful
Test coverage for governance transactions is comprehensive
The verification shows complete test coverage for both Deposit and CancelProposal functionality:
- Both transactions have dedicated test files covering the core functionality (
tx_test.go
) - Event emission is separately tested (
events_test.go
) - All corresponding implementation methods are properly tested:
- Transaction handlers:
Deposit
andCancelProposal
- Event emitters:
EmitDepositEvent
andEmitCancelProposalEvent
- Message constructors:
NewMsgDeposit
andNewMsgCancelProposal
- Transaction handlers:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check test coverage for the new governance transactions
# Look for all governance-related test files
fd -e go test$ precompiles/gov/ -x
# Check for any TODOs or missing test coverage
rg -i "todo|fixme|xxx" precompiles/gov/
Length of output: 192
Script:
#!/bin/bash
# Let's try a different approach to check test coverage
# Find all test files in the gov precompile directory
fd ".*_test.go$" precompiles/gov/
# Check for test functions related to Deposit and CancelProposal
rg "func.*Test(Deposit|CancelProposal)" precompiles/gov/
# Look for the implementation of these methods to ensure all cases are covered
rg "func.*(Deposit|CancelProposal)" precompiles/gov/ --type go -g '!*_test.go'
Length of output: 1737
precompiles/gov/tx_test.go (2)
5-7
: LGTM: Required imports added
The new imports are necessary for handling big numbers in deposits and EVM-specific types.
283-486
: Verify test coverage with additional scenarios
While the test suite covers basic functionality and error cases, consider adding tests for:
- Multiple deposits to the same proposal
- Deposits with multiple coin types
- Cancellation of proposals in different states (voting period, deposit period)
- Edge cases around minimum deposit requirements
precompiles/gov/integration_test.go (1)
13-13
: LGTM!
The new import for the common precompile package is appropriately aliased and necessary for the new deposit functionality.
precompiles/gov/abi.json (2)
6-61
: LGTM! Well-structured event definitions.
The new events CancelProposal
and Deposit
are properly defined with:
- Appropriate indexing of fields for efficient event filtering
- Clear and consistent parameter naming
- Proper type definitions matching the governance domain model
124-198
: LGTM! Well-designed function interfaces.
The new functions cancelProposal
and deposit
are well-implemented with:
- Clear parameter naming and appropriate types
- Proper return values including success flags
- Correct
nonpayable
state mutability - Consistent use of types (e.g.,
Coin[]
) with existing functions
Let's verify the consistency of these new functions with the rest of the codebase:
✅ Verification successful
The ABI functions are well-aligned with the interface contract
The cancelProposal
and deposit
function signatures in the ABI match their interface definitions in IGov.sol with:
- Correct parameter types and names
- Proper return values including success flags
- Consistent use of
Coin[]
struct type for deposits - Appropriate event definitions for both operations
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify consistent usage of Coin[] type and function naming patterns
# Check for consistent usage of Coin[] type in other governance functions
ast-grep --pattern 'struct Coin[] {
$$$
}'
# Check for consistent function naming patterns
ast-grep --pattern 'function $FNAME($$$) {
$$$
}'
Length of output: 129226
Script:
#!/bin/bash
# Let's verify the ABI functions with more targeted commands
# Check for consistent usage of Coin[] type in governance functions
rg -U "struct Coin\[\].*?\{.*?\}" --multiline
# Check for consistent function patterns in governance ABI
rg -U "\"name\": \"(cancelProposal|deposit)\".*?\"type\": \"function\"" --multiline -A 20 precompiles/gov/abi.json
# Look for any related governance function implementations
rg -U "function (cancelProposal|deposit)" --multiline
Length of output: 778
Script:
#!/bin/bash
# Let's examine the governance interface and implementation more closely
# Check the full interface definitions in IGov.sol
cat precompiles/gov/IGov.sol
# Look for any test files that might show usage patterns
rg -g "*.sol" -g "*.js" -l "cancelProposal|deposit.*proposalId"
Length of output: 8143
CHANGELOG.md (1)
53-53
: LGTM! The changelog entry accurately documents the new feature.
The entry properly captures the addition of Deposit
and CancelProposal
transactions to the governance precompile under the "Improvements" section, with correct PR reference.
precompiles/gov/tx.go (1)
173-173
: Review the suppression of linter warning G115
The //nolint:gosec // G115
comment suppresses a security linter warning. Ensure that suppressing this warning is justified and does not introduce security vulnerabilities, such as using weak cryptography or insecure time sources.
Run the following script to verify the linter warning:
Review the linter output and ensure that the use of Unix()
is safe in this context.
✅ Verification successful
Suppression of G115 warning is justified in this context
The G115 warning suppression is appropriate here as this code is handling blockchain governance timestamps in a safe manner. The Unix()
call is used consistently throughout the codebase for handling blockchain-specific timestamps, particularly in governance and staking operations. The timestamp is obtained from resp.CanceledTime
, which is a controlled, blockchain-provided time value, not a potentially insecure local system time. This pattern is used similarly in other precompiles for handling protocol-level timestamps.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Analyze the code for the G115 linter warning and determine if suppression is appropriate.
# Run gosec linter on the file
gosec -no-fail -include=G115 precompiles/gov/tx.go
Length of output: 148
Script:
#!/bin/bash
# Let's analyze the context around the Unix() call to understand its usage
# First, let's see the full context of the file
rg -A 5 -B 5 "Unix\(\)" precompiles/gov/tx.go
# Also check for any related test files or documentation
fd "tx_test.go|README" precompiles/gov/
# Look for other similar Unix() usages in the codebase
rg "Unix\(\)" precompiles/
Length of output: 4395
precompiles/gov/types.go (3)
9-16
: Imports updated to accommodate new dependencies
The addition of "cosmossdk.io/math"
and aliasing v1
for the governance types is appropriate and ensures compatibility with the updated modules.
112-148
: Implementation of NewMsgDeposit
aligns with expected functionality
The NewMsgDeposit
function correctly constructs a MsgDeposit
message with proper argument validation and error handling. The conversion from cmn.Coin
to sdk.Coin
is handled efficiently.
150-172
: Implementation of NewMsgCancelProposal
is correct
The NewMsgCancelProposal
function appropriately creates a MsgCancelProposal
message. Argument validation and error handling are implemented effectively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Outside diff range and nitpick comments (20)
precompiles/gov/errors.go (1)
34-35
: Fix inconsistency in error messageThere's a mismatch between the constant name and its error message:
- Constant name uses singular form:
ErrInvalidCoin
- Error message uses plural form: "invalid coins %s"
Consider maintaining consistency by either:
- Changing the constant to
ErrInvalidCoins
to match the message, or- Changing the message to "invalid coin %s" to match the constant
precompiles/gov/gov.go (1)
105-108
: Consider comprehensive testing scenarios.Given that these governance operations can have significant impact on the chain state:
- Ensure thorough testing of gas consumption patterns for these new operations
- Consider adding integration tests that verify the interaction between these methods and the underlying governance module
- Add test cases for error conditions, especially around proposal state transitions
Would you like assistance in designing these test scenarios?
Also applies to: 148-148
precompiles/gov/events.go (1)
27-38
: LGTM: Event structs are well-definedThe structs are properly defined with appropriate types and JSON tags. Consider adding a period at the end of struct documentation comments for consistency with Go documentation standards.
-// EventDeposit is the event type emitted when a deposit is made to a proposal +// EventDeposit is the event type emitted when a deposit is made to a proposal. -// EventCancelProposal is the event type emitted when a proposal is canceled +// EventCancelProposal is the event type emitted when a proposal is canceled.precompiles/gov/tx.go (2)
128-136
: Enhance documentation for EVM state handling.The EVM state consistency handling is crucial but could use more detailed documentation. Consider expanding the comment to explain:
- Why scaling to 18 decimals is necessary
- What problems could occur without this handling
- The relationship between bank keeper and EVM stateDB
- // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB - // when calling the precompile from a smart contract - // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state. - // Need to scale the amount to 18 decimals for the EVM balance change entry + // IMPORTANT: EVM State Consistency Handling + // When this precompile is called from a smart contract: + // 1. The bank keeper modifies the actual balance + // 2. These changes must be mirrored in the EVM stateDB to prevent overwrites + // 3. All EVM amounts must be scaled to 18 decimals (EVM standard) + // 4. Without this handling, the stateDB would overwrite the bank keeper changes + // during the EVM state commitment phase
171-175
: Document return value structure.The method returns multiple values packed into the ABI output:
- A boolean success flag
- Cancellation timestamp
- Cancellation height
Consider adding a comment documenting these return values and their significance.
+ // Pack multiple return values into ABI output: + // - bool: success flag indicating the proposal was successfully canceled + // - uint64: Unix timestamp when the proposal was canceled + // - uint64: block height when the proposal was canceled return method.Outputs.Pack( true, uint64(resp.CanceledTime.Unix()), resp.CanceledHeight, )precompiles/gov/IGov.sol (2)
129-138
: Consider adding validation requirements to deposit documentation.While the method signature is well-structured, it would be helpful to document any validation requirements for the deposit amount (e.g., minimum/maximum values, token types accepted) to guide implementers and users.
140-150
: Enhance cancelProposal documentation with cancellation conditions.The method is well-structured, but consider adding documentation about:
- Under what conditions a proposal can be canceled
- Any timing restrictions on cancellation
- Whether the proposer is the only one who can cancel
precompiles/gov/events_test.go (3)
155-156
: LGTM - Explicit struct initialization improves readabilityThe explicit use of
gov.WeightedVoteOption
in struct initialization improves code clarity.Consider using the field names for even better readability:
-gov.WeightedVoteOption{Option: 1, Weight: "0.70"}, +gov.WeightedVoteOption{ + Option: 1, + Weight: "0.70", +},
172-244
: Consider adding more test cases for deposit eventsThe test structure is solid, but consider adding these test cases for better coverage:
- Negative test cases:
- Invalid deposit amount (zero or negative)
- Non-existent proposal ID
- Unauthorized depositor
- Edge cases:
- Maximum deposit amount
- Multiple deposit denominations
246-313
: Consider adding more test cases for cancel proposal eventsThe test follows good practices but could be enhanced with additional test cases:
- Negative test cases:
- Non-existent proposal
- Unauthorized cancellation attempt (non-proposer)
- Already canceled proposal
- Edge cases:
- Proposal in different states (voting period, passed, rejected)
precompiles/gov/tx_test.go (2)
293-294
: Consider varying gas limits for different test casesAll test cases use the same gas limit of 200000. Consider adjusting gas limits based on the complexity of each operation to ensure proper gas estimation.
283-486
: Consider enhancing test infrastructureThe test suite could benefit from:
- Helper functions for common setup operations (e.g., proposal creation)
- Shared constants for common values
- Table-driven test utilities for better maintainability
This would reduce code duplication and make tests more maintainable.
precompiles/gov/types.go (8)
Line range hint
211-246
: Potential index out of range panic when accessingmethod.Inputs[2]
In the function
NewMsgVoteWeighted
, accessingmethod.Inputs[2]
without verifying thatmethod.Inputs
has at least three elements could cause an index out of range panic. Ensure thatmethod.Inputs
has sufficient length before accessing its elements.Apply this diff to add the necessary check:
func NewMsgVoteWeighted(method *abi.Method, args []interface{}) (*v1.MsgVoteWeighted, common.Address, WeightedVoteOptions, error) { if len(args) != 4 { return nil, common.Address{}, WeightedVoteOptions{}, fmt.Errorf(cmn.ErrInvalidNumberOfArgs, 4, len(args)) } + if len(method.Inputs) <= 2 { + return nil, common.Address{}, WeightedVoteOptions{}, fmt.Errorf("method.Inputs has insufficient length") + } voterAddress, ok := args[0].(common.Address) if !ok || voterAddress == (common.Address{}) { return nil, common.Address{}, WeightedVoteOptions{}, fmt.Errorf(ErrInvalidVoter, args[0])
Line range hint
273-302
: Inconsistent error handling inFromResponse
methodIn the
VotesOutput.FromResponse
method, if there's an error converting the Bech32 address to hex (utils.Bech32ToHexAddr
), the function returnsnil
without signaling the error. This can lead to silent failures downstream. Consider modifying the method to return an error alongside theVotesOutput
to properly handle error cases.Apply this diff to modify the function signature and error handling:
-func (vo *VotesOutput) FromResponse(res *v1.QueryVotesResponse) *VotesOutput { +func (vo *VotesOutput) FromResponse(res *v1.QueryVotesResponse) (*VotesOutput, error) { vo.Votes = make([]WeightedVote, len(res.Votes)) for i, v := range res.Votes { hexAddr, err := utils.Bech32ToHexAddr(v.Voter) if err != nil { - return nil + return nil, err } // ... rest of the code ... } // ... rest of the code ... - return vo + return vo, nil }
Line range hint
326-345
: Consistent error handling inVoteOutput.FromResponse
methodSimilar to the previous comment, in
VoteOutput.FromResponse
, the method returnsnil
in case of an error without propagating it. Consider updating the method to return an error for proper error handling.Apply this diff to modify the function signature and error handling:
-func (vo *VoteOutput) FromResponse(res *v1.QueryVoteResponse) *VoteOutput { +func (vo *VoteOutput) FromResponse(res *v1.QueryVoteResponse) (*VoteOutput, error) { hexVoter, err := utils.Bech32ToHexAddr(res.Vote.Voter) if err != nil { - return nil + return nil, err } // ... rest of the code ... - return vo + return vo, nil }
Line range hint
402-420
: Ensure proper error propagation inDepositOutput.FromResponse
In the
DepositOutput.FromResponse
method, errors are not propagated. Modify the method to return an error along with the output to handle failures explicitly.Apply this diff:
-func (do *DepositOutput) FromResponse(res *v1.QueryDepositResponse) *DepositOutput { +func (do *DepositOutput) FromResponse(res *v1.QueryDepositResponse) (*DepositOutput, error) { hexDepositor, err := utils.Bech32ToHexAddr(res.Deposit.Depositor) if err != nil { - return nil + return nil, err } // ... rest of the code ... - return do + return do, nil }
Line range hint
422-450
: Consistent error handling inDepositsOutput.FromResponse
The
DepositsOutput.FromResponse
method should also return errors when address conversion fails to avoid silent failures.Apply this diff:
-func (do *DepositsOutput) FromResponse(res *v1.QueryDepositsResponse) *DepositsOutput { +func (do *DepositsOutput) FromResponse(res *v1.QueryDepositsResponse) (*DepositsOutput, error) { do.Deposits = make([]DepositData, len(res.Deposits)) for i, d := range res.Deposits { hexDepositor, err := utils.Bech32ToHexAddr(d.Depositor) if err != nil { - return nil + return nil, err } // ... rest of the code ... } // ... rest of the code ... - return do + return do, nil }
Line range hint
514-536
: Potential issue with castingProposalStatus
In
ParseProposalsArgs
, castinginput.ProposalStatus
directly tov1.ProposalStatus
without validation could result in invalid status values. Consider adding validation to ensureinput.ProposalStatus
corresponds to a validv1.ProposalStatus
enum value.Apply this diff to include validation:
var input ProposalsInput if err := method.Inputs.Copy(&input, args); err != nil { return nil, fmt.Errorf("error while unpacking args to ProposalsInput: %s", err) } + if _, ok := v1.ProposalStatus_name[int32(input.ProposalStatus)]; !ok { + return nil, fmt.Errorf("invalid ProposalStatus value: %d", input.ProposalStatus) + } voter := ""
Line range hint
542-583
: Ensure error propagation inProposalOutput.FromResponse
In the
ProposalOutput.FromResponse
method, errors are not propagated when address conversion fails. Modify the method to return an error for proper error handling.Apply this diff:
-func (po *ProposalOutput) FromResponse(res *v1.QueryProposalResponse) *ProposalOutput { +func (po *ProposalOutput) FromResponse(res *v1.QueryProposalResponse) (*ProposalOutput, error) { // ... existing code ... proposer, err := utils.Bech32ToHexAddr(res.Proposal.Proposer) if err != nil { - return nil + return nil, err } // ... rest of the code ... - return po + return po, nil }
Line range hint
584-627
: Consistent error handling inProposalsOutput.FromResponse
The
ProposalsOutput.FromResponse
method should propagate errors instead of returningnil
to avoid silent failures.Apply this diff:
-func (po *ProposalsOutput) FromResponse(res *v1.QueryProposalsResponse) *ProposalsOutput { +func (po *ProposalsOutput) FromResponse(res *v1.QueryProposalsResponse) (*ProposalsOutput, error) { // ... existing code ... proposer, err := utils.Bech32ToHexAddr(p.Proposer) if err != nil { - return nil + return nil, err } // ... rest of the code ... - return po + return po, nil }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (11)
CHANGELOG.md
(1 hunks)precompiles/gov/IGov.sol
(2 hunks)precompiles/gov/abi.json
(2 hunks)precompiles/gov/errors.go
(2 hunks)precompiles/gov/events.go
(2 hunks)precompiles/gov/events_test.go
(3 hunks)precompiles/gov/gov.go
(2 hunks)precompiles/gov/integration_test.go
(2 hunks)precompiles/gov/tx.go
(3 hunks)precompiles/gov/tx_test.go
(2 hunks)precompiles/gov/types.go
(19 hunks)
🔇 Additional comments (25)
precompiles/gov/errors.go (2)
8-11
: LGTM! Well-structured error messages for origin validation
The new error constants follow the established pattern and provide clear, descriptive messages for address validation failures.
Line range hint 8-35
: Verify comprehensive error handling in transaction handlers
Let's ensure these new error constants are properly utilized in the transaction handlers for comprehensive error handling.
✅ Verification successful
Let me analyze the error handling usage further with additional scripts to check for comprehensive coverage.
Based on the results from both script executions, I can now provide a final response:
Error handling implementation is comprehensive and properly utilized
The verification shows that:
- All error constants are actively used in the codebase, primarily in
precompiles/gov/types.go
for input validation - Error handling covers different scenarios:
- Origin address validation for proposers and depositors
- Input validation for proposal IDs, voters, options, and metadata
- Parameter validation for weighted votes
- No instances of hardcoded error messages that should be using these constants instead
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if all new error constants are used in the codebase
# and verify no direct string error messages are used instead
# Search for usage of new error constants
echo "Checking usage of new error constants..."
rg "ErrDifferentOriginProposer|ErrDifferentOriginDepositor|ErrInvalidProposer|ErrInvalidCoin" --type go
# Search for potential hardcoded error messages that should use these constants
echo "Checking for potential hardcoded error messages..."
rg -i "(?:invalid (?:proposer|coins?)|(?:origin|tx).*(?:proposer|depositor))" --type go
Length of output: 9702
Script:
#!/bin/bash
# Check for the usage of other error constants defined in the file
# and their corresponding error handling in transaction handlers
# Search for usage of remaining error constants
echo "Checking usage of other error constants..."
rg "ErrInvalidVoter|ErrInvalidProposalID|ErrInvalidPageRequest|ErrInvalidOption|ErrInvalidMetadata|ErrInvalidWeightedVoteOptions|ErrInvalidWeightedVoteOption|ErrInvalidWeightedVoteOptionType|ErrInvalidWeightedVoteOptionWeight|ErrInvalidDepositor" --type go
# Check the transaction handlers implementation
echo "Checking transaction handlers implementation..."
ast-grep --pattern 'func ($x *Precompile) $method($$$) ($$$) {
$$$
}' precompiles/gov/tx.go
Length of output: 3730
precompiles/gov/gov.go (1)
148-148
: LGTM! Verify method constants are defined.
The new transaction methods are correctly classified alongside other state-modifying operations.
Let's verify that the method constants are properly defined:
✅ Verification successful
Method constants are properly defined and used consistently
The verification shows that both DepositMethod
and CancelProposalMethod
are correctly defined in precompiles/gov/tx.go
:
DepositMethod = "deposit"
CancelProposalMethod = "cancelProposal"
These constants are consistently used across the codebase in tests, integration tests, and the main implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the method constants for Deposit and CancelProposal are defined
# Search for the constant definitions
rg -A 1 'const \(.*DepositMethod.*=.*\)'
rg -A 1 'const \(.*CancelProposalMethod.*=.*\)'
Length of output: 92
Script:
#!/bin/bash
# Let's try a broader search for these method constants
# First, search for any mentions of these methods
rg "DepositMethod|CancelProposalMethod" -B 2 -A 2
# Also search for const blocks in the same file
rg "const \(" -B 1 -A 10 precompiles/gov/gov.go
Length of output: 7899
precompiles/gov/events.go (3)
21-24
: LGTM: Event type constants follow existing patterns
The new event type constants are well-documented and maintain consistency with the existing naming conventions.
147-180
: LGTM: EmitCancelProposalEvent implementation is correct
The function correctly handles event emission with no additional data required beyond the indexed parameters.
Let's verify the event definition in the ABI matches the implementation:
104-145
: LGTM: EmitDepositEvent implementation is correct
The function follows the established pattern for event emission, with proper error handling and data packing.
Let's verify the event definition in the ABI matches the implementation:
precompiles/gov/tx.go (3)
9-10
: LGTM! Imports and constants are well-defined.
The new imports and method constants are appropriately added and follow the existing pattern in the codebase.
Also applies to: 25-28
173-173
: Review Unix timestamp conversion security.
The line is marked with a nolint:gosec
comment for G115 (potential time-based logic issues). While this might be acceptable for event timestamps, please verify that this doesn't introduce any security vulnerabilities in the governance process.
✅ Verification successful
Unix timestamp usage in governance module is consistent with other modules and properly documented
The Unix timestamp conversion in the governance module follows the same pattern used across other modules (vesting, staking, slashing) where timestamps are used for event logging and state transitions. All instances are properly marked with //nolint:gosec // G115
comments, acknowledging the known time-based logic considerations. The usage here is for recording the proposal cancellation time as part of the event data, which doesn't introduce security concerns in the governance process since:
- The timestamp is derived from the blockchain's block time, not from user input
- It's used for informational purposes in event logs
- The actual governance logic relies on block height for critical operations
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other Unix timestamp conversions in governance code
rg -A 2 "Unix\(\)" --type go
Length of output: 12702
113-117
: Please clarify the origin validation logic.
The origin validation logic is complex and could benefit from additional clarification:
isOriginDepositor := contract.CallerAddress == origin
isContractDepositor := contract.CallerAddress == depositorAddr && !isOriginDepositor
if !isContractDepositor && origin != depositorAddr {
return nil, fmt.Errorf(ErrDifferentOriginDepositor, origin.String(), depositorAddr.String())
}
Consider adding a comment explaining the different scenarios this handles:
- When is
isOriginDepositor
true? - When is
isContractDepositor
true? - What security concerns does this address?
precompiles/gov/IGov.sol (1)
90-100
: LGTM! Well-structured event definitions.
The new events are well-documented and follow best practices:
- Appropriate indexing on key parameters for efficient event filtering
- Clear documentation following the existing pattern
- Essential information captured in event parameters
precompiles/gov/events_test.go (1)
6-7
: LGTM - Required imports for new test functions
The new imports are necessary for handling math operations and EVM types in the deposit tests.
precompiles/gov/tx_test.go (1)
5-7
: LGTM: Import additions are appropriate
The new imports are correctly used in the test functions - math/big
for amount comparisons and evmtypes
for EVM coin denomination.
precompiles/gov/integration_test.go (1)
13-13
: LGTM!
The import of the common package is correctly aliased and necessary for the new test cases.
precompiles/gov/abi.json (4)
6-24
: LGTM: Well-structured event definition
The CancelProposal event is properly defined with appropriate parameter types and indexing for efficient event filtering.
25-61
: LGTM: Event parameters are well-structured
The Deposit event is properly defined with:
- Correct indexing strategy for efficient filtering
- Appropriate use of complex types for the amount parameter
124-157
: Verify proposer parameter authorization
The function includes a proposer parameter, which suggests authorization checks. Please ensure that the implementation properly validates that:
- Only the original proposer can cancel their proposal
- The proposal exists and is in a cancellable state
✅ Verification successful
Authorization checks are properly implemented
The implementation includes appropriate authorization checks:
- Verifies that the origin (transaction sender) matches the proposer address
- Has a special case to handle when the contract itself is the proposer
- Only allows the original proposer to cancel their proposal through the check:
if !isContractProposer && origin != proposerAddr
The proposal state validation is handled by the underlying Cosmos SDK governance module through msgSrv.CancelProposal()
, which ensures the proposal exists and is in a cancellable state.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for authorization checks in the implementation
ast-grep --pattern 'if ($proposer == $_) { $$$
}'
# Search for proposal state validation
ast-grep --pattern 'if ($proposal.status == $_) { $$$
}'
Length of output: 110
Script:
#!/bin/bash
# Let's search for the implementation file first
fd "gov" --type f --extension go --extension sol
# Then search for cancelProposal implementation
rg -l "cancelProposal"
# Search for any mentions of proposal cancellation logic
rg -i "cancel.*proposal"
Length of output: 5967
Script:
#!/bin/bash
# Let's examine the implementation in tx.go
rg -A 20 "func \(p Precompile\) CancelProposal" precompiles/gov/tx.go
# Also check the message construction
rg -A 10 "func NewMsgCancelProposal" precompiles/gov/types.go
Length of output: 1212
158-198
: Verify deposit validation
Please ensure that the implementation includes proper validation:
- The proposal exists and is in a deposit-accepting state
- The deposit amount meets minimum requirements
- The deposit denomination is valid
CHANGELOG.md (1)
53-53
: LGTM! The changelog entry matches the PR objectives.
The changelog entry correctly documents the addition of Deposit
and CancelProposal
transactions to the governance precompile, which aligns with the PR objectives.
Let's verify the implementation of these transactions:
✅ Verification successful
Implementation of Deposit
and CancelProposal
transactions verified successfully
The codebase shows complete implementation of both transactions:
- Both methods are properly defined in the governance precompile with appropriate parameters and error handling
- Event emission is implemented for both transactions
- Comprehensive test coverage exists including both transaction tests and event tests
- The implementation aligns with the changelog entry
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the implementation of Deposit and CancelProposal transactions
# in the governance precompile
# Check for the transaction definitions
rg -A 5 "Deposit.*CancelProposal" precompiles/gov
# Check for any test files
fd -g "*_test.go" | xargs rg "TestDeposit|TestCancelProposal"
Length of output: 696
Script:
#!/bin/bash
# Let's verify the implementation details of these methods
# Check the method definitions and implementations
ast-grep --pattern 'func (p *Precompile) Deposit($$$) error {
$$$
}'
ast-grep --pattern 'func (p *Precompile) CancelProposal($$$) error {
$$$
}'
# Check the method declarations in the interface
rg -A 2 "DepositMethod.*=|CancelProposalMethod.*=" precompiles/gov
# Check for event definitions
rg "Deposit.*Event|CancelProposal.*Event" precompiles/gov
Length of output: 1756
Script:
#!/bin/bash
# Let's check the actual implementation of these transactions
# Check the transaction implementations
rg -B 2 -A 10 "^func.*Deposit\(" precompiles/gov/tx.go
rg -B 2 -A 10 "^func.*CancelProposal\(" precompiles/gov/tx.go
# Check the test implementations to understand the expected behavior
rg -B 2 -A 10 "^func.*TestDeposit\(" precompiles/gov/tx_test.go
rg -B 2 -A 10 "^func.*TestCancelProposal\(" precompiles/gov/tx_test.go
Length of output: 1572
precompiles/gov/types.go (7)
9-9
: Import statement is appropriate
The addition of "cosmossdk.io/math"
is necessary and correctly included for handling mathematical operations.
16-16
: Updated import to use the new governance module types
The change to import v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
reflects the migration to the new governance module version and is correctly implemented.
150-172
: Function NewMsgCancelProposal
is correctly implemented
The NewMsgCancelProposal
function is correctly implemented with proper argument checks and message construction.
Line range hint 175-200
: Function NewMsgVote
is correctly implemented
The NewMsgVote
function correctly handles argument validation and message creation without issues.
Line range hint 257-267
: Function ParseVotesArgs
is correctly handling input parameters
The ParseVotesArgs
function correctly unpacks the arguments and constructs the query request.
Line range hint 451-460
: Function TallyResultOutput.FromResponse
is correctly implemented
The TallyResultOutput.FromResponse
method accurately maps the response data to the output structure.
Line range hint 498-508
: Function ParseProposalArgs
properly parses arguments
The ParseProposalArgs
function correctly handles input validation and constructs the query request.
I think we can apply most of the coderabbit suggestions |
Signed-off-by: stepit <[email protected]>
Co-authored-by: stepit <[email protected]> Signed-off-by: Vladislav Varadinov <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
precompiles/gov/events_test.go (3)
155-156
: Consider using idiomatic struct initializationThe struct initialization can be more concise using field names without repeating the type.
- gov.WeightedVoteOption{Option: 1, Weight: "0.70"}, - gov.WeightedVoteOption{Option: 2, Weight: "0.30"}, + {Option: 1, Weight: "0.70"}, + {Option: 2, Weight: "0.30"},
172-244
: Consider adding error test casesThe test only covers the success path. Consider adding test cases for:
- Invalid proposal ID
- Insufficient deposit amount
- Invalid deposit denomination
246-313
: Consider adding error test casesThe test only covers the success path. Consider adding test cases for:
- Invalid proposal ID
- Non-proposer attempting to cancel
- Already canceled proposal
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
CHANGELOG.md
(1 hunks)precompiles/gov/errors.go
(2 hunks)precompiles/gov/events_test.go
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- CHANGELOG.md
- precompiles/gov/errors.go
🔇 Additional comments (4)
precompiles/gov/events_test.go (4)
179-219
: Simplify test structure
Since we're only testing one case, we can simplify the test structure by removing the test cases array and directly implementing the test logic.
203-203
: Maintain consistent assertion order
For consistency with the codebase, expected value should be the first argument in assertions.
- s.Require().Equal(uint64(ctx.BlockHeight()), log.BlockNumber) //nolint:gosec // G115
+ s.Require().Equal(log.BlockNumber, uint64(ctx.BlockHeight())) //nolint:gosec // G115
253-289
: Simplify test structure
Since we're only testing one case, we can simplify the test structure by removing the test cases array and directly implementing the test logic.
276-276
: Maintain consistent assertion order
For consistency with the codebase, expected value should be the first argument in assertions.
- s.Require().Equal(log.BlockNumber, uint64(ctx.BlockHeight())) //nolint:gosec // G115
+ s.Require().Equal(uint64(ctx.BlockHeight()), log.BlockNumber) //nolint:gosec // G115
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (5)
precompiles/common/errors.go (1)
31-32
: Consider enhancing the error message with more context.The error message is quite generic and doesn't follow the pattern of other validation errors in this file that provide more detailed context. Consider making it more specific and adding format specifiers to include validation failure details.
- // ErrInvalidMethodInputs is raised when the method does not have the expected inputs defined. - ErrInvalidMethodInputs = "invalid method inputs" + // ErrInvalidMethodInputs is raised when the method inputs fail validation. + ErrInvalidMethodInputs = "invalid method inputs: %v"precompiles/vesting/types.go (2)
105-107
: Good addition of input validation, but consider making the check more preciseThe validation check prevents potential panic when accessing
method.Inputs[3]
and[4]
later in the function. However, since we know exactly how many inputs we need, we could make the check more precise.Consider updating the check to explicitly validate for exactly 5 inputs:
-if len(method.Inputs) <= 4 { +if len(method.Inputs) != 5 { return nil, common.Address{}, common.Address{}, nil, nil, fmt.Errorf(cmn.ErrInvalidMethodInputs) }This would better align with the function's requirements, as it uses indices 3 and 4 specifically for lockup and vesting periods.
105-107
: Consider enhancing the error messageThe generic
ErrInvalidMethodInputs
could be more helpful if it specified the expected number of inputs.Consider using a more descriptive error message:
-return nil, common.Address{}, common.Address{}, nil, nil, fmt.Errorf(cmn.ErrInvalidMethodInputs) +return nil, common.Address{}, common.Address{}, nil, nil, fmt.Errorf("invalid number of method inputs: expected 5, got %d", len(method.Inputs))precompiles/gov/types.go (2)
Line range hint
408-426
: Consider adding error context in FromResponse methodsThe
FromResponse
methods forDepositOutput
andDepositsOutput
silently return nil on Bech32 address conversion errors. Consider adding error context to help with debugging.func (do *DepositOutput) FromResponse(res *v1.QueryDepositResponse) *DepositOutput { hexDepositor, err := utils.Bech32ToHexAddr(res.Deposit.Depositor) if err != nil { - return nil + return fmt.Errorf("failed to convert depositor address: %w", err) }Also applies to: 428-456
Line range hint
548-589
: Consider implementing pagination limitThe
FromResponse
methods forProposalOutput
andProposalsOutput
handle large datasets. Consider implementing pagination limits to prevent potential memory issues with large result sets.Also applies to: 590-642
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
precompiles/common/errors.go
(1 hunks)precompiles/gov/types.go
(19 hunks)precompiles/ics20/types.go
(2 hunks)precompiles/vesting/types.go
(1 hunks)
🔇 Additional comments (6)
precompiles/common/errors.go (1)
31-32
: Verify the error constant usage across the codebase.
Let's ensure this error is being used consistently and follows similar patterns to other validation errors in the governance precompile.
✅ Verification successful
Let me gather more information about similar error patterns in the codebase to ensure consistency.
Based on the analysis of the codebase, I can now provide a final response about the usage of ErrInvalidMethodInputs
:
Error constant is used consistently and follows established patterns
The ErrInvalidMethodInputs
error is used appropriately across the codebase:
- It's used consistently in input validation checks across multiple precompiles (gov, ics20, vesting) when method inputs don't meet the expected length
- The error follows the same pattern as other validation errors in the codebase:
- Simple, descriptive message format
- Used in length validation checks before unpacking method inputs
- Returns with fmt.Errorf for consistent error handling
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check how the new error constant is used and compare with similar validation patterns
# Check where the new error is used
echo "Checking usage of ErrInvalidMethodInputs:"
rg "ErrInvalidMethodInputs" -B 2 -A 2
# Check similar validation patterns in governance precompile
echo -e "\nChecking similar validation patterns in governance code:"
rg "invalid.*method|method.*invalid" --type go -g "precompiles/gov/**"
Length of output: 2300
Script:
#!/bin/bash
# Check error patterns in precompiles
echo "Checking error patterns in precompiles:"
rg "ErrInvalid|invalid" --type go -g "precompiles/**/*.go" -B 1 -A 1
# Check error string formats
echo -e "\nChecking error string formats:"
rg '= ".*invalid.*"' --type go -g "precompiles/**/*.go"
# Check error handling patterns in input validation
echo -e "\nChecking input validation patterns:"
ast-grep --pattern 'if len($_.Inputs) $_ {
return $$$, fmt.Errorf($_)
}'
Length of output: 104793
precompiles/ics20/types.go (2)
311-313
:
Review the validation check for authorization method inputs
Similar to the previous issue, this validation check for method.Inputs
length is problematic:
- It's redundant with the args length check at line 310.
- If
method.Inputs
represents ABI method inputs, it should match the expected number of arguments (2). - The error message is too generic and doesn't indicate the actual requirement.
Let's verify the ABI method definition:
Consider one of these alternatives:
- if len(method.Inputs) <= 1 {
- return common.Address{}, nil, fmt.Errorf(cmn.ErrInvalidMethodInputs)
- }
+ // Option 1: Match expected args length
+ if len(method.Inputs) != 2 {
+ return common.Address{}, nil, fmt.Errorf("invalid number of method inputs: expected 2, got %d", len(method.Inputs))
+ }
+
+ // Option 2: Remove redundant check if it's not necessary
✅ Verification successful
The previous search was too specific. Let's broaden our search to understand the context better and verify the validation requirements for the transfer authorization method.
Based on the provided context, I can now generate the final response. The code shows that method.Inputs
represents the ABI method inputs, and the validation is part of the argument unpacking process for the allocations parameter.
The validation check for method inputs is necessary and correct
The check if len(method.Inputs) <= 1
is required because:
- The function needs to access
method.Inputs[1]
to unpack the allocations argument using ABI encoding. - The error occurs before attempting to access this index, preventing a potential panic.
- The error message correctly indicates an issue with the method's ABI definition.
The validation is different from the args length check because:
len(args)
validates the number of arguments passed to the functionlen(method.Inputs)
validates the ABI method definition itself has the correct parameter types
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for the ABI definition or interface that defines this authorization method
rg -A 5 'transfer.*authorization.*\(.*common\.Address.*ICS20Allocation'
Length of output: 73
Script:
#!/bin/bash
# Let's try to find the method definition and its usage in a broader search
rg -A 5 'checkTransferAuthzArgs'
# Also search for any transfer authorization related code
rg -A 5 'TransferAuthorization'
# Look for the actual method definition in the file
cat precompiles/ics20/types.go
Length of output: 29050
139-141
:
Review the validation check for method inputs
The validation check for method.Inputs
length seems problematic:
- It's redundant with the args length check at line 138.
- If
method.Inputs
represents ABI method inputs, it should match the expected number of arguments (9). - The error message is too generic and doesn't indicate the actual requirement.
Let's verify the ABI method definition:
Consider one of these alternatives:
- if len(method.Inputs) <= 6 {
- return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidMethodInputs)
- }
+ // Option 1: Match expected args length
+ if len(method.Inputs) != 9 {
+ return nil, common.Address{}, fmt.Errorf("invalid number of method inputs: expected 9, got %d", len(method.Inputs))
+ }
+
+ // Option 2: Remove redundant check if it's not necessary
precompiles/gov/types.go (3)
9-9
: LGTM! Import changes look good.
The transition from govv1
to v1
and addition of math
package are appropriate for the new implementation.
Also applies to: 16-16
239-242
:
Validate WeightedVoteOption values
This is a duplicate of a previous review comment. The VoteOption values should be validated before casting.
540-541
:
Validate ProposalStatus values
This is a duplicate of a previous review comment. The ProposalStatus should be validated before casting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (6)
precompiles/gov/tx.go (2)
133-142
: Consider documenting the state consistency logicThe state consistency handling for non-origin depositors is crucial but complex. Consider adding a more detailed comment explaining why this scaling is necessary and what could happen if it's not done correctly.
if !isOriginDepositor { - // NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB - // when calling the precompile from a smart contract - // This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state. - // Need to scale the amount to 18 decimals for the EVM balance change entry + // IMPORTANT: State Consistency Handling + // 1. When called from a smart contract, we need to mirror bank keeper changes in the EVM stateDB + // 2. This prevents the stateDB from overwriting the bank keeper's balance changes during EVM state commit + // 3. The amount must be scaled to 18 decimals to match EVM's decimal precision + // 4. Without this scaling, there would be precision loss in the EVM state
97-182
: Consider extracting common authorization patternsThe authorization logic for checking contract vs origin addresses is repeated across all methods (Vote, VoteWeighted, Deposit, CancelProposal). Consider extracting this into a helper function to improve maintainability and reduce duplication.
Example helper function:
func (p Precompile) validateOrigin( contract *vm.Contract, origin, expectedAddr common.Address, errMsg string, ) error { isContractCaller := contract.CallerAddress == expectedAddr && contract.CallerAddress != origin if !isContractCaller && origin != expectedAddr { return fmt.Errorf(errMsg, origin.String(), expectedAddr.String()) } return nil }🧰 Tools
🪛 GitHub Check: Run golangci-lint
[failure] 113-113:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)precompiles/gov/tx_test.go (1)
370-371
: Improve clarity of initial deposit valueThe magic number
100
should be defined as a constant with a descriptive name to improve readability and maintainability.+const initialDeposit = 100 // 100 is the initial deposit -s.Require().Equal(math.NewInt(1e18).AddRaw(100), deposits[0].Amount[0].Amount.BigInt()) +s.Require().Equal(math.NewInt(1e18).AddRaw(initialDeposit), deposits[0].Amount[0].Amount.BigInt())precompiles/gov/types.go (2)
112-158
: LGTM: Well-structured deposit message creation with comprehensive validationThe implementation includes thorough validation of all input parameters and proper conversion of coin amounts.
Consider improving error messages for better debugging:
- return nil, common.Address{}, fmt.Errorf(ErrInvalidDeposit) + return nil, common.Address{}, fmt.Errorf("%s: empty deposit amount", ErrInvalidDeposit)- return nil, common.Address{}, fmt.Errorf(ErrInvalidDeposit) + return nil, common.Address{}, fmt.Errorf("%s: non-positive amount %v", ErrInvalidDeposit, c.Amount)🧰 Tools
🪛 GitHub Check: Run golangci-lint
[failure] 138-138:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
[failure] 144-144:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
160-182
: Add validation for proposal IDThe implementation looks good but could benefit from additional validation.
Consider adding validation for non-zero proposal ID:
proposalID, ok := args[1].(uint64) if !ok { return nil, common.Address{}, fmt.Errorf(ErrInvalidProposalID, args[1]) } + if proposalID == 0 { + return nil, common.Address{}, fmt.Errorf("%s: proposal ID cannot be zero", ErrInvalidProposalID) + }precompiles/gov/integration_test.go (1)
259-325
: Well-structured test cases for Deposit!The test cases effectively cover both success and error scenarios, with proper verification of deposit amounts. Good use of the
initialDeposit
constant for maintainability.Consider adding a test case for depositing after the deposit end time:
It("should fail when depositing after deposit end time", func() { // Advance past the deposit end time proposal, _ := s.network.App.GovKeeper.Proposals.Get(s.network.GetContext(), proposalID) ctx := s.network.GetContext() ctx = ctx.WithBlockTime(proposal.DepositEndTime.Add(time.Hour)) s.network.App.GovKeeper.Proposals.Set(ctx, proposalID, proposal) depositAmount := big.NewInt(1e18) coins := []cmn.Coin{{Denom: evmtypes.GetEVMCoinDenom(), Amount: depositAmount}} callArgs.Args = []interface{}{ s.keyring.GetAddr(0), proposalID, coins, } depositCheck := defaultLogCheck.WithErrContains("deposit period ended") _, _, err := s.factory.CallContractAndCheckLogs(s.keyring.GetPrivKey(0), txArgs, callArgs, depositCheck) Expect(err).To(BeNil()) })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
precompiles/gov/errors.go
(2 hunks)precompiles/gov/integration_test.go
(2 hunks)precompiles/gov/tx.go
(3 hunks)precompiles/gov/tx_test.go
(2 hunks)precompiles/gov/types.go
(19 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- precompiles/gov/errors.go
🧰 Additional context used
🪛 GitHub Check: Run golangci-lint
precompiles/gov/tx.go
[failure] 113-113:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
precompiles/gov/types.go
[failure] 138-138:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
[failure] 144-144:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
🔇 Additional comments (9)
precompiles/gov/tx.go (3)
25-28
: LGTM: Constants follow naming convention
The new constants for Deposit and CancelProposal methods follow the existing naming pattern and correctly define the ABI method names.
146-182
: LGTM: Well-structured authorization and event handling
The CancelProposal implementation follows good practices:
- Proper authorization checks for contract vs origin proposer
- Clear event emission
- Complete return values including cancellation details
177-181
: Consider handling time conversion edge cases
The Unix timestamp conversion could potentially overflow for dates beyond 2038 on 32-bit systems. Consider adding validation or documentation about this limitation.
precompiles/gov/tx_test.go (2)
6-7
: LGTM!
The added import for evmtypes
is necessary and correctly placed following Go's standard import grouping.
470-474
: 🛠️ Refactor suggestion
Enhance proposal cancellation verification
The success test case should verify the proposal's existence before cancellation and ensure proper status changes.
func() {
+ // Verify proposal exists before cancellation
+ proposal, err := s.network.App.GovKeeper.Proposals.Get(ctx, proposalID)
+ s.Require().NoError(err)
+ s.Require().NotNil(proposal)
+
+ // Verify proposal is cancelled
found, err := s.network.App.GovKeeper.Proposals.Has(s.network.GetContext(), proposalID)
s.Require().NoError(err)
s.Require().False(found)
}
precompiles/gov/types.go (2)
9-9
: LGTM: Import changes align with v1 governance types
The changes correctly update the imports to use the new v1 governance types from the Cosmos SDK.
Also applies to: 16-16
246-249
:
Add validation for VoteOption values
The VoteOption is cast without validation, which could lead to invalid votes being processed.
As noted in the previous review, please add validation for VoteOption values:
weightedOptions := make([]*v1.WeightedVoteOption, len(options))
for i, option := range options {
+ if _, ok := v1.VoteOption_name[int32(option.Option)]; !ok {
+ return nil, common.Address{}, WeightedVoteOptions{}, fmt.Errorf("invalid VoteOption: %d", option.Option)
+ }
weightedOptions[i] = &v1.WeightedVoteOption{
Option: v1.VoteOption(option.Option),
Weight: option.Weight,
}
}
precompiles/gov/integration_test.go (2)
13-13
: LGTM!
The added import for the common package is necessary for the new test cases and follows the project's naming conventions.
213-257
: Well-structured test cases for CancelProposal!
The test cases effectively cover both success and error scenarios, with clear assertions and error messages.
As suggested in the previous review, consider adding test cases for:
- Attempting to cancel an already executed proposal
- Attempting to cancel an expired proposal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (5)
precompiles/gov/tx.go (1)
155-171
: Consider additional validation for proposal cancellationWhile the basic validation is in place, consider adding checks for:
- Proposal existence
- Proposal status (ensure it can be cancelled)
- Cancellation timeframe validation (if there are time-based restrictions)
msg, proposerAddr, err := NewMsgCancelProposal(args) if err != nil { return nil, err } + +// Add proposal existence check +proposal, err := p.govKeeper.GetProposal(ctx, msg.ProposalId) +if err != nil { + return nil, fmt.Errorf("proposal %d not found", msg.ProposalId) +} + +// Add status check +if !proposal.Status.IsCancellable() { + return nil, fmt.Errorf("proposal %d cannot be cancelled in status %s", msg.ProposalId, proposal.Status) +}precompiles/gov/tx_test.go (1)
288-377
: Consider adding more test casesThe test suite could benefit from additional edge cases:
- Multiple deposits from the same depositor
- Deposit with multiple coins
- Deposit with zero amount
Would you like me to provide implementations for these additional test cases?
precompiles/gov/types.go (2)
137-139
: Improve error message specificityThe error message should provide more context about why the deposit is invalid.
if len(amount) == 0 { - return nil, common.Address{}, fmt.Errorf(ErrInvalidDeposit) + return nil, common.Address{}, fmt.Errorf("%s: empty amount", ErrInvalidDeposit) }🧰 Tools
🪛 GitHub Check: Run golangci-lint
[failure] 138-138:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
143-145
: Improve error message for invalid deposit amountThe error message should specify which coin has an invalid amount.
if c.Amount.Sign() <= 0 { - return nil, common.Address{}, fmt.Errorf(ErrInvalidDeposit) + return nil, common.Address{}, fmt.Errorf("%s: non-positive amount for coin %s", ErrInvalidDeposit, c.Denom) }🧰 Tools
🪛 GitHub Check: Run golangci-lint
[failure] 144-144:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)precompiles/gov/integration_test.go (1)
276-276
: Consider using a more specific error message.The error message "failed ETH tx" is too generic. Consider checking for a more specific error message that indicates the proposal doesn't exist.
- depositCheck := defaultLogCheck.WithErrContains("failed ETH tx") + depositCheck := defaultLogCheck.WithErrContains("not found: key '999'")
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
precompiles/gov/errors.go
(2 hunks)precompiles/gov/integration_test.go
(2 hunks)precompiles/gov/tx.go
(3 hunks)precompiles/gov/tx_test.go
(2 hunks)precompiles/gov/types.go
(19 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- precompiles/gov/errors.go
🧰 Additional context used
🪛 GitHub Check: Run golangci-lint
precompiles/gov/tx.go
[failure] 113-113:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
precompiles/gov/types.go
[failure] 138-138:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
[failure] 144-144:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
🔇 Additional comments (12)
precompiles/gov/tx.go (3)
25-28
: LGTM: Constants follow consistent naming pattern
The new method constants for DepositMethod
and CancelProposalMethod
are well-defined and follow the existing naming convention.
177-181
: Verify timestamp handling in response
The Unix timestamp conversion should be checked for potential timezone issues or edge cases.
✅ Verification successful
Let me analyze the timestamp handling in the codebase based on the search results. The code in question is:
return method.Outputs.Pack(
true,
uint64(resp.CanceledTime.Unix()), //nolint:gosec // G115
resp.CanceledHeight,
)
From the search results, I can see that:
- The timestamp handling is consistent across the codebase, using
Unix()
for timestamp conversions - The
CanceledTime
is already in UTC as it comes from the blockchain's context - The code is properly handling the conversion by:
- Using the standard
Unix()
method which returns seconds since epoch - Converting to
uint64
which is the expected type for the ABI encoding
- Using the standard
- The G115 linter suppression is consistently used across the codebase for similar conversions
- The conversion doesn't involve any timezone-specific operations that could cause issues
No timezone or edge case concerns with timestamp handling
The timestamp handling is safe and consistent with the rest of the codebase. The CanceledTime
is already in UTC, and the conversion to Unix timestamp is straightforward without any timezone manipulation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for timestamp handling in tests
rg -A 5 "CanceledTime|Unix"
Length of output: 38339
133-142
: Review the balance scaling implementation
The balance scaling logic is critical for EVM state consistency. Ensure that:
- The conversion to 18 decimals is properly tested with various token denominations
- The balance change entries are correctly applied in all edge cases
✅ Verification successful
Let me gather more information about the testing coverage of this functionality.
Let me check the actual decimal conversion implementation and test coverage.
Let me check the actual test implementations to verify the coverage of edge cases.
Based on the comprehensive test coverage shown in the scaling tests, I can now provide the final response:
Balance scaling implementation is properly tested and verified
The balance scaling implementation is thoroughly tested with:
- Conversion between 6 and 18 decimals
- Edge cases including:
- Zero amounts
- Amounts less than conversion factor
- Maximum amounts ("one ether")
- Smallest possible amounts (1 wei)
- Rounding behavior for decimal places
- Different token denominations
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for tests covering the balance scaling logic
rg -A 5 "ConvertAmountTo18DecimalsBigInt|SetBalanceChangeEntries"
Length of output: 7356
Script:
#!/bin/bash
# Search for test files that might cover the balance scaling logic
rg -t go -g "*_test.go" "ConvertAmountTo18DecimalsBigInt|SetBalanceChangeEntries" -A 5
# Also check the implementation of GetEVMCoinDecimals which is crucial for the conversion
ast-grep --pattern 'func GetEVMCoinDecimals() $_'
Length of output: 493
Script:
#!/bin/bash
# Check the Decimals type and conversion factor implementation
rg -A 10 "type Decimals struct" x/evm/types/
# Look for test files covering decimal conversions
rg -g "*_test.go" "TestConvert.*Decimals|TestGetEVMCoin" -A 10
Length of output: 1930
Script:
#!/bin/bash
# Get the full content of the scaling tests
cat x/evm/types/scaling_test.go
# Check for any integration tests that might cover this functionality
rg -g "*_test.go" "TestIntegration.*Balance|TestPrecompile.*Balance" -A 10
Length of output: 10272
precompiles/gov/tx_test.go (3)
6-7
: LGTM!
The added import for evmtypes
is necessary and properly organized.
470-474
: Enhance proposal cancellation verification
The success case should verify the proposal's existence and status before cancellation.
This is a duplicate of a previous review comment. The suggestion to enhance the verification by checking the proposal's existence and status before cancellation remains valid.
413-425
: LGTM! Good error case coverage
The test case for non-existent proposal is well implemented and covers an important edge case.
precompiles/gov/types.go (3)
160-182
: LGTM! Well-implemented proposal cancellation
The function includes all necessary validations and proper error handling.
547-548
: Validate ProposalStatus to prevent invalid enum values
The ProposalStatus is cast without validation, which could lead to unexpected behavior.
246-251
:
Add validation for vote options
The conversion of vote options lacks validation, which could allow invalid vote options to pass through.
weightedOptions := make([]*v1.WeightedVoteOption, len(options))
for i, option := range options {
+ if _, ok := v1.VoteOption_name[int32(option.Option)]; !ok {
+ return nil, common.Address{}, WeightedVoteOptions{}, fmt.Errorf("invalid vote option: %d", option.Option)
+ }
weightedOptions[i] = &v1.WeightedVoteOption{
Option: v1.VoteOption(option.Option),
Weight: option.Weight,
}
}
Likely invalid or redundant comment.
precompiles/gov/integration_test.go (3)
13-13
: LGTM!
The import of the common package is necessary for the Coin type used in Deposit tests and follows the project's naming conventions.
213-257
: LGTM! Comprehensive test coverage for CancelProposal.
The test suite effectively covers:
- Error case: non-existent proposal
- Error case: unauthorized cancellation
- Success case: proper proposal cancellation with state verification
259-325
: LGTM! Well-structured test suite for Deposit functionality.
The test suite provides good coverage of success and failure scenarios, with proper state verification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
precompiles/gov/tx_test.go (1)
372-373
: Improve clarity of deposit amount verificationThe comment about initial deposit (100) needs better documentation and the verification could be more explicit.
- // 100 is the initial deposit - s.Require().Equal(math.NewInt(1e18).AddRaw(100).BigInt(), deposits[0].Amount[0].Amount.BigInt()) + // Verify total deposit amount (initial proposal deposit + new deposit) + initialDeposit := int64(100) // Initial deposit required for proposal creation + newDeposit := math.NewInt(1e18) + expectedAmount := newDeposit.AddRaw(initialDeposit) + s.Require().Equal(expectedAmount.BigInt(), deposits[0].Amount[0].Amount.BigInt())
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
precompiles/gov/tx_test.go
(2 hunks)
🔇 Additional comments (3)
precompiles/gov/tx_test.go (3)
6-7
: LGTM!
The added import for evmtypes
is necessary and properly used throughout the test cases.
282-503
: Overall implementation looks good!
The implementation of both TestDeposit
and TestCancelProposal
functions follows good testing practices:
- Comprehensive test cases covering various scenarios
- Proper error handling and validation
- Consistent structure with existing test functions
474-478
: 🛠️ Refactor suggestion
Enhance proposal cancellation verification
The success test case should verify the proposal's existence before cancellation for a more comprehensive test.
func() {
+ // Verify proposal exists before cancellation
+ found, err := s.network.App.GovKeeper.Proposals.Has(ctx, proposalID)
+ s.Require().NoError(err)
+ s.Require().True(found)
+
+ // Verify proposal is cancelled
found, err := s.network.App.GovKeeper.Proposals.Has(s.network.GetContext(), proposalID)
s.Require().NoError(err)
s.Require().False(found)
},
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (8)
precompiles/gov/tx.go (3)
107-115
: Enhance deposit validationWhile basic validation exists, consider adding more comprehensive checks:
- Validate that the amount is positive
- Verify the denomination is correct for your chain
- Add maximum deposit amount validation if applicable
if len(msg.Amount) != 1 { return nil, errors.New(ErrInvalidDeposit) } +if msg.Amount[0].IsZero() { + return nil, errors.New("deposit amount must be positive") +} +if msg.Amount[0].Denom != ExpectedDenom { + return nil, fmt.Errorf("invalid denomination: expected %s, got %s", ExpectedDenom, msg.Amount[0].Denom) +}
134-143
: Improve documentation of EVM state synchronizationThe current comment could be more explicit about the technical details of the state synchronization process.
Consider expanding the comment to:
-// NOTE: This ensures that the changes in the bank keeper are correctly mirrored to the EVM stateDB -// when calling the precompile from a smart contract -// This prevents the stateDB from overwriting the changed balance in the bank keeper when committing the EVM state. -// Need to scale the amount to 18 decimals for the EVM balance change entry +// NOTE: When a precompile is called from a smart contract, we need to ensure that +// balance changes made by the bank keeper are correctly reflected in the EVM state: +// 1. The bank keeper modifies the actual balance +// 2. We record a corresponding change in the EVM stateDB +// 3. This prevents the final EVM state commit from overwriting the bank keeper's changes +// 4. The amount must be scaled to 18 decimals to match EVM precision
178-182
: Document timestamp handlingThe Unix timestamp conversion needs clearer documentation about timezone handling and potential limitations.
return method.Outputs.Pack( true, - uint64(resp.CanceledTime.Unix()), //nolint:gosec // G115 + uint64(resp.CanceledTime.Unix()), // Convert to Unix timestamp (UTC) for EVM compatibility resp.CanceledHeight, )precompiles/gov/types.go (1)
138-146
: Enhance deposit amount validationWhile the function validates that the amount is not empty and positive, consider adding these additional checks:
- Validate maximum deposit amount
- Ensure denomination is allowed
if len(amount) == 0 { return nil, common.Address{}, errors.New(ErrInvalidDeposit) } +// Define allowed denominations +var allowedDenoms = map[string]bool{"stake": true, "evmos": true} + coins := make([]sdk.Coin, len(amount)) for i, c := range amount { if c.Amount.Sign() <= 0 { return nil, common.Address{}, errors.New(ErrInvalidDeposit) } + if !allowedDenoms[c.Denom] { + return nil, common.Address{}, fmt.Errorf("invalid denomination: %s", c.Denom) + } + // Add maximum deposit check if applicable + if c.Amount.BitLen() > 256 { + return nil, common.Address{}, fmt.Errorf("deposit amount too large") + } coins[i] = sdk.Coin{precompiles/gov/integration_test.go (4)
225-225
: Consider using a more specific error message check.The error message
"not found: key '999'"
is implementation-specific. Consider using a more domain-specific error message that better describes the business logic failure.
213-257
: Add more test cases for comprehensive coverage.While the current test cases cover the basic scenarios, consider adding tests for:
- Attempting to cancel an already executed proposal
- Attempting to cancel a proposal after voting period ends
- Attempting to cancel a proposal with insufficient gas
276-276
: Consider using a more specific error message check.Similar to the cancel proposal tests, the error message
"not found: key '999'"
is implementation-specific. Consider using a more domain-specific error message.
259-325
: Add test cases for additional edge cases.Consider adding tests for:
- Depositing after the deposit period ends
- Depositing with invalid denomination
- Depositing with zero amount
- Multiple deposits from the same depositor
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
precompiles/gov/integration_test.go
(2 hunks)precompiles/gov/tx.go
(3 hunks)precompiles/gov/types.go
(19 hunks)
🧰 Additional context used
🪛 GitHub Check: Run golangci-lint
precompiles/gov/types.go
[failure] 169-169:
SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
🔇 Additional comments (3)
precompiles/gov/tx.go (1)
26-29
: LGTM: Constants follow consistent naming pattern
The new constants DepositMethod
and CancelProposalMethod
are well-named and follow the existing pattern.
precompiles/gov/types.go (1)
214-214
: Add validation for VoteOption values
The VoteOption is still being cast without validation in multiple places, which could lead to invalid vote options being processed.
This issue was previously identified in the past review comments. Please implement the suggested validation for VoteOption values.
Also applies to: 250-250
precompiles/gov/integration_test.go (1)
298-324
: LGTM! Well-structured successful deposit test.
The successful deposit test is well implemented with:
- Clear setup of test data
- Proper event verification
- Thorough state validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
precompiles/gov/types.go (2)
129-131
: Improve error message for method inputs validationThe error message should be more specific about the expected number of inputs.
- return nil, common.Address{}, fmt.Errorf(cmn.ErrInvalidMethodInputs) + return nil, common.Address{}, fmt.Errorf("%s: expected > 2 inputs, got %d", cmn.ErrInvalidMethodInputs, len(method.Inputs))
138-146
: Enhance deposit amount validationThe current validation could be more specific about the requirements for valid deposits.
if len(amount) == 0 { - return nil, common.Address{}, errors.New(ErrInvalidDeposit) + return nil, common.Address{}, fmt.Errorf("%s: deposit amount cannot be empty", ErrInvalidDeposit) } coins := make([]sdk.Coin, len(amount)) for i, c := range amount { if c.Amount.Sign() <= 0 { - return nil, common.Address{}, errors.New(ErrInvalidDeposit) + return nil, common.Address{}, fmt.Errorf("%s: deposit amount must be positive for coin %s", ErrInvalidDeposit, c.Denom) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
precompiles/gov/types.go
(19 hunks)
🔇 Additional comments (5)
precompiles/gov/types.go (5)
17-17
: LGTM: Import changes align with governance types update
The change from govv1
to v1
correctly reflects the transition to updated governance types in the Cosmos SDK.
247-252
: Add validation for vote options
The code casts option.Option
to v1.VoteOption
without validating if it's a valid option value.
This issue was previously identified in past reviews. Please refer to the existing comment for the suggested fix.
167-170
:
Fix error message formatting
The error message uses fmt.Errorf without any formatting arguments.
proposer, ok := args[0].(common.Address)
if !ok || proposer == (common.Address{}) {
- return nil, common.Address{}, errors.New(ErrInvalidProposer)
+ return nil, common.Address{}, fmt.Errorf(ErrInvalidProposer, proposer)
}
Likely invalid or redundant comment.
172-175
: 🛠️ Refactor suggestion
Add validation for proposal ID value
The function should validate that the proposal ID is not zero.
proposalID, ok := args[1].(uint64)
if !ok {
return nil, common.Address{}, fmt.Errorf(ErrInvalidProposalID, args[1])
}
+ if proposalID == 0 {
+ return nil, common.Address{}, fmt.Errorf("%s: proposal ID cannot be zero", ErrInvalidProposalID)
+ }
Likely invalid or redundant comment.
113-183
: Verify transaction authorization checks
Please ensure that proper authorization checks are implemented in the precompile contract for these new transaction types.
✅ Verification successful
Based on the comprehensive review of the implementation, I can now provide the final response:
Authorization checks are properly implemented through the precompile framework
The governance precompile inherits from the common precompile framework which provides several security measures:
- Transaction vs. query validation through
RunSetup
- Write protection for read-only calls
- Proper gas accounting and error handling
- State management through journal entries
- Origin address validation in transaction methods
The Deposit
and CancelProposal
methods are properly secured as they:
- Run through the common precompile framework's security checks
- Validate the origin address of transactions
- Include proper error handling for invalid inputs
- Maintain state consistency through journal entries
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for authorization checks in the precompile contract
# Search for authorization checks in the precompile implementation
rg -A 5 "RequireNotPayable|RequireOnlyFromEOA|RequireAuth" precompiles/gov/
Length of output: 77
Script:
#!/bin/bash
# Let's check the precompile contract implementation for these methods
ast-grep --pattern 'func (p $_) Deposit($$$) error {
$$$
}'
# Also check for CancelProposal
ast-grep --pattern 'func (p $_) CancelProposal($$$) error {
$$$
}'
# Check for any authorization-related functions or methods
rg -B 2 -A 5 "authorize|auth|require" precompiles/gov/
Length of output: 4241
Script:
#!/bin/bash
# Let's check the actual implementation of these methods in the contract
rg -B 2 -A 10 "func \(p \*Precompile\) (Deposit|CancelProposal)" precompiles/gov/
# Also check for any transaction validation or authorization in the base precompile
rg -B 2 -A 10 "func \(p \*Precompile\) (CheckTransaction|ValidateBasic)" precompiles/gov/
# Check the common precompile package for authorization mechanisms
rg -B 2 -A 10 "func.*Require(Auth|NotPayable|OnlyFromEOA)" precompiles/common/
Length of output: 256
Script:
#!/bin/bash
# Let's check the transaction methods in the contract file
rg -B 2 -A 10 "func.*Deposit|func.*CancelProposal" precompiles/gov/tx.go
# Check the base contract implementation
cat precompiles/gov/gov.go
# Check if there are any other transaction methods that might show the pattern
rg -l "MsgServer" precompiles/gov/
Length of output: 5504
Script:
#!/bin/bash
# Let's check the common precompile implementation for authorization checks
cat precompiles/common/precompile.go
# Check if there are any authorization checks in the base setup
rg -B 2 -A 10 "RunSetup" precompiles/common/
# Check for any authorization checks in the transaction execution
rg -B 2 -A 10 "HandleGasError|AddJournalEntries" precompiles/common/
Length of output: 14392
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (1)
CHANGELOG.md (1)
53-54
: Consider breaking long line into multiple lines for better readability.The changelog entry exceeds the recommended line length. Consider reformatting it as:
-- (precompiles) [#3004](https://github.com/evmos/evmos/pull/3004) Add `Deposit` and `CancelProposal` tx to gov precompile. ++ (precompiles) [#3004](https://github.com/evmos/evmos/pull/3004) Add `Deposit` and ++ `CancelProposal` tx to gov precompile.🧰 Tools
🪛 Markdownlint (0.35.0)
54-54: Expected: 120; Actual: 137
Line length(MD013, line-length)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
CHANGELOG.md
(1 hunks)
🧰 Additional context used
🪛 Markdownlint (0.35.0)
CHANGELOG.md
54-54: Expected: 120; Actual: 137
Line length
(MD013, line-length)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
precompiles/gov/tx.go (3)
112-115
: Enhance deposit amount validationWhile the length check is good, consider adding more comprehensive validation:
- Verify amount is positive
- Validate denomination if specific tokens are required
if len(msg.Amount) != 1 { return nil, errors.New(ErrInvalidDeposit) } +if msg.Amount[0].IsZero() { + return nil, errors.New("deposit amount must be positive") +}
134-143
: Consider documenting the scaling factorThe balance scaling logic is correct, but it would be helpful to document:
- Why 18 decimals is used as the target
- What happens if the original token has more than 18 decimals
178-182
: Add comment explaining the return valuesThe method returns multiple values (success, canceledTime, canceledHeight) but their purpose isn't immediately clear. Consider adding a comment explaining what these values represent and how they should be used.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
precompiles/gov/tx.go
(3 hunks)
🔇 Additional comments (2)
precompiles/gov/tx.go (2)
26-29
: LGTM: Constants follow established naming patterns
The new constants for DepositMethod
and CancelProposalMethod
are well-defined and consistent with existing method naming conventions.
180-180
: Consider time zone handling for canceledTime
The Unix timestamp conversion assumes UTC. Consider documenting this assumption or handling time zones explicitly if needed.
✅ Verification successful
Based on the search results, I can see a consistent pattern across the codebase where Unix timestamps are handled uniformly. Here's what I found:
-
In the EVM/RPC layer (
rpc/types/utils.go
), timestamps are explicitly converted to UTC before Unix conversion:time := uint64(header.Time.UTC().Unix())
-
In other precompiles (staking, slashing, gov), Unix timestamps are used with
//nolint:gosec // G115
comment, indicating a deliberate choice to use Unix timestamps consistently. -
The codebase consistently treats time values as UTC timestamps when converting to Unix format, as seen in multiple precompiles like staking and evidence modules.
The time zone handling is consistent with blockchain conventions
The use of Unix timestamps in resp.CanceledTime.Unix()
follows the established pattern in the codebase where blockchain time is consistently handled in UTC. This is the standard approach in blockchain systems and doesn't require additional documentation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if there are any time zone conversions or assumptions in the codebase
rg -A 2 "Unix\(\)"
Length of output: 13488
Pull request was converted to draft
Description
Adds
Deposit
andCancelProposal
transactions with tests.Closes: #XXXX
Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
Reviewers Checklist
All items are required.
Please add a note if the item is not applicable
and please add your handle next to the items reviewed
if you only reviewed selected items.
I have...
Unreleased
section inCHANGELOG.md
Summary by CodeRabbit
Release Notes
New Features
Deposit
andCancelProposal
functionalities in governance, allowing users to deposit to proposals and cancel proposals.Deposit
andCancelProposal
to improve tracking of governance actions.Improvements
Bug Fixes
evmosd testnet init-files
to ensure correct default denomination usage.These changes enhance user interaction with governance features and improve overall system reliability.