Once you are inside the soroban-preview-9 container (by bash quickstart.sh and bash run.sh) you can start experimenting with the SoroswapPair contract.
1. Open and read the contract:
Open in your favourite IDE or text editor, and check the pair folder:
In the pair/src folder you will find:
The lib.rs file with the SoroswapPair functions
The token folder, which is a fork of the token contract from soroban-examples, with two added functions: The internal_burn and the internal_mint function. As the SoroswapPair contract is a token itself, if it's not making a cross-contract call to iself in order to mint or burn tokens, it will have problems with require_auth. Read more about this in the following issue: #16
The test.rs.
The events.rs to emmit events
The factory.rs used as a Interface of some of the factory functions
The create folder, that contains the create mod, used in testings in order to create the pair contract.
Also, you will see that in the root folder, there is a ./soroban_token_contract.wasm file. This was taken by compiling the []soroban-examples/token contract v0.8.4](https://github.com/stellar/soroban-examples/releases/tag/v0.8.4)
2. Compile the contract
We can compile both contracts by just calling make build from the root directory, however, we can go contract by contract:
cd pair
make build
3. Read and run the tests:
maketest
4.- Experiment with the SoroswapFactory contract using the soroban CLI:
You can see the followng step-by-step. However, if you decide you can read and just run the initialize_factory.sh contract:
bash initialize_pair.sh
1.- First, set your enviromental variables
Here, as we are using the soroban-network docker network, containers can call each other just using their name. In the case of the stellar quickstart container, it's name is stellar:
Choose your network. In this example we will use standalone, but you can also use futurenet:
NETWORK="standalone"
Then:
SOROBAN_RPC_HOST="http://stellar:8000"SOROBAN_RPC_URL="$SOROBAN_RPC_HOST/soroban/rpc"SOROBAN_NETWORK_PASSPHRASE="Standalone Network ; February 2017"FRIENDBOT_URL="$SOROBAN_RPC_HOST/friendbot"echoAddthe $NETWORK networktocliclientsorobanconfignetworkadd"$NETWORK" \--rpc-url"$SOROBAN_RPC_URL" \--network-passphrase"$SOROBAN_NETWORK_PASSPHRASE"echoCreatethetoken-adminidentitysorobanconfigidentitygeneratetoken-adminTOKEN_ADMIN_SECRET="$(sorobanconfigidentityshowtoken-admin)"TOKEN_ADMIN_ADDRESS="$(sorobanconfigidentityaddresstoken-admin)"echo"We are using the following TOKEN_ADMIN_ADDRESS: $TOKEN_ADMIN_ADDRESS"echo"$TOKEN_ADMIN_SECRET">.soroban/token_admin_secretecho"$TOKEN_ADMIN_ADDRESS">.soroban/token_admin_addressechoFundtoken-adminaccountfromfriendbotechoThiswillfailiftheaccountalreadyexists,butit\' stillbefine.curl-XPOST"$FRIENDBOT_URL?addr=$TOKEN_ADMIN_ADDRESS"ARGS="--network $NETWORK --source token-admin"echo"Using ARGS: $ARGS"
2.- Let's create two dummy tokens:
We need to create 2 tokens in order to interact with the Pair contract
Because the Pair token always uses token_a and token_b so token_a<token_b, this is something we need to check before initializing the pair contract with our two tokens. Later, this is something that will be done automatically by the Factory contract:
if [[ "$TOKEN_B_ID">"$TOKEN_A_ID" ]]; thenecho"TOKEN_B_ID is greater than TOKEN_A_ID"echo"This is the correct order"elseecho"TOKEN_B_ID is less than or equal to TOKEN_A_ID"echo"We will invert the order of the tokens" TOKEN_A_ID_NEW=$TOKEN_B_ID TOKEN_B_ID=$TOKEN_A_ID TOKEN_A_ID=$TOKEN_A_ID_NEWfiechoCurrentTOKEN_A_ID: $TOKEN_A_IDechoCurrentTOKEN_B_ID: $TOKEN_B_IDecho"--"echo"--"echo-n"$TOKEN_A_ID">.soroban/token_a_idecho-n"$TOKEN_B_ID">.soroban/token_b_id
3.- Build, deploy and initialize the Pair contract
echoBuildtheSoroswapPaircontractcdpairmakebuildcd.. PAIR_WASM="pair/target/wasm32-unknown-unknown/release/soroswap_pair_contract.wasm"echo"--"echoDeploythePair PAIR_ID="$(sorobancontractdeploy $ARGS --wasm $PAIR_WASM)"echo"$PAIR_ID">.soroban/pair_wasm_hashecho"SoroswapPair deployed succesfully with PAIR_ID: $PAIR_ID"echo"--"echo"Initialize the Pair contract using the Admin address as Factory"echo"Calling: fn initialize_pair( e: Env, factory: Address, token_a: BytesN<32>, token_b: BytesN<32>);"sorobancontractinvoke \ $ARGS \--wasm $PAIR_WASM \--id $PAIR_ID \-- \initialize_pair \--factory"$TOKEN_ADMIN_ADDRESS" \--token_a"$TOKEN_A_ID" \--token_b"$TOKEN_B_ID"
4.- Creare a USER account and mint tokens to that account.
echoInthefollowingwearegoingtouseanewUSERaccount:echoCreatingtheuseridentitysorobanconfigidentitygenerateuser USER_SECRET="$(sorobanconfigidentityshowuser)" USER_ADDRESS="$(sorobanconfigidentityaddressuser)"echo"We are using the following USER_ADDRESS: $USER_ADDRESS"echo"$USER_SECRET">.soroban/user_secretecho"$USER_ADDRESS">.soroban/user_addressechoFunduseraccountfromfriendbotechoThiswillfailiftheaccountalreadyexists,butit\' stillbefine.curl-XPOST"$FRIENDBOT_URL?addr=$USER_ADDRESS"echo"Mint 1000 units of token A user -- calling from TOKEN_ADMIN"sorobancontractinvoke \ $ARGS \--wasm $TOKEN_WASM \--id $TOKEN_A_ID \-- \mint \--admin"$TOKEN_ADMIN_ADDRESS" \--to"$USER_ADDRESS" \--amount"1000"echo"Mint 1000 units of token B to user"sorobancontractinvoke \ $ARGS \--wasm $TOKEN_WASM \--id $TOKEN_B_ID \-- \mint \--admin"$TOKEN_ADMIN_ADDRESS" \--to"$USER_ADDRESS" \--amount"1000"echo"Check that user has 1000 units of each token"echo"Check TOKEN_A"sorobancontractinvoke \ $ARGS \--wasm $TOKEN_WASM\--id $TOKEN_A_ID \-- \balance \--id $USER_ADDRESSecho"Check TOKEN_A"sorobancontractinvoke \ $ARGS \--wasm $TOKEN_WASM\--id $TOKEN_B_ID \-- \balance \--id $USER_ADDRESS
5.- Deposit tokens in the PAIR contract
Now is the fun part! Interacting with our pair contract!!!
echo"Deposit these tokens into the Pool contract"echo"This will be called by the user" ARGS_USER="--network $NETWORK --source user"echo"Hence we use ARG_USER: $ARGS_USER"echo"Calling: fn deposit( e: Env, to: Address, desired_a: i128, min_a: i128, desired_b: i128, min_b: i128)"sorobancontractinvoke \ $ARGS_USER \--wasm $PAIR_WASM \--id $PAIR_ID \-- \deposit \--to"$USER_ADDRESS" \--desired_a100 \--min_a100 \--desired_b100 \--min_b100
After this, you should receive a sucess message... But how do we know that we actually deposited 100 units of each token? The user shoud have new pair tokens, and it should have 100 token_a less and 100 token_b less!
Once the SoroswapPair contract (which is a liquidity pool) has been initialized with some units of token_a and token_b, any user can perform a trade executing the swap function.
Here we will call the fn swap(e: Env, to: Address, buy_a: bool, out: i128, in_max: i128) function. If "buy_a" is true, the swap will buy token_a and sell token_b. This is flipped if "buy_a" is false "out" is the amount being bought, with in_max being a safety to make sure you receive at least that amount. The swap function will transfer the selling token "to" to this contract, and then the contract will transfer the buying token to "to".