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

import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";

/**
 * @title LibRLP
 * @notice Via https://github.com/Rari-Capital/solmate/issues/207.
 */
library LibRLP {
    using Bytes32AddressLib for bytes32;

    function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {
        // The integer zero is treated as an empty byte string, and as a result it only has a length prefix, 0x80, computed via 0x80 + 0.
        // A one byte integer uses its own value as its length prefix, there is no additional "0x80 + length" prefix that comes before it.
        if (nonce == 0x00)
            return
                keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))
                    .fromLast20Bytes();
        if (nonce <= 0x7f)
            return
                keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))
                    .fromLast20Bytes();

        // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.
        if (nonce <= type(uint8).max)
            return
                keccak256(
                    abi.encodePacked(
                        bytes1(0xd7),
                        bytes1(0x94),
                        deployer,
                        bytes1(0x81),
                        uint8(nonce)
                    )
                ).fromLast20Bytes();
        if (nonce <= type(uint16).max)
            return
                keccak256(
                    abi.encodePacked(
                        bytes1(0xd8),
                        bytes1(0x94),
                        deployer,
                        bytes1(0x82),
                        uint16(nonce)
                    )
                ).fromLast20Bytes();
        if (nonce <= type(uint24).max)
            return
                keccak256(
                    abi.encodePacked(
                        bytes1(0xd9),
                        bytes1(0x94),
                        deployer,
                        bytes1(0x83),
                        uint24(nonce)
                    )
                ).fromLast20Bytes();

        // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp
        // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)
        // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)
        // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)
        // We assume nobody can have a nonce large enough to require more than 32 bytes.
        return
            keccak256(
                abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))
            ).fromLast20Bytes();
    }
}
