Converting a Soroban Smart Contract into a crate library
Published: 2023-10-17 16:56:12

I am working developing [Soroswap.Finance](https://soroswap.finance/), an AMM in Soroban and we write our Smart Contracts based on the [UniswapV2](https://docs.uniswap.org/contracts/v2/reference/smart-contracts/factory) Smart Contracts written in Solidity.

In Solidity we can write an smart contract, deploy it and use it as an smart contract and also use the same code as a library, so another smart contract can inherit its logic.

Common usage is:
```javascript
contract MyContract is ContractFather

```
Another usage is to use a Solidity library like:
```javascript
import './libraries/UniswapV2Library.sol';

...
// and then use the library like:
uint amountBOptimal = UniswapV2Library.quote(amountADesired, reserveA, reserveB);

```

How can we do something similar with rust and soroban-sdk?

## The Library Contract
I wrote the SoroswapLibrary Smart Contract and it was working perfectly: Here is the code I had at the moment:
https://github.com/soroswap/core/tree/c65cebcfe69f05b38567158610dab25a941d4e6a/contracts/library

## Publishing into crates.io
In order to transform this "pure" Smart Contract into a Library that can be imported by another Smart Contract I did the following:

1.- Edit the Cargo.toml to add some information necessary to publish into crates.io
```
[package]
name = "soroswap-library"
version = "0.1.1"
description = "Library that enables efficient and optimized code execution across different contracts on the Soroswap.Finance protocol"
homepage = "https://github.com/soroswap/core/tree/main/contracts/library"
repository = "https://github.com/soroswap/core/tree/main/contracts/library"
authors = ["esteblock <esteblock@paltalabs.io>"]
readme = "README.md"
license = "GPL-3.0"
edition = "2021"
keywords = ["no_std", "wasm", "soroswap", "amm", "soroban"]
rust-version = "1.73"
publish = true
```

2.- Create an account in crates.io and login
```
cargo login
```

3.- Publish:
```
cargo publish
```

If everything goes well, your contract will be published in crates.io and you can use it

## Importing it into your code:
In my Router contract I can use it as a library, editing `Cargo.toml`
```
[dependencies]
soroban-sdk = { version = "20.0.0-rc2" }
num-integer = { version = "0.1.45", default-features = false, features = ["i128"] }
soroswap-library = "0.1.1"
```

And I **should** be able to use it inside my `lib.rs` as
```
use soroswap_library;
```

## The "no external crate" error
When I complile the `Router` contract I had the following error:

```
error[E0432]: unresolved import `soroswap_library`
 --> src/lib.rs:9:5
  |
9 | use soroswap_library;
  |     ^^^^^^^^^^^^^^^^ no external crate `soroswap_library`

```

Very strange... But I found that I could solve it, adding the `rlib` crate type in the library contract... So it stays like this:

```

[lib]
crate-type = ["cdylib", "rlib"]
```

## Moving out your desired functions.
Also, in order to use a function as a crate library, you'll need to move them out from the contract Trait... and re-export them:

In my case, the Library's `lib.rs` has:
```rust
mod test;
mod tokens;
mod reserves;
mod quotes;

pub use tokens::{
    sort_tokens,
    pair_for
};
pub use reserves::{
    get_reserves
};
pub use quotes::{
    quote, 
    get_amount_out, 
    get_amount_in, 
    get_amounts_out, 
    get_amounts_in
};

```

Check the final code here: https://github.com/soroswap/core/tree/main/contracts/library

## Using the library
With this change (and of course after publishing a new version of the library in crates.io), I could use in my Router

```rust
use soroswap_library;
// and then

let amount_b_optimal = soroswap_library::quote(amount_a_desired.clone(), reserve_a.clone(), reserve_b.clone());
```