Making deposits to an smart contract using PHP, symfony and the soroban technology
Tags: php, symfony, soroban, smartcontract
Published: 2024-03-18 08:08:26

## Introduction
Blockchain and the smart contracts can change the way users interact on the internet providing more prominence to users and taking it away from intermediaries. 
This post is not about to talk about what blockchain and smart contracts are but to learn how we can interact with them using PHP and the symfony framework. 

## The smart contract
The smart contract is built using the [soroban](https://soroban.stellar.org/docs) technology and written with the [Rust programming language](https://www.rust-lang.org/es). It allows users to make deposits to the contract with an specified [soroban token](https://soroban.stellar.org/docs/tokens/token-interface). To do this, when the contract receives the deposit call, it transfers the amount from the user address to the contract address which increases the balance of the contract and decreases that of the user

> I've chosen soroban because there is a fantastic [php sdk](https://github.com/Soneso/stellar-php-sdk) to integrate with it.

### The code
Below we can see the complete code of the contract:

```rust
#![no_std]

use soroban_sdk::{contract, contractimpl, contracttype, contracterror, Address, Env, Symbol, token, symbol_short};

pub const ADMIN: Symbol = symbol_short!("admin");
pub const TOKEN: Symbol = symbol_short!("token");
pub const STATE: Symbol = symbol_short!("state");

#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u32)]
#[contracterror]
pub enum Error {
    ContractNotInitialized = 2
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u32)]
#[contracttype]
pub enum State {
    Pending = 1,
    Initialized = 2
}
fn get_state(env: &Env) -> State {
    if let Some(s) = env.storage().persistent().get(&STATE) {
        return s;
    }
    return State::Pending;
}

#[contract]
pub struct CryptoDeposit;

#[contractimpl]
impl CryptoDeposit {

    pub fn init(env: Env, admin_addr: Address, token_addr: Address) -> Result<bool, Error>{
        env.storage().persistent().set(&ADMIN, &admin_addr);
        env.storage().persistent().set(&TOKEN, &token_addr);
        env.storage().persistent().set(&STATE, &State::Initialized);
        Ok(true)
    }
    
    
    pub fn deposit(env: Env, addr: Address, amount: i128) -> Result<i128, Error> {

        if get_state(&env) != State::Initialized {
            return Err(Error::ContractNotInitialized);
        }

        addr.require_auth();
        let token: Address = env.storage().persistent().get(&TOKEN).unwrap();
        
        let tk = token::Client::new(&env, &token);
        tk.transfer(&addr, &env.current_contract_address(), &amount);
        let current_contract_balance = tk.balance(&env.current_contract_address());
        Ok(current_contract_balance)
    }
}

```
Let's focus on the "*CryptoDeposit impl*" which is the part holding the contract accessible functions.

#### Function init
The *init* function receives the token address which will be used to make the deposits. It stores it on the soroban storage and sets the state as *Initialized*.

#### Function deposit
This function is in charge of making the deposits. It follows the next steps:

- Check if the contract has been initialized.
- Loads the token instance.
- Transfers the funds from user address to contract address. 
- Gets the  contract address balance and returns it.

> I'm not going to delve deeper into the contract code or the rust programming language since those are not the aims of this post. If you want to learn more about soroban, you can refer to their [docs](https://soroban.stellar.org/docs).

## The Symfony application
The full application is hosted in my [github account](https://github.com/icolomina/symfony-soroban-example). In order to easily install it, I've created a [docker](https://www.docker.com/) image which builds and installs all the necessary elements. 

Let's build the container using the image:

```shell
git clone git@github.com:icolomina/symfony-soroban-example.git
cd symfony-soroban-example
docker build --no-cache -t crypto-bills .
docker run -it -p 97:80 crypto-bills
```

### Login to the app
After the container is created and started, we can navigate through the application. Open a browser (preferably chrome)  and write the following direction:

```shell
http://localhost:97
```
You will see a login page loaded:

![Login page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qovzn7qlruq6vvxcv4o5.png)

Enter the following credentials:
- User: user@test.com
- Pass: test

Click on the "Log in" button. You will be redirected to the contracts page. 

### Creating a contract
The first you can see in this page is that there are no created contracts. Click on the "Create a contract" link on the side menu. It will load the following form:

![Contract form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r6ye5e3dcpax0ghmuuv.png)

Write a label and a description. Write the token that appears in parentheses and click the button "Create contract". After a few seconds you will be redirected to the created contracts list:

![Contracts list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tecmw9ex74rujn5igs11.png)

> As you can see in the image, you can create as many contracts as you want.

### Making a deposit
Each contract has a button to make a deposit at the end of the row. Click on that button and you will be redirected to a form for making the deposit.

![Make deposit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/va5m18b4io31w7j4br4g.png)

Enter the amount you want to deposit (no more than 5000 since the account is minted with 5000 units) and click on the "Send deposit" button. After a few seconds you will be redirected to the created contracts list and you will see that the balance column has been updated.

## Conclusion
This app example demonstrates how we can interact with soroban smart contracts using PHP and the symfony framework. This is also possible thanks great [stellar php-sdk compoment](https://github.com/Soneso/stellar-php-sdk). 
Using PHP to interact with smart contracts  can be useful to develop applications which follows a custodial model on which user keys and addresses are managed by the third parties.

> I hope you have found this post useful and interesting. If you enjoy my content and like the Symfony framework, consider reading my book: [Building an Operation-Oriented Api using PHP and the Symfony Framework: A step-by-step guide](https://amzn.eu/d/3eO1DDi)