abi.gno
1.91 Kb · 81 lines
1package types
2
3import "encoding/binary"
4
5// wrapABIEncode wraps an already-encoded dynamic ABI payload with the
6// 32-byte offset header that Solidity prepends when a single dynamic value is
7// returned at the top level.
8func wrapABIEncode(encoded []byte) []byte {
9 out := make([]byte, 0, 32+len(encoded))
10 out = append(out, u64ToH256(32)...)
11
12 return append(out, encoded...)
13}
14
15func encodeABIPacketArray(packets []Packet) ([]byte, error) {
16 out := make([]byte, 0)
17 out = append(out, u64ToH256(uint64(len(packets)))...)
18
19 headLen := len(packets) * 32
20 tail := make([]byte, 0)
21
22 for _, packet := range packets {
23 encoded, err := packet.EncodeABI()
24 if err != nil {
25 return nil, err
26 }
27
28 out = append(out, u64ToH256(uint64(headLen+len(tail)))...)
29 tail = append(tail, encoded...)
30 }
31
32 return append(out, tail...), nil
33}
34
35func encodeABIBytesArray(items [][]byte) []byte {
36 out := make([]byte, 0)
37 out = append(out, u64ToH256(uint64(len(items)))...)
38
39 headLen := len(items) * 32
40 tail := make([]byte, 0)
41
42 for _, item := range items {
43 encoded := encodeABIBytes(item)
44
45 out = append(out, u64ToH256(uint64(headLen+len(tail)))...)
46 tail = append(tail, encoded...)
47 }
48
49 return append(out, tail...)
50}
51
52// encodeABIBytes encodes bz as a Solidity `bytes` value: a 32-byte length word
53// followed by the data right-padded to a 32-byte boundary.
54func encodeABIBytes(bz []byte) []byte {
55 pad := (32 - len(bz)%32) % 32
56 out := make([]byte, 0, 32+len(bz)+pad)
57 out = append(out, u64ToH256(uint64(len(bz)))...)
58
59 out = append(out, bz...)
60 if pad > 0 {
61 out = append(out, make([]byte, pad)...)
62 }
63
64 return out
65}
66
67// u32ToH256 left-pads a uint32 into a 32-byte big-endian word.
68func u32ToH256(n uint32) []byte {
69 bz := [32]byte{}
70 binary.BigEndian.PutUint32(bz[28:], n)
71
72 return bz[:]
73}
74
75// u64ToH256 left-pads a uint64 into a 32-byte big-endian word.
76func u64ToH256(n uint64) []byte {
77 bz := [32]byte{}
78 binary.BigEndian.PutUint64(bz[24:], n)
79
80 return bz[:]
81}