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

📝 EOF Plan #1142

Open
Vectorized opened this issue Nov 1, 2024 · 0 comments
Open

📝 EOF Plan #1142

Vectorized opened this issue Nov 1, 2024 · 0 comments

Comments

@Vectorized
Copy link
Owner

Vectorized commented Nov 1, 2024

https://github.com/ithacaxyz/odyssey-examples/tree/main/chapter1/eof

Primer

EOF disables a number of opcodes. Right now, if your contract contains any of those it will get compiled but will not be deployable.

The banned opcodes are:

  • Code introspection opcodes: CODESIZE, CODECOPY, EXTCODESIZE, EXTCODECOPY, EXTCODEHASH.
  • Dynamic jumps: JUMP, JUMPI, PC.
  • Gas introspection opcodes: GAS, GASLIMIT, GASPRICE.
  • Legacy call instructions: CREATE, CALL, DELEGATECALL, CREATE2, STATICCALL.
  • Legacy opcodes: SELFDESTRUCT, CALLCODE.

Plan

  • Test with forge test --eof.

  • Tests

    • test__codesize() to be removed. We cannot use codesize anymore. Not really a dealbreaker.
    • _brutalizeMemory(). We will simply have to spam keccak256 and mcopy.
    • Have all the etch functions for factories and escape hatches.
  • Transpiling

    • Identify a list of problematic contracts and easy contracts. Sort them from most problematic to least.
    • Hit the most problematic contracts first.

Escape hatch

https://github.com/Vectorized/escape-hatch

To be deployed via Nick's factory:

  • EXTCODECOPY, EXTCODESIZE

  • CREATE

    • Reverts with returndata upon failure. Returns the address otherwise.
  • CREATE2

    • Reverts with returndata upon failure. Returns the address otherwise.
    • Since Nick's doesn't return the address, we will just have to make our own factory.
  • SELFDESTRUCT to force send Ether

    • Takes in address.
    • Reverts with empty data upon failure. Returns true otherwise.
  • Gas limited CALL

    • Forwards value.
    • Returns/Reverts with all returndata.
  • Gas limited STATICCALL

    • Returns/Reverts with all returndata.

I think it's best that we make a separate repo while devving these escape hatches. Doesn't need npm.

Notes

  • All addresses passed in to EXTCALL, EXTDELEGATECALL, EXTDELEGATECALL must have upper 96 bits cleaned. Also, their behavior are different.

  • Hand translation might not be that hard. We can use functions to encapsulate if it looks better.

Transpilation

We might define an eof/src and eof/test directory. These directories are intentionally not in src or test, so that when people install Solady for use in a regular Solidity project, they still can compile hassle free.

I'm thinking if it might be better if we keep the EOF stuff in Solady:

  • Aggregate traffic into Solady.
  • It keeps the diffing easier.
  • Say if we put the stuff in Soledge, and someone who wants to use the tstore libs on a non EOF project (which we expect most users to), they might run into compilation hassles.
  • I'd also like to reserve Soledge for the worse case scenario where Solidity becomes a completely different language in the future (in a bad way), and Soledge will have to exist to add support for that.

I feel that some stuff might not be fit for automatic transpilation. We'll know it when we get there.

A lot of the code will be a one-time transpilation. There are also many devious edge cases. A hand-transpilation approach might be overall more effort efficient even in the long run. Additionally, hand-transpiling will allow us to perform EOF specific hand-optimizations if time permits.

Effort estimates

  • 1 week to craft, mine vanity address, and deploy escape hatches.
  • 1 week to refactor the test base contracts TestPlus.sol, Brutalizer.sol, SoladyTest.sol, Test.sol.
  • 1 week to refactor the original test contracts to avoid using banned opcodes.
  • 2 weeks of porting the contracts to EOF.

These will be full-time efforts.

In the long term, we will need to maintain two 1:1 copies of Solady, the legacy in src and eof.

Priorities

Our top priority is drop-in compatibility with EOF Solidity compiler.

We'll just go with full code-reuse style. We do NOT need inline anything.

In fact, I have a feel that contracts with more code reuse are better suited for EOF, with the subroutine stuff.

LibClone might actually have lesser SLOCs with rampant code reuse.

Regression

Going forward, Solady's legacy code will still be at the forefront of cutting edge features.

We will need to have some discipline on keeping the EOF quickly up to parity with the non-EOF code, but if resources are limited, we will just create a new backlog issue on porting it to EOF.

File analysis

[
    {
        "srcPath": "src/Milady.sol",
        "lastModifiedGitTimestamp": 1730050433
    },
    {
        "srcPath": "src/accounts/Receiver.sol",
        "lastModifiedGitTimestamp": 1725453789
    },
    {
        "srcPath": "src/auth/Ownable.sol",
        "lastModifiedGitTimestamp": 1697754631
    },
    {
        "srcPath": "src/auth/OwnableRoles.sol",
        "lastModifiedGitTimestamp": 1720385905
    },
    {
        "srcPath": "src/tokens/ERC2981.sol",
        "lastModifiedGitTimestamp": 1686120478
    },
    {
        "srcPath": "src/tokens/ERC6909.sol",
        "lastModifiedGitTimestamp": 1703921789
    },
    {
        "srcPath": "src/utils/Base64.sol",
        "lastModifiedGitTimestamp": 1709232746
    },
    {
        "srcPath": "src/utils/DateTimeLib.sol",
        "lastModifiedGitTimestamp": 1705005025
    },
    {
        "srcPath": "src/utils/DynamicBufferLib.sol",
        "lastModifiedGitTimestamp": 1726471158
    },
    {
        "srcPath": "src/utils/EIP712.sol",
        "lastModifiedGitTimestamp": 1698938547
    },
    {
        "srcPath": "src/utils/ERC1967FactoryConstants.sol",
        "lastModifiedGitTimestamp": 1720878475
    },
    {
        "srcPath": "src/utils/EfficientHashLib.sol",
        "lastModifiedGitTimestamp": 1724696571
    },
    {
        "srcPath": "src/utils/EnumerableSetLib.sol",
        "lastModifiedGitTimestamp": 1728734415
    },
    {
        "srcPath": "src/utils/FixedPointMathLib.sol",
        "lastModifiedGitTimestamp": 1725075080
    },
    {
        "srcPath": "src/utils/JSONParserLib.sol",
        "lastModifiedGitTimestamp": 1705066803
    },
    {
        "srcPath": "src/utils/LibBit.sol",
        "lastModifiedGitTimestamp": 1717740645
    },
    {
        "srcPath": "src/utils/LibBitmap.sol",
        "lastModifiedGitTimestamp": 1721699660
    },
    {
        "srcPath": "src/utils/LibBytes.sol",
        "lastModifiedGitTimestamp": 1730857419
    },
    {
        "srcPath": "src/utils/LibMap.sol",
        "lastModifiedGitTimestamp": 1690778106
    },
    {
        "srcPath": "src/utils/LibPRNG.sol",
        "lastModifiedGitTimestamp": 1719111683
    },
    {
        "srcPath": "src/utils/LibRLP.sol",
        "lastModifiedGitTimestamp": 1726471715
    },
    {
        "srcPath": "src/utils/LibSort.sol",
        "lastModifiedGitTimestamp": 1727873015
    },
    {
        "srcPath": "src/utils/LibString.sol",
        "lastModifiedGitTimestamp": 1730857419
    },
    {
        "srcPath": "src/utils/LibTransient.sol",
        "lastModifiedGitTimestamp": 1730765339
    },
    {
        "srcPath": "src/utils/MerkleProofLib.sol",
        "lastModifiedGitTimestamp": 1697511114
    },
    {
        "srcPath": "src/utils/MinHeapLib.sol",
        "lastModifiedGitTimestamp": 1723492714
    },
    {
        "srcPath": "src/utils/ReentrancyGuardTransient.sol",
        "lastModifiedGitTimestamp": 1730497227
    },
    {
        "srcPath": "src/utils/SafeCastLib.sol",
        "lastModifiedGitTimestamp": 1715433563
    },
    {
        "srcPath": "src/utils/Initializable.sol",
        "scores": {
            "extcodesize": 1
        },
        "lastModifiedGitTimestamp": 1705139261
    },
    {
        "srcPath": "src/utils/RedBlackTreeLib.sol",
        "scores": {
            "codesize": 1
        },
        "lastModifiedGitTimestamp": 1717740645
    },
    {
        "srcPath": "src/utils/ReentrancyGuard.sol",
        "scores": {
            "codesize": 1
        },
        "lastModifiedGitTimestamp": 1706263836
    },
    {
        "srcPath": "src/tokens/ERC20.sol",
        "scores": {
            "staticcall": 1
        },
        "lastModifiedGitTimestamp": 1729135343
    },
    {
        "srcPath": "src/tokens/ERC20Votes.sol",
        "scores": {
            "staticcall": 1
        },
        "lastModifiedGitTimestamp": 1729135343
    },
    {
        "srcPath": "src/tokens/ERC4626.sol",
        "scores": {
            "staticcall": 1
        },
        "lastModifiedGitTimestamp": 1717740645
    },
    {
        "srcPath": "src/utils/MetadataReaderLib.sol",
        "scores": {
            "staticcall": 2
        },
        "lastModifiedGitTimestamp": 1723462389
    },
    {
        "srcPath": "src/accounts/ERC4337Factory.sol",
        "scores": {
            "codesize": 1,
            "call": 1
        },
        "lastModifiedGitTimestamp": 1703276182
    },
    {
        "srcPath": "src/accounts/ERC6551Proxy.sol",
        "scores": {
            "codesize": 1,
            "delegatecall": 1
        },
        "lastModifiedGitTimestamp": 1710219546
    },
    {
        "srcPath": "src/utils/Multicallable.sol",
        "scores": {
            "codesize": 1,
            "delegatecall": 1
        },
        "lastModifiedGitTimestamp": 1725108562
    },
    {
        "srcPath": "src/utils/UpgradeableBeacon.sol",
        "scores": {
            "codesize": 2,
            "extcodesize": 1
        },
        "lastModifiedGitTimestamp": 1715045031
    },
    {
        "srcPath": "src/auth/EnumerableRoles.sol",
        "scores": {
            "staticcall": 2
        },
        "lastModifiedGitTimestamp": 1728811386
    },
    {
        "srcPath": "src/tokens/WETH.sol",
        "scores": {
            "codesize": 2,
            "call": 1
        },
        "lastModifiedGitTimestamp": 1719095021
    },
    {
        "srcPath": "src/utils/CREATE3.sol",
        "scores": {
            "extcodesize": 1,
            "create2": 1,
            "call": 1
        },
        "lastModifiedGitTimestamp": 1720878475
    },
    {
        "srcPath": "src/utils/DynamicArrayLib.sol",
        "scores": {
            "codesize": 2,
            "codecopy": 2
        },
        "lastModifiedGitTimestamp": 1728355500
    },
    {
        "srcPath": "src/utils/GasBurnerLib.sol",
        "scores": {
            "codecopy": 2,
            "staticcall": 1
        },
        "lastModifiedGitTimestamp": 1721303834
    },
    {
        "srcPath": "src/utils/WebAuthn.sol",
        "scores": {
            "staticcall": 2
        },
        "lastModifiedGitTimestamp": 1730239265
    },
    {
        "srcPath": "src/accounts/Pod.sol",
        "scores": {
            "codesize": 2,
            "call": 2
        },
        "lastModifiedGitTimestamp": 1727862888
    },
    {
        "srcPath": "src/utils/DeploylessPredeployQueryer.sol",
        "scores": {
            "codesize": 1,
            "extcodesize": 1,
            "call": 2
        },
        "lastModifiedGitTimestamp": 1713208829
    },
    {
        "srcPath": "src/utils/ERC1967Factory.sol",
        "scores": {
            "create": 1,
            "create2": 1,
            "call": 2
        },
        "lastModifiedGitTimestamp": 1706770409
    },
    {
        "srcPath": "src/utils/UUPSUpgradeable.sol",
        "scores": {
            "codesize": 2,
            "staticcall": 1,
            "delegatecall": 1
        },
        "lastModifiedGitTimestamp": 1715045031
    },
    {
        "srcPath": "src/utils/P256.sol",
        "scores": {
            "staticcall": 4
        },
        "lastModifiedGitTimestamp": 1723742125
    },
    {
        "srcPath": "src/utils/LibZip.sol",
        "scores": {
            "codesize": 4,
            "codecopy": 3,
            "delegatecall": 1
        },
        "lastModifiedGitTimestamp": 1707000199
    },
    {
        "srcPath": "src/accounts/LibERC6551.sol",
        "scores": {
            "extcodesize": 2,
            "extcodecopy": 7,
            "call": 1
        },
        "lastModifiedGitTimestamp": 1709789868
    },
    {
        "srcPath": "src/tokens/ERC721.sol",
        "scores": {
            "codesize": 6,
            "extcodesize": 1,
            "call": 1,
            "staticcall": 1
        },
        "lastModifiedGitTimestamp": 1711338124
    },
    {
        "srcPath": "src/utils/SSTORE2.sol",
        "scores": {
            "codesize": 1,
            "extcodesize": 4,
            "extcodecopy": 3,
            "create": 1,
            "create2": 2,
            "call": 1
        },
        "lastModifiedGitTimestamp": 1728067022
    },
    {
        "srcPath": "src/accounts/ERC1271.sol",
        "scores": {
            "codesize": 1,
            "gaslimit": 2,
            "gasprice": 8,
            "staticcall": 2
        },
        "lastModifiedGitTimestamp": 1730050055
    },
    {
        "srcPath": "src/accounts/ERC6551.sol",
        "scores": {
            "codesize": 2,
            "extcodecopy": 3,
            "call": 2,
            "staticcall": 3
        },
        "lastModifiedGitTimestamp": 1717372305
    },
    {
        "srcPath": "src/utils/ECDSA.sol",
        "scores": {
            "staticcall": 8
        },
        "lastModifiedGitTimestamp": 1730845513
    },
    {
        "srcPath": "src/utils/Lifebuoy.sol",
        "scores": {
            "codesize": 4,
            "extcodesize": 3,
            "call": 5,
            "staticcall": 1
        },
        "lastModifiedGitTimestamp": 1724378720
    },
    {
        "srcPath": "src/accounts/ERC4337.sol",
        "scores": {
            "codesize": 11,
            "extcodesize": 2,
            "call": 5,
            "staticcall": 1,
            "delegatecall": 1
        },
        "lastModifiedGitTimestamp": 1713297028
    },
    {
        "srcPath": "src/tokens/ERC1155.sol",
        "scores": {
            "extcodesize": 3,
            "call": 4,
            "staticcall": 10
        },
        "lastModifiedGitTimestamp": 1718114922
    },
    {
        "srcPath": "src/utils/ext/delegatexyz/DelegateCheckerLib.sol",
        "scores": {
            "staticcall": 20
        },
        "lastModifiedGitTimestamp": 1720170364
    },
    {
        "srcPath": "src/utils/SignatureCheckerLib.sol",
        "scores": {
            "codesize": 2,
            "extcodesize": 2,
            "call": 3,
            "staticcall": 21
        },
        "lastModifiedGitTimestamp": 1730845513
    },
    {
        "srcPath": "src/utils/SafeTransferLib.sol",
        "scores": {
            "codesize": 29,
            "extcodesize": 11,
            "create": 4,
            "call": 21,
            "staticcall": 6
        },
        "lastModifiedGitTimestamp": 1729206025
    },
    {
        "srcPath": "src/utils/LibClone.sol",
        "scores": {
            "codesize": 23,
            "codecopy": 3,
            "extcodesize": 25,
            "extcodecopy": 16,
            "create": 11,
            "create2": 21,
            "call": 11,
            "staticcall": 16
        },
        "lastModifiedGitTimestamp": 1730767406
    }
]
@Vectorized Vectorized pinned this issue Nov 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant