Skip to content

Commit a3d8ef7

Browse files
committed
Merge remote-tracking branch 'origin/smooth-meadow' into go-abi
2 parents 69ffbb8 + 17c90ed commit a3d8ef7

File tree

4 files changed

+240
-228
lines changed

4 files changed

+240
-228
lines changed

MIGRATION_GUIDE.md

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ This guide explains how to migrate precompile integration tests from the old go-
88

99
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.
1010

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+
1126
## Key Differences
1227

1328
### Old API (go-ethereum/accounts/abi)
@@ -126,7 +141,15 @@ err = is.precompile.UnpackIntoInterface(&balances, bank2.BalancesMethod, ethRes.
126141
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
127142
```
128143

129-
**After:**
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):**
130153
```go
131154
balances, err := decodeBalancesResult(ethRes.Ret)
132155
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
@@ -141,7 +164,15 @@ Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
141164
Expect(out[0].(*big.Int).String()).To(Equal(expectedValue.String()))
142165
```
143166

144-
**After:**
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):**
145176
```go
146177
supply, err := decodeSupplyOfResult(ethRes.Ret)
147178
Expect(err).ToNot(HaveOccurred(), "failed to unpack balances")
@@ -204,8 +235,76 @@ After migration, verify the tests build successfully:
204235
go build -tags=tests ./tests/integration/precompiles/{precompile_name}/...
205236
```
206237

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+
207304
## References
208305

209306
- 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`
210309
- go-abi library: github.com/yihuang/go-abi
211310
- Generated types example: `precompiles/bank/bank.abi.go`

tests/integration/precompiles/bech32/test_bech32.go

Lines changed: 59 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,22 @@ func (s *PrecompileTestSuite) TestRun() {
7979
"fail - error during unpack",
8080
func() *vm.Contract {
8181
// only pass the method ID to the input
82-
contract.Input = s.precompile.Methods[bech32.HexToBech32Method].ID
82+
contract.Input = bech32.HexToBech32Selector[:]
8383
return contract
8484
},
8585
func([]byte) {},
8686
false,
87-
"abi: attempting to unmarshal an empty string while arguments are expected",
87+
"unexpected EOF",
8888
},
8989
{
9090
"fail - HexToBech32 method error",
9191
func() *vm.Contract {
92-
input, err := s.precompile.Pack(
93-
bech32.HexToBech32Method,
94-
s.keyring.GetAddr(0),
95-
"",
96-
)
97-
s.Require().NoError(err, "failed to pack input")
92+
call := bech32.HexToBech32Call{
93+
Addr: s.keyring.GetAddr(0),
94+
Prefix: "",
95+
}
96+
input, err := call.EncodeWithSelector()
97+
s.Require().NoError(err, "failed to encode input")
9898

9999
// only pass the method ID to the input
100100
contract.Input = input
@@ -107,22 +107,20 @@ func (s *PrecompileTestSuite) TestRun() {
107107
{
108108
"pass - hex to bech32 account (cosmos)",
109109
func() *vm.Contract {
110-
input, err := s.precompile.Pack(
111-
bech32.HexToBech32Method,
112-
s.keyring.GetAddr(0),
113-
"cosmos",
114-
)
115-
s.Require().NoError(err, "failed to pack input")
110+
call := bech32.HexToBech32Call{
111+
Addr: s.keyring.GetAddr(0),
112+
Prefix: "cosmos",
113+
}
114+
input, err := call.EncodeWithSelector()
115+
s.Require().NoError(err, "failed to encode input")
116116
contract.Input = input
117117
return contract
118118
},
119119
func(data []byte) {
120-
args, err := s.precompile.Unpack(bech32.HexToBech32Method, data)
120+
var ret bech32.HexToBech32Return
121+
_, err := ret.Decode(data)
121122
s.Require().NoError(err, "failed to unpack output")
122-
s.Require().Len(args, 1)
123-
addr, ok := args[0].(string)
124-
s.Require().True(ok)
125-
s.Require().Equal(s.keyring.GetAccAddr(0).String(), addr)
123+
s.Require().Equal(s.keyring.GetAccAddr(0).String(), ret.Bech32Address)
126124
},
127125
true,
128126
"",
@@ -133,79 +131,73 @@ func (s *PrecompileTestSuite) TestRun() {
133131
valAddrCodec := s.network.App.GetStakingKeeper().ValidatorAddressCodec()
134132
valAddrBz, err := valAddrCodec.StringToBytes(s.network.GetValidators()[0].GetOperator())
135133
s.Require().NoError(err, "failed to convert string to bytes")
136-
input, err := s.precompile.Pack(
137-
bech32.HexToBech32Method,
138-
common.BytesToAddress(valAddrBz),
139-
"cosmosvaloper",
140-
)
141-
s.Require().NoError(err, "failed to pack input")
134+
call := bech32.HexToBech32Call{
135+
Addr: common.BytesToAddress(valAddrBz),
136+
Prefix: "cosmosvaloper",
137+
}
138+
input, err := call.EncodeWithSelector()
139+
s.Require().NoError(err, "failed to encode input")
142140
contract.Input = input
143141
return contract
144142
},
145143
func(data []byte) {
146-
args, err := s.precompile.Unpack(bech32.HexToBech32Method, data)
144+
var ret bech32.HexToBech32Return
145+
_, err := ret.Decode(data)
147146
s.Require().NoError(err, "failed to unpack output")
148-
s.Require().Len(args, 1)
149-
addr, ok := args[0].(string)
150-
s.Require().True(ok)
151-
s.Require().Equal(s.network.GetValidators()[0].OperatorAddress, addr)
147+
s.Require().Equal(s.network.GetValidators()[0].OperatorAddress, ret.Bech32Address)
152148
},
153149
true,
154150
"",
155151
},
156152
{
157153
"pass - hex to bech32 consensus address (cosmosvalcons)",
158154
func() *vm.Contract {
159-
input, err := s.precompile.Pack(
160-
bech32.HexToBech32Method,
161-
s.keyring.GetAddr(0),
162-
"cosmosvalcons",
163-
)
164-
s.Require().NoError(err, "failed to pack input")
155+
call := bech32.HexToBech32Call{
156+
Addr: s.keyring.GetAddr(0),
157+
Prefix: "cosmosvalcons",
158+
}
159+
input, err := call.EncodeWithSelector()
160+
s.Require().NoError(err, "failed to encode input")
165161
contract.Input = input
166162
return contract
167163
},
168164
func(data []byte) {
169-
args, err := s.precompile.Unpack(bech32.HexToBech32Method, data)
165+
var ret bech32.HexToBech32Return
166+
_, err := ret.Decode(data)
170167
s.Require().NoError(err, "failed to unpack output")
171-
s.Require().Len(args, 1)
172-
addr, ok := args[0].(string)
173-
s.Require().True(ok)
174-
s.Require().Equal(sdk.ConsAddress(s.keyring.GetAddr(0).Bytes()).String(), addr)
168+
s.Require().Equal(sdk.ConsAddress(s.keyring.GetAddr(0).Bytes()).String(), ret.Bech32Address)
175169
},
176170
true,
177171
"",
178172
},
179173
{
180174
"pass - bech32 to hex account address",
181175
func() *vm.Contract {
182-
input, err := s.precompile.Pack(
183-
bech32.Bech32ToHexMethod,
184-
s.keyring.GetAccAddr(0).String(),
185-
)
186-
s.Require().NoError(err, "failed to pack input")
176+
call := bech32.Bech32ToHexCall{
177+
Bech32Address: s.keyring.GetAccAddr(0).String(),
178+
}
179+
input, err := call.EncodeWithSelector()
180+
s.Require().NoError(err, "failed to encode input")
187181
contract.Input = input
188182
return contract
189183
},
190184
func(data []byte) {
191-
args, err := s.precompile.Unpack(bech32.Bech32ToHexMethod, data)
185+
var ret bech32.Bech32ToHexReturn
186+
_, err := ret.Decode(data)
192187
s.Require().NoError(err, "failed to unpack output")
193-
s.Require().Len(args, 1)
194-
addr, ok := args[0].(common.Address)
195-
s.Require().True(ok)
196-
s.Require().Equal(s.keyring.GetAddr(0), addr)
188+
s.Require().Equal(s.keyring.GetAddr(0), ret.Addr)
197189
},
198190
true,
199191
"",
200192
},
201193
{
202194
"pass - bech32 to hex validator address",
203195
func() *vm.Contract {
204-
input, err := s.precompile.Pack(
205-
bech32.Bech32ToHexMethod,
206-
s.network.GetValidators()[0].OperatorAddress,
207-
)
208-
s.Require().NoError(err, "failed to pack input")
196+
call := bech32.Bech32ToHexCall{
197+
Bech32Address: s.network.GetValidators()[0].OperatorAddress,
198+
}
199+
input, err := call.EncodeWithSelector()
200+
s.Require().NoError(err, "failed to encode input")
209201
contract.Input = input
210202
return contract
211203
},
@@ -214,34 +206,30 @@ func (s *PrecompileTestSuite) TestRun() {
214206
valAddrBz, err := valAddrCodec.StringToBytes(s.network.GetValidators()[0].GetOperator())
215207
s.Require().NoError(err, "failed to convert string to bytes")
216208

217-
args, err := s.precompile.Unpack(bech32.Bech32ToHexMethod, data)
209+
var ret bech32.Bech32ToHexReturn
210+
_, err = ret.Decode(data)
218211
s.Require().NoError(err, "failed to unpack output")
219-
s.Require().Len(args, 1)
220-
addr, ok := args[0].(common.Address)
221-
s.Require().True(ok)
222-
s.Require().Equal(common.BytesToAddress(valAddrBz), addr)
212+
s.Require().Equal(common.BytesToAddress(valAddrBz), ret.Addr)
223213
},
224214
true,
225215
"",
226216
},
227217
{
228218
"pass - bech32 to hex consensus address",
229219
func() *vm.Contract {
230-
input, err := s.precompile.Pack(
231-
bech32.Bech32ToHexMethod,
232-
sdk.ConsAddress(s.keyring.GetAddr(0).Bytes()).String(),
233-
)
234-
s.Require().NoError(err, "failed to pack input")
220+
call := bech32.Bech32ToHexCall{
221+
Bech32Address: sdk.ConsAddress(s.keyring.GetAddr(0).Bytes()).String(),
222+
}
223+
input, err := call.EncodeWithSelector()
224+
s.Require().NoError(err, "failed to encode input")
235225
contract.Input = input
236226
return contract
237227
},
238228
func(data []byte) {
239-
args, err := s.precompile.Unpack(bech32.Bech32ToHexMethod, data)
229+
var ret bech32.Bech32ToHexReturn
230+
_, err := ret.Decode(data)
240231
s.Require().NoError(err, "failed to unpack output")
241-
s.Require().Len(args, 1)
242-
addr, ok := args[0].(common.Address)
243-
s.Require().True(ok)
244-
s.Require().Equal(s.keyring.GetAddr(0), addr)
232+
s.Require().Equal(s.keyring.GetAddr(0), ret.Addr)
245233
},
246234
true,
247235
"",

0 commit comments

Comments
 (0)