Skip to content

Commit fda9778

Browse files
authored
fix(evm)!: correct EIP55 addr encoding (#2187)
* fix: add extra case of converting straight from bytes to string * fix: eip55 encoding * Update CHANGELOG.md
1 parent 5d1f87b commit fda9778

File tree

3 files changed

+90
-60
lines changed

3 files changed

+90
-60
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ needed to include double quotes around the hexadecimal string.
9393
- [#2180](https://github.com/NibiruChain/nibiru/pull/2180) - fix(evm): apply gas consumption across the entire EVM codebase at `CallContractWithInput`
9494
- [#2183](https://github.com/NibiruChain/nibiru/pull/2183) - fix(evm): bank keeper extension gas meter type
9595
- [#2184](https://github.com/NibiruChain/nibiru/pull/2184) - test(evm): e2e tests configuration enhancements
96-
-
96+
- [#2187](https://github.com/NibiruChain/nibiru/pull/2187) - fix(evm): fix eip55 address encoding
97+
9798
#### Nibiru EVM | Before Audit 2 - 2024-12-06
9899

99100
The codebase went through a third-party [Code4rena

eth/eip55.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func NewEIP55AddrFromStr(input string) (EIP55Addr, error) {
3636
// Marshal implements the gogo proto custom type interface.
3737
// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md
3838
func (h EIP55Addr) Marshal() ([]byte, error) {
39-
return []byte(h.Address.Hex()), nil
39+
return h.Bytes(), nil
4040
}
4141

4242
// MarshalJSON returns the [EIP55Addr] as JSON bytes.
@@ -51,18 +51,15 @@ func (h EIP55Addr) MarshalJSON() ([]byte, error) {
5151
// Implements the gogo proto custom type interface.
5252
// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md
5353
func (h *EIP55Addr) MarshalTo(data []byte) (n int, err error) {
54-
copy(data, []byte(h.Address.Hex()))
54+
copy(data, h.Bytes())
5555
return h.Size(), nil
5656
}
5757

5858
// Unmarshal implements the gogo proto custom type interface.
5959
// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md
6060
func (h *EIP55Addr) Unmarshal(data []byte) error {
61-
addr, err := NewEIP55AddrFromStr(string(data))
62-
if err != nil {
63-
return err
64-
}
65-
*h = addr
61+
addr := gethcommon.BytesToAddress(data)
62+
*h = EIP55Addr{Address: addr}
6663
return nil
6764
}
6865

@@ -71,9 +68,7 @@ func (h *EIP55Addr) Unmarshal(data []byte) error {
7168
func (h *EIP55Addr) UnmarshalJSON(bz []byte) error {
7269
var addrStr string
7370
if err := json.Unmarshal(bz, &addrStr); err != nil {
74-
return fmt.Errorf(
75-
"EIP55AddrError: UnmarhsalJSON had invalid input %s: %w", bz, err,
76-
)
71+
return err
7772
}
7873
addr, err := NewEIP55AddrFromStr(addrStr)
7974
if err != nil {
@@ -86,5 +81,5 @@ func (h *EIP55Addr) UnmarshalJSON(bz []byte) error {
8681
// Size implements the gogo proto custom type interface.
8782
// Ref: https://github.com/cosmos/gogoproto/blob/v1.5.0/custom_types.md
8883
func (h EIP55Addr) Size() int {
89-
return len([]byte(h.Address.Hex()))
84+
return len(h.Bytes())
9085
}

eth/eip55_test.go

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package eth_test
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"strconv"
6-
"strings"
77
"testing"
88

99
gethcommon "github.com/ethereum/go-ethereum/common"
@@ -12,25 +12,19 @@ import (
1212
"github.com/NibiruChain/nibiru/v2/eth"
1313
)
1414

15-
// MustNewEIP55AddrFromStr is the same as [NewEIP55AddrFromStr], except it panics
15+
// mustNewEIP55AddrFromStr is the same as [NewEIP55AddrFromStr], except it panics
1616
// when there's an error.
17-
func MustNewEIP55AddrFromStr(input string) eth.EIP55Addr {
17+
func mustNewEIP55AddrFromStr(input string) eth.EIP55Addr {
1818
addr, err := eth.NewEIP55AddrFromStr(input)
1919
if err != nil {
2020
panic(err)
2121
}
2222
return addr
2323
}
2424

25-
var threeValidAddrs []eth.EIP55Addr = []eth.EIP55Addr{
26-
MustNewEIP55AddrFromStr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"),
27-
MustNewEIP55AddrFromStr("0xAe967917c465db8578ca9024c205720b1a3651A9"),
28-
MustNewEIP55AddrFromStr("0x1111111111111111111112222222222223333323"),
29-
}
30-
3125
func (s *EIP55AddrSuite) TestEquivalence() {
3226
expectedGethAddr := gethcommon.HexToAddress("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")
33-
expectedEIP55Addr := MustNewEIP55AddrFromStr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")
27+
expectedEIP55Addr := mustNewEIP55AddrFromStr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")
3428

3529
equivalentAddrs := []string{
3630
"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed",
@@ -110,54 +104,95 @@ func (s *EIP55AddrSuite) TestNewEIP55Addr() {
110104
}
111105
}
112106

113-
func (s *EIP55AddrSuite) TestProtobufEncoding() {
107+
func (s *EIP55AddrSuite) TestJsonEncoding() {
114108
for tcIdx, tc := range []struct {
115109
input eth.EIP55Addr
116-
expectedJson string
110+
expectedJson json.RawMessage
117111
wantErr string
118112
}{
119113
{
120-
input: threeValidAddrs[0],
121-
expectedJson: `"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"`,
114+
input: mustNewEIP55AddrFromStr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"),
115+
expectedJson: []byte("\"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed\""),
122116
},
123117
{
124-
input: threeValidAddrs[1],
125-
expectedJson: `"0xAe967917c465db8578ca9024c205720b1a3651A9"`,
118+
input: mustNewEIP55AddrFromStr("0xAe967917c465db8578ca9024c205720b1a3651A9"),
119+
expectedJson: []byte("\"0xAe967917c465db8578ca9024c205720b1a3651A9\""),
126120
},
127121
{
128-
input: threeValidAddrs[2],
129-
expectedJson: `"0x1111111111111111111112222222222223333323"`,
122+
input: mustNewEIP55AddrFromStr("0x1111111111111111111112222222222223333323"),
123+
expectedJson: []byte("\"0x1111111111111111111112222222222223333323\""),
130124
},
131125
} {
132126
s.Run(strconv.Itoa(tcIdx), func() {
133-
givenMut := tc.input
134-
jsonBz, err := givenMut.MarshalJSON()
135-
s.NoError(err)
136-
s.Equal(tc.expectedJson, string(jsonBz))
127+
jsonBz, err := tc.input.MarshalJSON()
128+
s.Require().NoError(err)
129+
s.Require().EqualValues(tc.expectedJson, jsonBz)
137130

138131
eip55Addr := new(eth.EIP55Addr)
139-
s.NoError(eip55Addr.UnmarshalJSON(jsonBz))
140-
s.Equal(givenMut, tc.input,
141-
"Given -> MarshalJSON -> UnmarshalJSON returns a different value than the given when it should be an identity operation (no-op). test case #%d", tcIdx)
132+
s.Require().NoError(eip55Addr.UnmarshalJSON(jsonBz))
133+
s.Require().EqualValues(tc.input, *eip55Addr)
134+
})
135+
}
136+
}
142137

138+
func (s *EIP55AddrSuite) TestProtobufEncoding() {
139+
for tcIdx, tc := range []struct {
140+
input eth.EIP55Addr
141+
expectedProtoBz []byte
142+
wantErr string
143+
}{
144+
{
145+
input: mustNewEIP55AddrFromStr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"),
146+
expectedProtoBz: []byte{90, 174, 182, 5, 63, 62, 148, 201, 185, 160, 159, 51, 102, 148, 53, 231, 239, 27, 234, 237},
147+
},
148+
{
149+
input: mustNewEIP55AddrFromStr("0xAe967917c465db8578ca9024c205720b1a3651A9"),
150+
expectedProtoBz: []byte{174, 150, 121, 23, 196, 101, 219, 133, 120, 202, 144, 36, 194, 5, 114, 11, 26, 54, 81, 169},
151+
},
152+
{
153+
input: mustNewEIP55AddrFromStr("0x1111111111111111111112222222222223333323"),
154+
expectedProtoBz: []byte{17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 34, 34, 34, 34, 34, 35, 51, 51, 35},
155+
},
156+
} {
157+
s.Run(strconv.Itoa(tcIdx), func() {
143158
bz, err := tc.input.Marshal()
144-
s.NoError(err)
145-
s.Equal(strings.Trim(tc.expectedJson, `"`), string(bz),
146-
"Marshaling to bytes gives different value than the test case specifies. test case #%d", tcIdx)
159+
s.Require().NoError(err)
160+
s.Require().EqualValues(tc.expectedProtoBz, bz)
147161

148-
err = eip55Addr.Unmarshal(bz)
149-
s.NoError(err)
150-
s.Equal(tc.input.Address, eip55Addr.Address,
151-
"Given -> Marshal -> Unmarshal returns a different value than the given when it should be an identity operation (no-op). test case #%d", tcIdx)
162+
eip55Addr := new(eth.EIP55Addr)
163+
s.Require().NoError(eip55Addr.Unmarshal(bz))
164+
s.Require().Equal(tc.input.Address, eip55Addr.Address)
165+
})
166+
}
167+
}
152168

153-
s.Equal(len([]byte(tc.input.Hex())), tc.input.Size())
154-
s.Equal(len(tc.input.Hex()), tc.input.Size())
169+
func (s *EIP55AddrSuite) TestSize() {
170+
for idx, tc := range []struct {
171+
input eth.EIP55Addr
172+
expectedSize int
173+
wantErr string
174+
}{
175+
{
176+
input: mustNewEIP55AddrFromStr("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"),
177+
expectedSize: 20,
178+
},
179+
{
180+
input: mustNewEIP55AddrFromStr("0xAe967917c465db8578ca9024c205720b1a3651A9"),
181+
expectedSize: 20,
182+
},
183+
{
184+
input: mustNewEIP55AddrFromStr("0x1111111111111111111112222222222223333323"),
185+
expectedSize: 20,
186+
},
187+
} {
188+
s.Run(strconv.Itoa(idx), func() {
189+
s.Require().EqualValues(tc.expectedSize, tc.input.Size())
155190
})
156191
}
157192
}
158193

159194
// showcases how geth checks for valid hex addresses and treats invalid inputs
160-
func (s *EIP55AddrSuite) TestIsEIP55Address() {
195+
func (s *EIP55AddrSuite) TestHexAddress() {
161196
s.True(gethcommon.IsHexAddress("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"))
162197
s.True(gethcommon.IsHexAddress("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAED"))
163198
s.False(gethcommon.IsHexAddress("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed1234"))
@@ -179,21 +214,20 @@ func TestEIP55AddrSuite(t *testing.T) {
179214

180215
func (s *EIP55AddrSuite) TestStringEncoding() {
181216
addrHex := "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
182-
addr := new(eth.EIP55Addr)
183-
err := addr.Unmarshal([]byte(addrHex))
184-
s.NoError(err)
185-
s.Equal(addrHex, addr.Address.Hex())
217+
addr, err := eth.NewEIP55AddrFromStr(addrHex)
218+
s.Require().NoError(err)
219+
s.Require().Equal(addrHex, addr.Address.Hex())
186220

187-
addrBytes, err := addr.Marshal()
188-
s.NoError(err)
189-
s.Equal(addrHex, string(addrBytes))
221+
addrBz, err := addr.Marshal()
222+
s.Require().NoError(err)
223+
s.Require().EqualValues(addr.Bytes(), addrBz)
190224

191225
bz, err := addr.MarshalJSON()
192-
s.NoError(err)
193-
s.Equal(fmt.Sprintf(`"%s"`, addrHex), string(bz))
226+
s.Require().NoError(err)
227+
s.Require().Equal(fmt.Sprintf(`"%s"`, addrHex), string(bz))
194228

195-
addrb := new(eth.EIP55Addr)
196-
err = addrb.UnmarshalJSON([]byte(fmt.Sprintf(`"%s"`, addrHex)))
197-
s.NoError(err)
198-
s.EqualValues(addrb, addr)
229+
newAddr := new(eth.EIP55Addr)
230+
err = newAddr.UnmarshalJSON(bz)
231+
s.Require().NoError(err)
232+
s.Require().EqualValues(addrHex, newAddr.Hex())
199233
}

0 commit comments

Comments
 (0)