Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abi packed address is different from js/solidity #27348

Closed
exqlnet opened this issue May 25, 2023 · 4 comments
Closed

Abi packed address is different from js/solidity #27348

exqlnet opened this issue May 25, 2023 · 4 comments
Labels

Comments

@exqlnet
Copy link

exqlnet commented May 25, 2023

System information

Geth version: -
CL client & version: github.com/ethereum/go-ethereum v1.11.6
OS & Version: OSX
Commit hash : -

Expected behaviour

Pack address using abi.Arguments like abi.encodePacked in solidity. Bytes length of packed address should be 20.
For example:

0xd54e1DA3c07e678BbB96FF889Ba43e068fc60059 => d54e1DA3c07e678BbB96FF889Ba43e068fc60059

Actual behaviour

0xd54e1DA3c07e678BbB96FF889Ba43e068fc60059 => 000000000000000000000000d54e1da3c07e678bbb96ff889ba43e068fc60059

Steps to reproduce the behaviour

Here is the code reproducing the behaviour.

package main

import (
	"fmt"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"log"
)

func main() {
	Address, _ := abi.NewType("address", "", nil)
	args := abi.Arguments{}
	args = append(args, abi.Argument{
		Type: Address,
	})
	ret, err := args.Pack(common.HexToAddress("0xd54e1DA3c07e678BbB96FF889Ba43e068fc60059"))
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%x", ret)
}

Backtrace

[backtrace]

When submitting logs: please submit them as text and not screenshots.

@exqlnet
Copy link
Author

exqlnet commented May 25, 2023

In Javascript, it works fine. Also in solidity.

const ethers = require("ethers")

let packed = ethers.utils.solidityPack(
    ["address"],
    ["0xd54e1DA3c07e678BbB96FF889Ba43e068fc60059"]
)
console.log(packed)

I see go-ethereum calls common.LeftPadBytes(reflectValue.Bytes(), 32) while packing address. My confusion is why this number is 32 instead of 20.

@holiman
Copy link
Contributor

holiman commented May 25, 2023

I think there's a confusion of terms here. Go-ethereum pack/unpack can be used to pack/unpack ABI-encoded hexdata according to the ABI-specification.
The abi-encoding of a single argument, an address is 32 bytes, left-padded with zeroes according to go-ethereum, and according to https://abi.hashex.org/.

The docs at https://docs.soliditylang.org/en/latest/abi-spec.html are a bit ambiguous, because it does say that address is uint160. However, look at examples

Thus, for our Foo example if we wanted to call baz with the parameters 69 and true, we would pass 68 bytes total, which can be broken down into:

    0xcdcd77c0: the Method ID. This is derived as the first 4 bytes of the Keccak hash of the ASCII form of the signature baz(uint32,bool).

    0x0000000000000000000000000000000000000000000000000000000000000045: the first parameter, a uint32 value 69 padded to 32 bytes

    0x0000000000000000000000000000000000000000000000000000000000000001: the second parameter - boolean true, padded to 32 bytes

They pad each parameter to the full 32 bytes.

@exqlnet
Copy link
Author

exqlnet commented May 25, 2023

I'm looking for alternative method of solidity abi.encodePacked in Go. Is there any suggestion?

@exqlnet
Copy link
Author

exqlnet commented May 25, 2023

I've found an issue indicates abi.encodePacked is not recommended. It's not standardized, only use the minimal required memory to encode the data and maybe can not be decoded. The abi encode implementation of go-etheruem are same as abi.encode in solidity.

It's not a bug. And I will use more standardized methods. :-)

@exqlnet exqlnet closed this as completed May 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants