DEV Community

Nacho Colomina Torregrosa
Nacho Colomina Torregrosa

Posted on • Edited on

Making deposits to an smart contract using PHP, symfony and the soroban technology

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 technology and written with the Rust programming language. It allows users to make deposits to the contract with an specified soroban token. 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 to integrate with it.

The code

Below we can see the complete code of the contract:

#![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)
    }
}

Enter fullscreen mode Exit fullscreen mode

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.

The Symfony application

The full application is hosted in my github account. In order to easily install it, I've created a docker image which builds and installs all the necessary elements.

Let's build the container using the image:

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
Enter fullscreen mode Exit fullscreen mode

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:

http://localhost:97
Enter fullscreen mode Exit fullscreen mode

You will see a login page loaded:

Login page

Enter the following credentials:

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

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

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

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.
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

Top comments (0)