Skip to content

Commit

Permalink
feat: abi decoding compatibility with cast calldata
Browse files Browse the repository at this point in the history
  • Loading branch information
IdrisHanafi committed Dec 8, 2023
1 parent 67ba980 commit 560f741
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 19 deletions.
39 changes: 30 additions & 9 deletions cmd/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ var ABICmd = &cobra.Command{
return err
}
for _, meth := range abi.Methods {
fmt.Printf("Selector:%s\tSignature:%s\n", hex.EncodeToString(meth.ID), meth)
fmt.Printf("Selector:%s\tSignature:%s%s\n", hex.EncodeToString(meth.ID), meth.Sig, getReturnSignature(meth.Outputs))
}
if *inputData != "" {
id, callData, err := parseContractInputData(*inputData)
fmt.Printf("id: %x, %x\n", id, callData)
if err != nil {
return err
}
Expand All @@ -61,6 +62,18 @@ var ABICmd = &cobra.Command{
fmt.Println("Input data:")
prettyInput, _ := json.MarshalIndent(inputVals, "", " ")
fmt.Println(string(prettyInput))

unpackedCallData, err := meth.Inputs.UnpackValues(callData)
if err != nil {
return err
}

fmt.Println("Signature and Input")
fmt.Printf("%s%s", meth.Sig, getReturnSignature(meth.Outputs))
for _, unpackedCallDataArg := range unpackedCallData {
fmt.Printf(" %v", unpackedCallDataArg)
}
fmt.Println()
}
return nil
},
Expand All @@ -77,19 +90,18 @@ func init() {

func parseContractInputData(data string) ([]byte, []byte, error) {
// "0x11223344"
if len(data) < 10 {
selectorLength := 8
data = strings.TrimPrefix(data, "0x")
if len(data) < selectorLength {
return nil, nil, fmt.Errorf("the input %s is too short for a function call. It should start with 0x and needs at least 4 bytes for a function selector", data)
}
if data[0:2] != "0x" {
return nil, nil, fmt.Errorf("the input data must start with 0x")
}
// drop the 0x and select the next bytes to represent the selector
stringId := data[2:10]
rawId, err := hex.DecodeString(stringId)

selectorId := data[:selectorLength]
rawId, err := hex.DecodeString(selectorId)
if err != nil {
return nil, nil, err
}
rawCallData, err := hex.DecodeString(data[10:])
rawCallData, err := hex.DecodeString(data[selectorLength:])
if err != nil {
return nil, nil, err
}
Expand All @@ -108,3 +120,12 @@ func getInputData(cmd *cobra.Command, args []string) ([]byte, error) {

return io.ReadAll(os.Stdin)
}

func getReturnSignature(funcReturns gethabi.Arguments) string {
returnSig := ""
for _, ret := range funcReturns {
returnSig += fmt.Sprintf("(%s)", ret.Type)
}

return returnSig
}
29 changes: 24 additions & 5 deletions cmd/abi/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,35 @@ $ polycli abi --file contract.abi
This would output some information that would let us know the various function selectors for this contract.

```bash
Selector:19d8ac61 Signature:function lastTimestamp() view returns(uint64)
Selector:a066215c Signature:function setVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) returns()
Selector:715018a6 Signature:function renounceOwnership() returns()
Selector:cfa8ed47 Signature:function trustedSequencer() view returns(address)
$ polycli abi --file ./bindings/tester/LoadTester.abi
Selector:3430ec06 Signature:dumpster(uint256)(bytes)
Selector:a271b721 Signature:loopBlockHashUntilLimit()(uint256)
Selector:0ba8a73b Signature:testADD(uint256)(uint256)
Selector:fde7721c Signature:testMULMOD(uint256)(uint256)
Selector:63138d4f Signature:testSHA256(bytes)(bytes32)
...
```

If we want to break down input data we can run something like this.

```bash
$ polycli abi --data 0x3c158267000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063ed0f8f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006eec03843b9aca0082520894d2f852ec7b4e457f6e7ff8b243c49ff5692926ea87038d7ea4c68000808204c58080642dfe2cca094f2419aad1322ec68e3b37974bd9c918e0686b9bbf02b8bd1145622a3dd64202da71549c010494fd1475d3bf232aa9028204a872fd2e531abfd31c000000000000000000000000000000000000 < contract.abi
$ polycli abi --data 0xd53ff3fd0000000000000000000000000000000000000000000000000000000000000063 < ./bindings/tester/LoadTester.abi
Selector:a60a1087 Signature:testCHAINID(uint256)(uint256)
Selector:b7b86207 Signature:testCODESIZE(uint256)(uint256)
...
Selector:d53ff3fd Signature:testSUB(uint256)(uint256)
Selector:962e4dc2 Signature:testECMul(bytes)(bytes)
Selector:de97a363 Signature:testEXP(uint256)(uint256)
Selector:9cce7cf9 Signature:testIdentity(bytes)(bytes)
Selector:19b621d6 Signature:testSHA3(uint256)(uint256)
...
id: d53ff3fd, 0000000000000000000000000000000000000000000000000000000000000063
Input data:
{
"x": 99
}
Signature and Input
testSUB(uint256)(uint256) 99
```

In addition to the function selector data, we'll also get a breakdown of input data:
Expand Down
29 changes: 24 additions & 5 deletions doc/polycli_abi.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,35 @@ $ polycli abi --file contract.abi
This would output some information that would let us know the various function selectors for this contract.

```bash
Selector:19d8ac61 Signature:function lastTimestamp() view returns(uint64)
Selector:a066215c Signature:function setVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget) returns()
Selector:715018a6 Signature:function renounceOwnership() returns()
Selector:cfa8ed47 Signature:function trustedSequencer() view returns(address)
$ polycli abi --file ./bindings/tester/LoadTester.abi
Selector:3430ec06 Signature:dumpster(uint256)(bytes)
Selector:a271b721 Signature:loopBlockHashUntilLimit()(uint256)
Selector:0ba8a73b Signature:testADD(uint256)(uint256)
Selector:fde7721c Signature:testMULMOD(uint256)(uint256)
Selector:63138d4f Signature:testSHA256(bytes)(bytes32)
...
```

If we want to break down input data we can run something like this.

```bash
$ polycli abi --data 0x3c158267000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063ed0f8f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006eec03843b9aca0082520894d2f852ec7b4e457f6e7ff8b243c49ff5692926ea87038d7ea4c68000808204c58080642dfe2cca094f2419aad1322ec68e3b37974bd9c918e0686b9bbf02b8bd1145622a3dd64202da71549c010494fd1475d3bf232aa9028204a872fd2e531abfd31c000000000000000000000000000000000000 < contract.abi
$ polycli abi --data 0xd53ff3fd0000000000000000000000000000000000000000000000000000000000000063 < ./bindings/tester/LoadTester.abi
Selector:a60a1087 Signature:testCHAINID(uint256)(uint256)
Selector:b7b86207 Signature:testCODESIZE(uint256)(uint256)
...
Selector:d53ff3fd Signature:testSUB(uint256)(uint256)
Selector:962e4dc2 Signature:testECMul(bytes)(bytes)
Selector:de97a363 Signature:testEXP(uint256)(uint256)
Selector:9cce7cf9 Signature:testIdentity(bytes)(bytes)
Selector:19b621d6 Signature:testSHA3(uint256)(uint256)
...
id: d53ff3fd, 0000000000000000000000000000000000000000000000000000000000000063
Input data:
{
"x": 99
}
Signature and Input
testSUB(uint256)(uint256) 99
```

In addition to the function selector data, we'll also get a breakdown of input data:
Expand Down

0 comments on commit 560f741

Please sign in to comment.