Skip to content

feat: add LOOKUP_DELEGATED_ADDRESS precompile wrapper#9

Open
pali101 wants to merge 14 commits intofilecoin-project:mainfrom
pali101:feat/lookup-delegated-address-v2
Open

feat: add LOOKUP_DELEGATED_ADDRESS precompile wrapper#9
pali101 wants to merge 14 commits intofilecoin-project:mainfrom
pali101:feat/lookup-delegated-address-v2

Conversation

@pali101
Copy link
Copy Markdown
Contributor

@pali101 pali101 commented Mar 1, 2026

Summary

Implements the LOOKUP_DELEGATED_ADDRESS precompile wrapper (0xfe...02) to retrieve an actor's delegated address (f4) and extract the Ethereum-style address using optimized inline assembly.

The primary API returns address for ergonomic use in Solidity while preserving raw bytes helpers for applications that require the f4 encoding.

Addresses all reviewer feedback from the initial submission (#6).

Key Changes

  • src/FVMActor.sol

    • Added tryLookupDelegatedAddress(uint64) → (bool, address): returns empty and exists=false if actor has no delegated address
    • Added lookupDelegatedAddress(uint64) → address: strict variant, reverts with DelegatedAddressNotFound(actorId) if no delegated address exists
    • Added tryLookupDelegatedAddressBytes(uint64) → (bool, bytes): returns empty and exists=false if actor has no delegated address; defaults to zero slot (0x60) to safely represent empty bytes without allocation
    • Added lookupDelegatedAddressBytes(uint64) → bytes: strict raw-bytes variant
  • src/FVMAddress.sol

    • Added toEthAddress(bytes) → address: validates f410 format (length 22, prefix 0x040a) and extracts the last 20 bytes as an Ethereum address
    • Added InvalidDelegatedAddress error
  • src/mocks/FVMActor.sol

    • Added delegatedAddressMocks mapping to support LOOKUP_DELEGATED_ADDRESS in the unified fallback
    • Added mockLookupDelegatedAddress(uint64, bytes) and mockLookupDelegatedAddress(uint64, address) overloads
    • Fallback routes on msg.data.length == 32 to distinguish lookup from resolve calls
  • src/mocks/MockFVMTest.sol

    • Etches and copies storage for LOOKUP_DELEGATED_ADDRESS alongside RESOLVE_ADDRESS
  • src/Demo.sol

Reviewer Notes

  • FVMLookupDelegatedAddress merged into FVMActor per feedback
  • toEthAddress moved to FVMAddress per feedback
  • Precompile revert data propagated directly via returndatacopy + revert(0, returnSize), consistent with feat: add RESOLVE_ADDRESS precompile wrapper #5

Update (after review feedback)

Based on reviewer feedback, the delegated address API has been updated to return address by default since delegated addresses are native to the FEVM.

The raw bytes helpers are still available for callers that need the f4/f410 encoding.

Updated API:

  • tryLookupDelegatedAddress(uint64)(bool, address)
  • lookupDelegatedAddress(uint64)address
  • tryLookupDelegatedAddressBytes(uint64)(bool, bytes)
  • lookupDelegatedAddressBytes(uint64)bytes

Closes #2

@wjmelements
Copy link
Copy Markdown
Collaborator

I think it could be more natural to return address for delegated address since a delegated address is native to the FEVM. However, we should keep the bytes method in case somebody needs to format it that way, so they aren't forced to decode and re-encode it.

@wjmelements
Copy link
Copy Markdown
Collaborator

This is very close to merging. Can you link a deployed Demo contract with your next push?

bytes memory tooShort = abi.encodePacked(uint8(0x04), uint8(0x0a), bytes19(0));

vm.expectRevert(FVMAddress.InvalidDelegatedAddress.selector);
this._toEthAddress(tooShort);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you have to explicitly this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to keep this. Foundry's vm.expectRevert() only catches reverts on external calls by default. Without it, it becomes an internal call, which crashes the test and fails with: [FAIL: call didn't revert at a lower depth than cheatcode call depth]

That said, Foundry recently added a config to allow testing internal reverts. I can add /// forge-config: default.allow_internal_expect_revert = true above these tests and drop the this. if you prefer that pattern! Let me know what you think is cleaner.

pali101 added 2 commits March 20, 2026 13:01
- Combined BigBrain code blocks in README.md for clarity.
- Moved _toEthAddress under the correct test banner in Address.t.sol.
@pali101
Copy link
Copy Markdown
Contributor Author

pali101 commented Mar 20, 2026

Here is the deployed Demo contract on the Calibration testnet: 0x09f149b6AeCFCeF271fA2E84b01205373c84c16D

I also ran a quick profiling trick: by using cast send instead of cast call on the view function, I forced a transaction to get the exact WASM gas trace on the block explorer. This comparison is before and after the returndatasize() and input overwrite optimizations.

Before: 3205778 (txn hash: 0x13de8f573707c7845b7764c72a3f816a36781e47a5323beef967a4bb811b3c6a)
After: 2702216 (txn hash: 0x3fe4999b1037c08b3801f1ade2c705a941a3e80da2b3bc3dbb7d9cf494ad9e9b)

Saving: 503562 gas

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

Successfully merging this pull request may close these issues.

Support precompile: LookupDelegatedAddress

2 participants