Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions accounts/abi/argument.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,9 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
// input offset is the bytes offset for packed output
inputOffset := 0
for _, abiArg := range abiArgs {
if abiArg.Type.T == ArrayTy {
inputOffset += 32 * abiArg.Type.Size
} else {
inputOffset += 32
}
inputOffset += getOffset(abiArg.Type)
}

var ret []byte
for i, a := range args {
input := abiArgs[i]
Expand All @@ -257,14 +254,15 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
if err != nil {
return nil, err
}
// check for a slice type (string, bytes, slice)
if input.Type.requiresLengthPrefix() {
// calculate the offset
offset := inputOffset + len(variableInput)
// check for dynamic types)=
if offsetRequired(input.Type) {
// set the offset
ret = append(ret, packNum(reflect.ValueOf(offset))...)
// Append the packed output to the variable input. The variable input
// will be appended at the end of the input.
ret = append(ret, packNum(reflect.ValueOf(inputOffset))...)

// calculate next offset
inputOffset += len(packed)

// append to variable input
variableInput = append(variableInput, packed...)
} else {
// append the packed value to the input
Expand Down
77 changes: 52 additions & 25 deletions accounts/abi/pack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func TestPack(t *testing.T) {
{
"uint8[]",
[]uint8{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"uint16",
Expand All @@ -52,7 +52,7 @@ func TestPack(t *testing.T) {
{
"uint16[]",
[]uint16{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"uint32",
Expand All @@ -62,7 +62,7 @@ func TestPack(t *testing.T) {
{
"uint32[]",
[]uint32{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"uint64",
Expand All @@ -72,7 +72,7 @@ func TestPack(t *testing.T) {
{
"uint64[]",
[]uint64{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"uint256",
Expand All @@ -82,7 +82,7 @@ func TestPack(t *testing.T) {
{
"uint256[]",
[]*big.Int{big.NewInt(1), big.NewInt(2)},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"int8",
Expand All @@ -92,7 +92,7 @@ func TestPack(t *testing.T) {
{
"int8[]",
[]int8{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"int16",
Expand All @@ -102,7 +102,7 @@ func TestPack(t *testing.T) {
{
"int16[]",
[]int16{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"int32",
Expand All @@ -112,7 +112,7 @@ func TestPack(t *testing.T) {
{
"int32[]",
[]int32{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"int64",
Expand All @@ -122,7 +122,7 @@ func TestPack(t *testing.T) {
{
"int64[]",
[]int64{1, 2},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"int256",
Expand All @@ -132,7 +132,7 @@ func TestPack(t *testing.T) {
{
"int256[]",
[]*big.Int{big.NewInt(1), big.NewInt(2)},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"),
},
{
"bytes1",
Expand Down Expand Up @@ -308,18 +308,12 @@ func TestPack(t *testing.T) {
//web3.eth.abi.encodeParameter('address[]', ['0x0100000000000000000000000000000000000000','0x0200000000000000000000000000000000000000']);
"address[]",
[]common.Address{{1}, {2}},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020" +
"0000000000000000000000000000000000000000000000000000000000000002" +
"0000000000000000000000000100000000000000000000000000000000000000" +
"0000000000000000000000000200000000000000000000000000000000000000"),
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000200000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000"),
},
{
"bytes32[]",
[]common.Hash{{1}, {2}},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020" + //offset: 32
"0000000000000000000000000000000000000000000000000000000000000002" + //len: 2
"0100000000000000000000000000000000000000000000000000000000000000" + // 1
"0200000000000000000000000000000000000000000000000000000000000000"), // 2
common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000201000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000"),
},
{
"function",
Expand All @@ -329,31 +323,37 @@ func TestPack(t *testing.T) {
{
"string",
"foobar",
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020" + // offset: 32
"0000000000000000000000000000000000000000000000000000000000000006" + // len: 6
"666f6f6261720000000000000000000000000000000000000000000000000000"), // "foobar"
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000006666f6f6261720000000000000000000000000000000000000000000000000000"),
},
{
"string[]",
[]string{"hello", "foobar"},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020" + // offset array 32
"0000000000000000000000000000000000000000000000000000000000000002" + // len(array) = 2
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002" + // len(array) = 2
"0000000000000000000000000000000000000000000000000000000000000040" + // offset 64 to i=0
"0000000000000000000000000000000000000000000000000000000000000080" + // offset 128 to i=1
"0000000000000000000000000000000000000000000000000000000000000005" + // len(str[0]) = 5
"68656c6c6f000000000000000000000000000000000000000000000000000000" + // str[0]
"0000000000000000000000000000000000000000000000000000000000000006" + // len(str[1]) = 6
"666f6f6261720000000000000000000000000000000000000000000000000000"), // str[1]
},
{
"string[2]",
[]string{"hello", "foobar"},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040" + // offset to hello
"0000000000000000000000000000000000000000000000000000000000000080" + // offset to foobar
"0000000000000000000000000000000000000000000000000000000000000005" + // length of hello
"68656c6c6f000000000000000000000000000000000000000000000000000000" + // encoded foobar
"0000000000000000000000000000000000000000000000000000000000000006" + // length of foobar
"666f6f6261720000000000000000000000000000000000000000000000000000"), // encoded foobar
},
{

//web3.eth.abi.encodeParameter('bytes32[][]', [['0x0100000000000000000000000000000000000000000000000000000000000000',
// '0x0200000000000000000000000000000000000000000000000000000000000000'],['0x0300000000000000000000000000000000000000000000000000000000000000',
// '0x0400000000000000000000000000000000000000000000000000000000000000','0x0500000000000000000000000000000000000000000000000000000000000000']]);
"bytes32[][]",
[][]common.Hash{{{1}, {2}}, {{3}, {4}, {5}}},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020" + // offset array 32
"0000000000000000000000000000000000000000000000000000000000000002" + // len(array) = 2
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000002" + // len(array) = 2
"0000000000000000000000000000000000000000000000000000000000000040" + // offset 64 to i=0
"00000000000000000000000000000000000000000000000000000000000000a0" + // offset 160 to i=1
"0000000000000000000000000000000000000000000000000000000000000002" + // len(array[0]) = 2
Expand All @@ -365,6 +365,33 @@ func TestPack(t *testing.T) {
"0500000000000000000000000000000000000000000000000000000000000000"), // array[2]

},

{
"bytes32[][2]",
[][]common.Hash{{{1}, {2}}, {{3}, {4}, {5}}},
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040" + // offset 64 to i=0
"00000000000000000000000000000000000000000000000000000000000000a0" + // offset 160 to i=1
"0000000000000000000000000000000000000000000000000000000000000002" + // len(array[0]) = 2
"0100000000000000000000000000000000000000000000000000000000000000" + // array[0]
"0200000000000000000000000000000000000000000000000000000000000000" + // array[1]
"0000000000000000000000000000000000000000000000000000000000000003" + // len(array[1]) = 3
"0300000000000000000000000000000000000000000000000000000000000000" + // array[0]
"0400000000000000000000000000000000000000000000000000000000000000" + // array[1]
"0500000000000000000000000000000000000000000000000000000000000000"), // array[2]

},

{
"bytes32[3][2]",
[][]common.Hash{{{1}, {2}, {3}}, {{3}, {4}, {5}}},
common.Hex2Bytes("0100000000000000000000000000000000000000000000000000000000000000" + // array[0]
"0200000000000000000000000000000000000000000000000000000000000000" + // array[1]
"0300000000000000000000000000000000000000000000000000000000000000" + // array[2]
"0300000000000000000000000000000000000000000000000000000000000000" + // array[0]
"0400000000000000000000000000000000000000000000000000000000000000" + // array[1]
"0500000000000000000000000000000000000000000000000000000000000000"), // array[2]

},
} {
typ, err := NewType(test.typ)
if err != nil {
Expand Down
60 changes: 51 additions & 9 deletions accounts/abi/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,27 +183,69 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
return nil, err
}

if t.T == SliceTy || t.T == ArrayTy {
var packed []byte
switch t.T {
case SliceTy, ArrayTy:
var ret []byte

if t.requiresLengthPrefix() {
// append length
ret = append(ret, packNum(reflect.ValueOf(v.Len()))...)
}

// calculate offset if any
offset := 0
offsetReq := offsetRequired(*t.Elem)
if offsetReq {
offset = getOffset(*t.Elem) * v.Len()
}

var tail []byte
for i := 0; i < v.Len(); i++ {
val, err := t.Elem.pack(v.Index(i))
if err != nil {
return nil, err
}
packed = append(packed, val...)
}
if t.T == SliceTy {
return packBytesSlice(packed, v.Len()), nil
} else if t.T == ArrayTy {
return packed, nil

if !offsetReq {
ret = append(ret, val...)
continue
}

ret = append(ret, packNum(reflect.ValueOf(offset))...)
offset += len(val)
tail = append(tail, val...)
}

return append(ret, tail...), nil
default:
return packElement(t, v), nil
}
return packElement(t, v), nil
}

// requireLengthPrefix returns whether the type requires any sort of length
// prefixing.
func (t Type) requiresLengthPrefix() bool {
return t.T == StringTy || t.T == BytesTy || t.T == SliceTy
}

// offsetRequired returns true if the type is considered dynamic
func offsetRequired(t Type) bool {
// dynamic types
// array is also a dynamic type if the array type is dynamic
if t.T == StringTy || t.T == BytesTy || t.T == SliceTy || (t.T == ArrayTy && offsetRequired(*t.Elem)) {
return true
}

return false
}

// getOffset returns the offset to be added for t
func getOffset(t Type) int {
// if it is an array and there are no dynamic types
// then the array is static type
if t.T == ArrayTy && !offsetRequired(*t.Elem) {
return 32 * t.Size
}

return 32
}