Skip to content

feat: Allow references in contract methods#1521

Closed
willemneal wants to merge 3 commits intostellar:mainfrom
theahaco:feat/ref_args
Closed

feat: Allow references in contract methods#1521
willemneal wants to merge 3 commits intostellar:mainfrom
theahaco:feat/ref_args

Conversation

@willemneal
Copy link
Copy Markdown
Contributor

What

Support references in contract methods:

#[contractimpl]
impl Contract {
    pub fn foo(e: &Env, a: &Symbol, b: &SomeUDT){
...

Why

Often when testing contracts with unit testing or calling an external interface from within a contract in can be useful to have the argument to the method be a reference.

Known limitations

Need to test more thoroughly.

@leighmcculloch leighmcculloch self-requested a review August 7, 2025 10:26
@leighmcculloch
Copy link
Copy Markdown
Member

I'm iterating on this change over at #1535 because this pull request doesn't permit pushes from maintainers.

@willemneal
Copy link
Copy Markdown
Contributor Author

Thanks! Will change that in future PRs!

github-merge-queue bot pushed a commit that referenced this pull request Oct 29, 2025
### What
Allow contract functions parameters to be immutable references, rather
than only owned values.

### Why

This change is primarily about making it more convenient to write
contract functions like typical Rust functions. In Rust function
parameters can be of a few variations, they can be an owned value or a
reference/borrow, and can be immutable or mutable. Today contract
function parameters must be owned and immutable.

Reference parameters are useful when needing to pass around a value that
the caller would like to retain ownership over. Mutable parameters are
helpful when the function will mutate the parameter making the mutated
value available to the caller.

It is common when writing small composable Rust functions to use ref and
mut as needed.

When writing contract functions the composability of the functions being
written is restricted. Owned values must be used, and this leads to
situations where functions must received cloned values.

In contracts cloning SDK types when passing them around is not a
performance concern since all SDK types are a small integer value. But
it is inconvenient and it makes contracts look less like regular Rust
code when there is an abundance of `.clone()` for no apparent reason
other than the contract functions don't let you.

Is this a big issue? No, not particularly. But in general the
soroban-sdk tries to let people write Rust how they'd write Rust
elsewhere. And this change lifts a limitation that isn't really
required.

### Why not

This change introduces variance into the trait-compatible interface that
implementations can take. For a contract interface that is intended to
be standard, one implementation might use all owned values, another
might use all refs, and another might use any combination. This doesn't
affect a contracts ability to be called because this information does
not make it into the exported interface. But if someone was to share a
Rust trait to match one implementation, there's a good chance it would
fail to match other implementations. Technically variance already exists
today. The `env: Env` parameter is already optional, and can already
take either an owned `Env` or a ref `&Env`. So the ship already sailed
from day one.

You could argue that the top-level entry point value in a program should
always be owned. Someone has to own every value. The fact that contract
functions do not need to own the value is because there's actually an
outer function that gets exported that is truly the entry point and that
function can own the value. But in some ways that's a bit odd.

### Merging

This change can be merged at anytime and can be released in a minor
release. It does not change or limit any existing behaviour and only
adds new behaviour that is disallowed today.

### Thanks

Thanks to @willemneal contributing #1521 that this change is derived.

### Todo
- [x] Test the change on soroban-examples.
#1591
- [x] Test the change on several complex ecosystem contracts.
- [x] Test with #1544 
- [x] #1606

---------

Co-authored-by: Willem Wyndham <willem@ahalabs.dev>
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.

2 participants