Skip to content

Commit 6b07f11

Browse files
committed
Problem: geth abi library is not suitable for precompile
Solution: - use go-abi for much better efficiency and error handling update go-abi stdlib support fix: convert interface{} to generated statically typed structs in precompile tests Refactored test files to use generated statically typed structs from go-abi instead of interface{}: - gov/types_test.go: Updated 5 test functions * TestNewMsgDeposit → DepositCall * TestNewMsgCancelProposal → CancelProposalCall * TestNewMsgVote → VoteCall * TestParseVoteArgs → GetVoteCall * TestParseDepositArgs → GetDepositCall - distribution/types_test.go: Updated 8 test functions * TestNewMsgSetWithdrawAddress → SetWithdrawAddressCall * TestNewMsgWithdrawDelegatorReward → WithdrawDelegatorRewardsCall * TestNewMsgFundCommunityPool → FundCommunityPoolCall * TestNewMsgDepositValidatorRewardsPool → DepositValidatorRewardsPoolCall * TestNewDelegationRewardsRequest → DelegationRewardsCall * TestNewDelegationTotalRewardsRequest → DelegationTotalRewardsCall * TestNewDelegatorValidatorsRequest → DelegatorValidatorsCall * TestNewDelegatorWithdrawAddressRequest → DelegatorWithdrawAddressCall - slashing/types_test.go: Updated 1 test function * TestParseSigningInfoArgs: Simplified to remove unnecessary type checks Removed type validation test cases (now handled by Go's type system) and kept only business logic tests. Removed unused fmt imports where applicable. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> fix test fix: convert interface{} to generated statically typed structs in precompile tests Convert all precompile test files to use generated statically typed structs instead of []interface{}, providing better type safety and developer experience. Changes: - distribution/types_test.go: Convert test arguments from []interface{} to generated structs - staking/types_test.go: Convert all test cases to use generated statically typed structs: * CreateValidatorCall, DelegateCall, UndelegateCall, RedelegateCall * CancelUnbondingDelegationCall, DelegationCall, UnbondingDelegationCall * Updated struct field names to match generated types (Commission → CommissionRates) * Removed unused imports - slashing/types_test.go: Convert test arguments from []interface{} to GetSigningInfoCall - slashing/query.go: Updated query functions to use generated struct types - slashing/tx.go: Updated transaction functions to use generated struct types - slashing/types.go: Updated ParseSigningInfoArgs and ParseSigningInfosArgs - slashing/slashing.go: Added PageRequest mapping to go:generate directive - slashing/slashing.abi.go: Regenerated to use cmn.PageRequest instead of duplicate type Results: - All tests pass successfully - 517 lines of code removed - Type safety improved with compile-time checking - Better IDE autocomplete and type hints 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> perf: remove redundant *Output structs and move FromResponse to *Return structs Refactor precompile code to remove redundant *Output structs (SigningInfoOutput, SigningInfosOutput, ParamsOutput) and their corresponding custom types. The FromResponse methods now directly populate the generated *Return structs. Benefits: - Removed 78 lines of redundant code - Eliminated type duplication between *Output and *Return structs - Simplified query functions by removing unnecessary conversions - Direct use of generated statically typed structs Changes in slashing precompile: - Deleted SlashingSigningInfo, SigningInfoOutput, SigningInfosOutput structs - Deleted SlashingParams, ParamsOutput structs - Moved FromResponse method receivers to *GetSigningInfoReturn, *GetSigningInfosReturn, *GetParamsReturn - Simplified query.go functions to directly use *Return structs - All tests pass successfully 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> feat: migrate remaining precompiles to use generated statically typed structs Convert bank, bech32, erc20, and werc20 precompiles to use generated statically typed structs instead of []interface{}, following the pattern established in staking, distribution, and slashing precompiles. Changes: - bank/types.go: Removed unused ParseBalancesArgs and ParseSupplyOfArgs functions - bech32/methods.go: Updated HexToBech32 and Bech32ToHex to use generated Call/Return structs - bech32/bech32.go: Updated Run function to decode args directly using generated structs - erc20/approve.go: Updated Approve to use ApproveCall and ApproveReturn - erc20/erc20.go: Updated Execute to use cmn.Run and cmn.RunWithStateDB with ID constants - erc20/query.go: Converted all query functions to use generated return types - erc20/tx.go: Updated Transfer/TransferFrom to use generated Call/Return structs - erc20/types.go: Removed all Parse*Args functions (replaced by generated structs) - werc20/tx.go: Updated Withdraw to use WithdrawCall and WithdrawReturn - werc20/werc20.go: Updated Execute and IsTransaction to use ID constants Benefits: - ~500+ lines of code removed across all precompiles - Type safety improved with compile-time checking - Better IDE autocomplete and type hints - Consistent patterns across all precompiles Build Status: ✅ All migrated precompiles build successfully ✅ All tests pass (staking, distribution, slashing) Note: ics20 precompile deferred (already builds successfully but uses old pattern) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> update go-abi cleanup changelog fix build feat: migrate bank precompile integration tests to go-abi Migrate bank precompile tests from go-ethereum ABI to custom go-abi library: - Updated ContractData struct to remove precompileABI field - Replaced UnpackIntoInterface/Unpack calls with manual decoding helpers - Updated getTxAndCallArgs to use EncodeWithSelector() for direct precompile calls - Rewrote test_query.go unit tests to use typed call structs (BalancesCall, SupplyOfCall, TotalSupplyCall) - Created decoder helper functions for type-safe result decoding - Tests now use fully type-safe generated types instead of reflection Created comprehensive MIGRATION_GUIDE.md with step-by-step instructions for migrating other precompile tests to go-abi. Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> feat: migrate bech32 and slashing precompile integration tests to go-abi Migrated bech32 and slashing precompile tests from go-ethereum ABI to custom go-abi library: Bech32 precompile (tests/integration/precompiles/bech32/): - Updated all test cases to use typed call structs (HexToBech32Call, Bech32ToHexCall) - Replaced Pack() calls with EncodeWithSelector() for input encoding - Replaced Unpack() calls with direct Decode() on result types - Rewrote unit tests to use direct precompile methods instead of generic interface Slashing precompile (tests/integration/precompiles/slashing/): - Updated TestGetSigningInfo to use GetSigningInfoCall with ConsAddress field - Updated TestGetSigningInfos to use GetSigningInfosCall with Pagination field - Updated TestGetParams to use GetParamsCall with EmptyTuple - Replaced all UnpackIntoInterface calls with direct result type decoding - Tests now use fully type-safe generated types instead of reflection Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> cleanup bank test refactor tests fix tests fix: update factory to use abi.Method from CallArgs Update ExecuteContractCall and QueryContract to use callArgs.Method instead of callArgs directly to match the new GenerateContractCallArgs signature that expects abi.Method interface. Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> docs: update MIGRATION_GUIDE.md with status and troubleshooting - Added migration status table for all 10 precompiles - Updated decode examples to show recommended approach (direct Decode) - Added troubleshooting section with common issues and solutions: * s.precompile.Methods undefined * s.precompile.ABI undefined * Too many arguments in calls * Factory calls with CallArgs - Added references to Bech32 and Slashing migrations - Updated examples to be more comprehensive Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> fix: variable declarations in BeforeEach blocks - Use short declaration operator (:=) in BeforeEach blocks instead of separate var declarations - Fix DepositEvent and WithdrawalEvent to use pointers: &werc20.DepositEvent{} - Fix ERC20 return type field access (Field1 instead of Balance, Name, Symbol, Decimals) - Remove unused crypto import from test_events.go 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> fix gov tests fix gov events test fix gov test build remove unused methods fix build bank tests fix: migrate distribution and erc20 precompiles to go-abi Migrate precompile tests from go-ethereum to go-abi following the gov precompile pattern. Changes: - Distribution precompile: Regenerated ABI and updated test files to use new go-abi encoding pattern - ERC20 precompile: Updated test files to use new call struct pattern and method interface - Updated imports from ethereum/accounts/abi to yihuang/go-abi - Replaced precompile.Methods[] and Pack() with call structs and EncodeWithSelector() - Updated IsTransaction() calls to use method.GetMethodID() This enables the precompiles to build successfully with the new go-abi framework. 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Claude <[email protected]> fix: migrate slashing precompile to go-abi Migrate slashing precompile tests from go-ethereum to go-abi following the established pattern. Changes: - test_tx.go: Updated to use new call struct pattern (UnjailCall) instead of Methods[] and Pack() - test_query.go: Updated to use common.PageRequest and slashing.PageResponse types - Fixed method signatures to use pointer receivers for call structs - Removed unused imports (fmt, testutil) This enables the slashing precompile main test files to build successfully with the new go-abi framework. 🤖 Generated with [Claude Code](https://claude.ai/claude-code) Co-Authored-By: Claude <[email protected]> temp fix erc20 tests temp
1 parent f6d50b4 commit 6b07f11

File tree

127 files changed

+38531
-7099
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+38531
-7099
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### IMPROVEMENTS
88

99
- [\#758](https://github.com/cosmos/evm/pull/758) Cleanup precompiles abi.json.
10+
- [\#788](https://github.com/cosmos/evm/pull/788) Use go-abi to replace go-ethereum/accounts/abi usage in precompiles.
1011

1112
### FEATURES
1213

MIGRATION_GUIDE.md

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
# Precompile Test Migration Guide to go-abi
2+
3+
## Overview
4+
5+
This guide explains how to migrate precompile integration tests from the old go-ethereum ABI API to the new custom `go-abi` library (github.com/yihuang/go-abi).
6+
7+
## Background
8+
9+
The precompiles have been refactored to use a custom `go-abi` library instead of the standard `go-ethereum/accounts/abi` package. This change requires updates to the test code to work with the new API.
10+
11+
## Migration Status
12+
13+
| Precompile | Status | Notes |
14+
|------------|--------|-------|
15+
| **Bank** | ✅ Complete | Fully migrated, all tests working |
16+
| **Bech32** | ✅ Complete | Fully migrated, all tests working |
17+
| **Slashing** | 🟡 Partial | Query tests migrated, integration/tx tests need work |
18+
| **P256** | ✅ Complete | Already working, no changes needed |
19+
| **Distribution** | ❌ Pending | Complex test suite, needs migration |
20+
| **ERC20** | ❌ Pending | Many test files, needs migration |
21+
| **Gov** | ❌ Pending | Test files exist, needs migration |
22+
| **ICS20** | ❌ Pending | Complex IBC tests, needs migration |
23+
| **Staking** | ❌ Pending | Large test suite, needs migration |
24+
| **WERC20** | ❌ Pending | Event handling issues, needs migration |
25+
26+
## Key Differences
27+
28+
### Old API (go-ethereum/accounts/abi)
29+
- Used `abi.ABI.Pack()` to encode method calls
30+
- Used `UnpackIntoInterface()` and `Unpack()` to decode results
31+
- Relied on reflection for encoding/decoding
32+
- Tests accessed `precompile.ABI` field
33+
34+
### New API (go-abi)
35+
- Uses generated types with methods like `EncodeWithSelector()`
36+
- Uses generated `Decode()` methods on result types
37+
- No reflection, fully type-safe
38+
- No `ABI` field on precompile struct
39+
40+
## Migration Steps
41+
42+
### 1. Update ContractData Struct
43+
44+
**Before:**
45+
```go
46+
type ContractData struct {
47+
ownerPriv cryptotypes.PrivKey
48+
contractAddr common.Address
49+
contractABI abi.ABI
50+
precompileAddr common.Address
51+
precompileABI abi.ABI // ← Remove this
52+
}
53+
```
54+
55+
**After:**
56+
```go
57+
type ContractData struct {
58+
ownerPriv cryptotypes.PrivKey
59+
contractAddr common.Address
60+
contractABI abi.ABI
61+
precompileAddr common.Address
62+
// precompileABI removed
63+
}
64+
```
65+
66+
### 2. Remove precompileABI from initialization
67+
68+
**Before:**
69+
```go
70+
contractData = ContractData{
71+
ownerPriv: sender.Priv,
72+
precompileAddr: is.precompile.Address(),
73+
precompileABI: is.precompile.ABI, // ← Remove this
74+
contractAddr: bankCallerContractAddr,
75+
contractABI: bankCallerContract.ABI,
76+
}
77+
```
78+
79+
**After:**
80+
```go
81+
contractData = ContractData{
82+
ownerPriv: sender.Priv,
83+
precompileAddr: is.precompile.Address(),
84+
contractAddr: bankCallerContractAddr,
85+
contractABI: bankCallerContract.ABI,
86+
}
87+
```
88+
89+
### 3. Update getTxAndCallArgs Function
90+
91+
This function handles encoding for direct precompile calls. Replace manual encoding with `EncodeWithSelector()`:
92+
93+
```go
94+
func getTxAndCallArgs(
95+
callType int,
96+
contractData ContractData,
97+
methodName string,
98+
args ...interface{},
99+
) (evmtypes.EvmTxArgs, testutiltypes.CallArgs) {
100+
txArgs := evmtypes.EvmTxArgs{}
101+
callArgs := testutiltypes.CallArgs{}
102+
103+
switch callType {
104+
case directCall:
105+
var input []byte
106+
switch methodName {
107+
case bank.BalancesMethod:
108+
addr := args[0].(common.Address)
109+
call := bank.BalancesCall{Account: addr}
110+
input, _ = call.EncodeWithSelector() // Use built-in method
111+
case bank.TotalSupplyMethod:
112+
var call bank.TotalSupplyCall
113+
input, _ = call.EncodeWithSelector()
114+
case bank.SupplyOfMethod:
115+
addr := args[0].(common.Address)
116+
call := bank.SupplyOfCall{Erc20Address: addr}
117+
input, _ = call.EncodeWithSelector()
118+
default:
119+
panic(fmt.Sprintf("unknown method: %s", methodName))
120+
}
121+
txArgs.To = &contractData.precompileAddr
122+
txArgs.Input = input
123+
callArgs.ContractABI = abi.ABI{}
124+
case contractCall:
125+
txArgs.To = &contractData.contractAddr
126+
callArgs.ContractABI = contractData.contractABI
127+
}
128+
129+
callArgs.MethodName = methodName
130+
callArgs.Args = args
131+
return txArgs, callArgs
132+
}
133+
```
134+
135+
### 5. Replace UnpackIntoInterface Calls
136+
137+
**Before:**
138+
```go
139+
var balances []bank.Balance
140+
err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.Ret)
141+
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
142+
```
143+
144+
**After (Recommended):**
145+
```go
146+
var ret bank.BalancesReturn
147+
_, err = ret.Decode(ethRes.Ret)
148+
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
149+
Expect(ret.Balances).To(Equal(expectedBalances))
150+
```
151+
152+
**After (With Helper):**
153+
```go
154+
balances, err := decodeBalancesResult(ethRes.Ret)
155+
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
156+
```
157+
158+
### 6. Replace Unpack Calls
159+
160+
**Before:**
161+
```go
162+
out, err := is.precompile.Unpack(bank2.SupplyOfMethod, ethRes.Ret)
163+
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
164+
Expect(out[0].(*big.Int).String()).To(Equal(expectedValue.String()))
165+
```
166+
167+
**After (Recommended):**
168+
```go
169+
var ret bank.SupplyOfReturn
170+
_, err = ret.Decode(ethRes.Ret)
171+
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
172+
Expect(ret.TotalSupply.String()).To(Equal(expectedValue.String()))
173+
```
174+
175+
**After (With Helper):**
176+
```go
177+
supply, err := decodeSupplyOfResult(ethRes.Ret)
178+
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
179+
Expect(supply.String()).To(Equal(expectedValue.String()))
180+
```
181+
182+
### 7. Update Unit Tests (test_query.go)
183+
184+
**Before:**
185+
```go
186+
func (s *PrecompileTestSuite) TestBalances() {
187+
s.SetupTest()
188+
method := s.precompile.Methods[bank.BalancesMethod] // ← Methods field doesn't exist
189+
190+
// Test cases using method variable...
191+
bz, err := s.precompile.Balances(ctx, &method, args)
192+
var balances []bank.Balance
193+
err = s.precompile.UnpackIntoInterface(&balances, method.Name, bz)
194+
}
195+
```
196+
197+
**After:**
198+
```go
199+
func (s *PrecompileTestSuite) TestBalances() {
200+
s.SetupTest()
201+
202+
// Test cases use typed call structs directly
203+
call := &bank.BalancesCall{Account: addr}
204+
result, err := s.precompile.Balances(ctx, call)
205+
206+
balances := result.Balances // Direct access to result fields
207+
}
208+
```
209+
210+
## Generated Types
211+
212+
The `go-abi` tool generates these types for each method:
213+
214+
- `{MethodName}Call` - Input parameters struct
215+
- `{MethodName}Return` - Output results struct
216+
- `{MethodName}Selector` - Method selector constant
217+
- `{MethodName}ID` - Method ID constant
218+
- `{MethodName}Method` - Method name constant
219+
220+
## Example for Other Precompiles
221+
222+
For each precompile (bech32, distribution, erc20, gov, etc.), you need to:
223+
224+
1. Check the generated types in `{precompile}.abi.go`
225+
2. Create appropriate decode helper functions
226+
3. Update `getTxAndCallArgs` to handle the precompile's methods
227+
4. Replace all `UnpackIntoInterface` and `Unpack` calls
228+
5. Update unit tests to use typed call structs
229+
230+
## Verification
231+
232+
After migration, verify the tests build successfully:
233+
234+
```bash
235+
go build -tags=tests ./tests/integration/precompiles/{precompile_name}/...
236+
```
237+
238+
## Common Issues and Solutions
239+
240+
### Issue 1: `s.precompile.Methods` undefined
241+
**Error:** `s.precompile.Methods undefined (type *"github.com/cosmos/evm/precompiles/xxx".Precompile has no field or method Methods)`
242+
243+
**Solution:** The `Methods` field no longer exists. Use typed call structs directly:
244+
```go
245+
// Old:
246+
method := s.precompile.Methods[xxx.SomeMethod]
247+
result, err := s.precompile.SomeMethod(ctx, &method, args)
248+
249+
// New:
250+
var call xxx.SomeCall
251+
result, err := s.precompile.SomeMethod(ctx, &call)
252+
```
253+
254+
### Issue 2: `s.precompile.ABI` undefined
255+
**Error:** `s.precompile.ABI undefined (type *"github.com/cosmos/evm/precompiles/xxx".Precompile has no field or method ABI)`
256+
257+
**Solution:** The `ABI` field no longer exists. For direct precompile calls, encode with `EncodeWithSelector()`:
258+
```go
259+
// Old:
260+
input, err := s.precompile.Pack(xxx.SomeMethod, args...)
261+
s.precompile.UnpackIntoInterface(&out, xxx.SomeMethod, data)
262+
263+
// New:
264+
var call xxx.SomeCall{CreateArgs: args}
265+
input, _ := call.EncodeWithSelector()
266+
var ret xxx.SomeReturn
267+
_, err := ret.Decode(data)
268+
```
269+
270+
### Issue 3: Too many arguments in call
271+
**Error:** `too many arguments in call to s.precompile.SomeMethod`
272+
273+
**Solution:** The new API uses typed structs instead of variadic `[]interface{}`:
274+
```go
275+
// Old:
276+
result, err := s.precompile.SomeMethod(ctx, contract, stateDB, []interface{}{arg1, arg2})
277+
278+
// New:
279+
var call xxx.SomeCall{Arg1: value1, Arg2: value2}
280+
result, err := s.precompile.SomeMethod(ctx, call, stateDB, contract)
281+
```
282+
283+
### Issue 4: Factory calls with CallArgs
284+
**Error:** `cannot use callArgs as "github.com/yihuang/go-abi".Method value`
285+
286+
**Solution:** When calling through factory functions, set the `Method` field in `CallArgs`:
287+
```go
288+
// Old:
289+
callArgs := testutiltypes.CallArgs{
290+
ContractABI: contract.ABI,
291+
MethodName: "someMethod",
292+
Args: []interface{}{arg1, arg2},
293+
}
294+
295+
// New:
296+
callArgs := testutiltypes.CallArgs{
297+
ContractABI: contract.ABI,
298+
MethodName: "someMethod",
299+
Args: []interface{}{arg1, arg2},
300+
Method: &SomeCall{Arg1: arg1, Arg2: arg2}, // Add this
301+
}
302+
```
303+
304+
## References
305+
306+
- Bank precompile migration: `tests/integration/precompiles/bank/`
307+
- Bech32 precompile migration: `tests/integration/precompiles/bech32/`
308+
- Slashing precompile migration: `tests/integration/precompiles/slashing/test_query.go`
309+
- go-abi library: github.com/yihuang/go-abi
310+
- Generated types example: `precompiles/bank/bank.abi.go`

evmd/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ require (
241241
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
242242
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
243243
github.com/ulikunitz/xz v0.5.15 // indirect
244+
github.com/yihuang/go-abi v0.0.0-20251101094340-01f258e337df // indirect
244245
github.com/yusufpapurcu/wmi v1.2.4 // indirect
245246
github.com/zeebo/errs v1.4.0 // indirect
246247
github.com/zondax/golem v0.27.0 // indirect

0 commit comments

Comments
 (0)