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

feat: support evm contract calls #34

Closed
wants to merge 3 commits into from

Conversation

0xrusowsky
Copy link
Contributor

@0xrusowsky 0xrusowsky commented Jan 20, 2025

adds support for EVM contract calls by enhancing the interface macro with 2 args (both optional from the user pov):

  • compilation target: encodes the fn selector based on the rules of the compilation target. Available options are "r55" (default if uninformed) or "evm". For instance, fn set(&mut self, value: U256) would be hashed from:
    • set(uint256) on "evm"
    • set on "r55"
  • rename: renames the fn name ("camelCase" is the only supported option)

tested by manually loading the bytecode of a simple storage contract written in foundry to test x-contract calls in both directions:

  • tx call to r55 contract > evm contract call
  • tx call to evm contract > r55 contract call ( > evm contract call)

i believe that this proves that the execution changes made on:

were enough to fully support cross contract calls, but happy to test more scenarios if needed (remember that @leonardoalt questioned whether the changes would be enough or not, so maybe worth increasing test coverage even more)


open questions:

  • i'm manually mapping the rust (alloy primitives) types to solidity types, i couldn't find a better way to do it:
    // Helper function to convert rust types to their solidity equivalent
    // TODO: make sure that the impl is robust, so far only tested with "simple types"
    fn rust_type_to_sol_type(ty: &Type) -> Result<DynSolType, &'static str> {
  • i'm manually creating a dummy value of the return type of the contract calls to determine an expected return size.
    • there must be better ways to do it
    • it won't work for dynamic types of unknown size
    • if i returned a size of 0 there was no memory allocation and txs were reverting as it trying to access slot 0 of the memory which is smaller than the BASE determined by the riscv emulator, so i forced a minimum size of 32bytes for the time being:
    // TODO: figure out a better way to get the return size
    // Create a dummy value to get its encoded size
    let dummy_value = <#return_ty>::default();
    let size = dummy_value.abi_encoded_size() as u64;
    let result = eth_riscv_runtime::call_contract(
       self.address,
       0_u64,
       &complete_calldata,
       if size == 0 { 32_u64 } else { size }
     )?;
    

@0xrusowsky 0xrusowsky closed this Jan 22, 2025
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.

1 participant