Boilertalk / Web3.swift

A pure swift Ethereum Web3 library
MIT License
636 stars 187 forks source link

Dynamic array's encode/decode issue #122

Open Crypto-Doby opened 2 years ago

Crypto-Doby commented 2 years ago

now the dynamic array's encoding logic is to encode every item, then concat the hex string follow the length encoded hex.:

public func abiEncodeDynamic() -> String? {
    // get values
    let values = self.compactMap { value -> String? in
        return value.abiEncode(dynamic: true)
    }
    // number of elements in the array, padded left
    let length = String(values.count, radix: 16).paddingLeft(toLength: 64, withPad: "0")
    // values, joined with no separator
    return length + values.joined()
}

but follw the document: https://docs.soliditylang.org/en/v0.8.13/abi-spec.html#formal-specification-of-the-encoding it seems that the dynamic array's encoded data should have extra bytes between length hex and item's hex, to represent the dynamic item's data location.

for example: I want to encode a dynamic array of 4 datas:

let testArr = [
    Data.init(hex: "0x01"),
    Data.init(hex: "0x02"),
    Data.init(hex: "0x03"),
    Data.init(hex: "0x04")
]

let testData = testArr.abiEncode(dynamic: true)

the testData now is this:

0000000000000000000000000000000000000000000000000000000000000004

0000000000000000000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000001
0200000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000001
0300000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000001
0400000000000000000000000000000000000000000000000000000000000000

it seems should add the extra bytes like this:

0000000000000000000000000000000000000000000000000000000000000004

0000000000000000000000000000000000000000000000000000000000000080
00000000000000000000000000000000000000000000000000000000000000c0
0000000000000000000000000000000000000000000000000000000000000100
0000000000000000000000000000000000000000000000000000000000000140

0000000000000000000000000000000000000000000000000000000000000001
0100000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000001
0200000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000001
0300000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000001
0400000000000000000000000000000000000000000000000000000000000000

I was trying to send a eth_call with dynamic array's encoded data but got error. after add the extra bytes. the call is success.

is there any wrong usage of me or any missunderstanding?

koraykoska commented 2 years ago

@Crypto-Doby Can you fix this method and make a PR? Please also include the official test cases from Solidity's docs.

koraykoska commented 1 year ago

@Crypto-Doby Please check #135

That's just decoding for now. But after making a few tests I will recreate the encoding API as well.

rkingxbank commented 9 months ago

This issue has not been fixed