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

Remove abi.encodePacked #11593

Open
axic opened this issue Jun 29, 2021 · 15 comments
Open

Remove abi.encodePacked #11593

axic opened this issue Jun 29, 2021 · 15 comments
Labels
breaking change ⚠️ has dependencies The PR depends on other PRs that must be merged first language design :rage4: Any changes to the language, e.g. new features low effort There is not much implementation work to be done. The task is very easy or tiny. medium impact Default level of impact must have eventually Something we consider essential but not enough to prevent us from releasing Solidity 1.0 without it.
Milestone

Comments

@axic
Copy link
Member

axic commented Jun 29, 2021

abi.encodePacked was introduced in 0.4.22 as a backwards compatibility measure for the irregular "packed" encoding.

Since then we have introduced bytes.concat (#10903) and learned that most projects (rightly) do not rely on the packed encoding, but only concatenation. I suggest we drop abi.encodePacked in the next breaking release.

(We could consider introducing a message with #11508 if we want to test the waters 😅 , but would rather refrain from this.)

@axic axic added breaking change ⚠️ language design :rage4: Any changes to the language, e.g. new features labels Jun 29, 2021
@chriseth
Copy link
Contributor

Which types can be used with encodePacked that cannot be used with bytes.concat?

@charles-cooper
Copy link

Which types can be used with encodePacked that cannot be used with bytes.concat?

Arrays. https://docs.soliditylang.org/en/v0.8.6/abi-spec.html.

What is the effect of this proposal on event index encoding?

@chriseth
Copy link
Contributor

chriseth commented Aug 2, 2021

Event index encoding will not change, since we only plan to remove abi.encodePacked from the language.

Is packed encoding of arrays used in the real world?

@e-nikolov
Copy link

e-nikolov commented Mar 9, 2022

Is packed encoding of arrays used in the real world?

One place where it can be used is for EIP-712 hashes - https://eips.ethereum.org/EIPS/eip-712#definition-of-encodedata.

For example if there is a struct that contains an array:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

contract MultiTransferDemo {
    struct MultiTransfer {
        uint256 id;
        Transfer[] transfers;
    }

    struct Transfer {
        uint256 amount;
        address recepient;
    }

    function hash(MultiTransfer memory mt) public pure returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256(
                        "MultiTransfer(uint256 id,Transfer[] transfers)Transfer(uint256 amount,address recepient)"
                    ),
                    mt.id,
                    hashTransfers(mt.transfers)
                )
            );
    }

    function hashTransfers(Transfer[] memory transfers)
        public
        pure
        returns (bytes32)
    {
        bytes32[] memory hashedTransfers = new bytes32[](transfers.length);
        for (uint256 i = 0; i < transfers.length; i++) {
            hashedTransfers[i] = hashTransfer(transfers[i]);
        }
        return keccak256(abi.encodePacked(hashedTransfers));
    }

    function hashTransfer(Transfer memory transfer)
        public
        pure
        returns (bytes32)
    {
        return
            keccak256(
                abi.encode(
                    keccak256("Transfer(uint256 amount,address recepient)"),
                    transfer.amount,
                    transfer.recepient
                )
            );
    }
}

It can also be implemented via bytes.concat, but I'm not sure which version has better performance:

    function hashTransfers2(Transfer[] memory transfers)
        public
        pure
        returns (bytes32)
    {
        bytes memory encodedTransfers = new bytes(0);
        for (uint256 i = 0; i < transfers.length; i++) {
            encodedTransfers = bytes.concat(
                encodedTransfers,
                hashTransfer(transfers[i])
            );
        }
        return keccak256(encodedTransfers);
    }

@maurelian
Copy link
Contributor

Which types can be used with encodePacked that cannot be used with bytes.concat?

As a real world example, this use of encodePacked():

https://github.com/Anish-Agnihotri/merkle-airdrop-starter/blob/83d6c65d00a10b40e0abdd84a5afa692553a9e72/contracts/src/MerkleClaimERC20.sol#L66

Would need to use casting to do the same thing:

keccak256(bytes.concat(bytes20(a),bytes32(value)));

Would it be considered more 'idiomatic' to use bytes.concat and cast from address and uintX?

@cameel
Copy link
Member

cameel commented Apr 26, 2022

I think that address is actually something that should be allowed as input in bytes.concat(). It does have an unambiguous binary representation and an explicit cast to bytes20 should not be needed.

@fredlacs
Copy link

fredlacs commented Jun 16, 2022

Curious on the current thinking around this.
Is this still being considered?

@ekpyron
Copy link
Member

ekpyron commented Sep 14, 2022

Current plan is to indeed remove abi.encodePacked as soon as #11593 is done and it's possible to reimplement this generically in user code :-).

@ekpyron ekpyron added has dependencies The PR depends on other PRs that must be merged first low effort There is not much implementation work to be done. The task is very easy or tiny. medium impact Default level of impact must have eventually Something we consider essential but not enough to prevent us from releasing Solidity 1.0 without it. labels Sep 14, 2022
@cameel
Copy link
Member

cameel commented Sep 14, 2022

#11593 is this issue :)

@ekpyron
Copy link
Member

ekpyron commented Sep 15, 2022

#11593 is this issue :)

Ah, sorry, I meant #13321 :-).

@axic
Copy link
Member Author

axic commented Sep 27, 2022

I think that address is actually something that should be allowed as input in bytes.concat(). It does have an unambiguous binary representation and an explicit cast to bytes20 should not be needed.

@cameel I think the real solution is #11284 and not adding non-bytes types to bytes.concat.

@cameel
Copy link
Member

cameel commented Sep 27, 2022

I think it's a solution for the general case but I also wouldn't mind easing on the overly verbose conversions in select cases where they don't add anything. Even with some nicer conversion from #11284 this would be more verbose than it needs to be for clarity.

@PaulRBerg
Copy link
Contributor

What's your latest advice on how to convert an address to bytes32?

I'm still relying on abi.encodePacked since it's clearer than bytes.concat(bytes20(addr)).

@CJ42
Copy link
Contributor

CJ42 commented Oct 12, 2023

I think abi.encodePacked is very convenient for concatenation.
Especially when concatenating multiple types that are not all bytesN or bytes.

For instance, to concatenate like: abi.encodePacked(address, bytesN, uint256, …)

@exqlnet
Copy link

exqlnet commented Feb 23, 2024

The most common problem i have met is that how can i do this using other languages? such as js/golang?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change ⚠️ has dependencies The PR depends on other PRs that must be merged first language design :rage4: Any changes to the language, e.g. new features low effort There is not much implementation work to be done. The task is very easy or tiny. medium impact Default level of impact must have eventually Something we consider essential but not enough to prevent us from releasing Solidity 1.0 without it.
Projects
None yet
Development

No branches or pull requests