aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYondon Fu <yondon.fu@gmail.com>2017-10-12 22:58:53 +0800
committerYondon Fu <yondon.fu@gmail.com>2017-10-12 22:58:53 +0800
commita5330fe0c569b75cb8a524f60f7e8dc06498262b (patch)
tree48d19fd353e6ad443107a44234613a6d0c8563c7
parent8d8034fe59e40d606e6feea4c71b4798e7862e2f (diff)
downloadgo-tangerine-a5330fe0c569b75cb8a524f60f7e8dc06498262b.tar.gz
go-tangerine-a5330fe0c569b75cb8a524f60f7e8dc06498262b.tar.zst
go-tangerine-a5330fe0c569b75cb8a524f60f7e8dc06498262b.zip
accounts/abi: include fixed array size in offset for dynamic type
-rw-r--r--accounts/abi/abi_test.go50
-rw-r--r--accounts/abi/method.go13
2 files changed, 62 insertions, 1 deletions
diff --git a/accounts/abi/abi_test.go b/accounts/abi/abi_test.go
index a3aa9446e..5420eb19a 100644
--- a/accounts/abi/abi_test.go
+++ b/accounts/abi/abi_test.go
@@ -367,6 +367,56 @@ func TestInputVariableInputLength(t *testing.T) {
}
}
+func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
+ const definition = `[
+ { "type" : "function", "name" : "fixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] },
+ { "type" : "function", "name" : "fixedArrBytes", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] }
+ ]`
+
+ abi, err := JSON(strings.NewReader(definition))
+ if err != nil {
+ t.Error(err)
+ }
+
+ // test fixed array of uint256 and a string
+ arrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
+ strin := "hello world"
+ fixedArrStrPack, err := abi.Pack("fixedArrStr", strin, arrin)
+ if err != nil {
+ t.Error(err)
+ }
+
+ offset := make([]byte, 32)
+ offset[31] = 96
+ length := make([]byte, 32)
+ length[31] = byte(len(strin))
+ strvalue := common.RightPadBytes([]byte(strin), 32)
+ arrinvalue1 := common.LeftPadBytes(arrin[0].Bytes(), 32)
+ arrinvalue2 := common.LeftPadBytes(arrin[1].Bytes(), 32)
+ exp := append(offset, arrinvalue1...)
+ exp = append(exp, arrinvalue2...)
+ exp = append(exp, append(length, strvalue...)...)
+
+ // ignore first 4 bytes of the output. This is the function identifier
+ fixedArrStrPack = fixedArrStrPack[4:]
+ if !bytes.Equal(fixedArrStrPack, exp) {
+ t.Errorf("expected %x, got %x\n", exp, fixedArrStrPack)
+ }
+
+ // test fixed array of uint256 and a byte array
+ bytesin := []byte(strin)
+ fixedArrBytesPack, err := abi.Pack("fixedArrBytes", bytesin, arrin)
+ if err != nil {
+ t.Error(err)
+ }
+
+ // ignore first 4 bytes of the output. This is the function identifier
+ fixedArrBytesPack = fixedArrBytesPack[4:]
+ if !bytes.Equal(fixedArrBytesPack, exp) {
+ t.Errorf("expected %x, got %x\n", exp, fixedArrBytesPack)
+ }
+}
+
func TestDefaultFunctionParsing(t *testing.T) {
const definition = `[{ "name" : "balance" }]`
diff --git a/accounts/abi/method.go b/accounts/abi/method.go
index 62b3d2957..32077e8a6 100644
--- a/accounts/abi/method.go
+++ b/accounts/abi/method.go
@@ -48,6 +48,16 @@ func (method Method) pack(args ...interface{}) ([]byte, error) {
// output. This is used for strings and bytes types input.
var variableInput []byte
+ // input offset is the bytes offset for packed output
+ inputOffset := 0
+ for _, input := range method.Inputs {
+ if input.Type.IsArray {
+ inputOffset += (32 * input.Type.SliceSize)
+ } else {
+ inputOffset += 32
+ }
+ }
+
var ret []byte
for i, a := range args {
input := method.Inputs[i]
@@ -60,7 +70,8 @@ func (method Method) pack(args ...interface{}) ([]byte, error) {
// check for a slice type (string, bytes, slice)
if input.Type.requiresLengthPrefix() {
// calculate the offset
- offset := len(method.Inputs)*32 + len(variableInput)
+ offset := inputOffset + len(variableInput)
+
// set the offset
ret = append(ret, packNum(reflect.ValueOf(offset))...)
// Append the packed output to the variable input. The variable input