# BitSong Cosmwasm Testnet ## Smart Contracts Development The following are a collection of guides on how to build and deploy CoswmWasm smart contracts on the BitSong blockchain. Please note that a user can deploy contracts with tools such as Beaker or directly with the `bitsongd` binary via CLI. ## Public Endpoints | ChainID | bwasmnet-1 | | -------- | -------- | | RPC endpoint | https://rpc.bwasmnet-1.bitsong.network | | LCD endpoint | https://api.bwasmnet-1.bitsong.network | # Testnet deployment The following guide shows the basics of deploying a contract to a BitSong Cosmwasm Testnet (bwasmnet-1): - Initial setup - Setup Rust - Setup bitsong testnet - Install `bitsongd` - Setup the client - Deploy a Smart contract - Clone cw-template - Compile the wasm contract - Optimize compilation - Upload to BitSong testnet - Instantiate the contract - Exectue the contract - Get contract's count - Increment contract's count - Reset contract's count This tutorial uses a BitSong specific development tools to deploy contracts to BitSong Cosmwasm Testnet (bwasmnet-1). ## Setup rust Rust is the main programming language used for CosmWasm smart contracts. While WASM smart contracts can theoretically be written in any programming language, CosmWasm libraries and tooling work best with Rust. First, **[install rustup](https://rustup.rs/)**. Then run the following commands: ```bash= # 1. Set 'stable' as the default release channel: rustup default stable cargo version # If this is lower than 1.50.0+, update rustup update stable # 2. Add WASM as the compilation target: rustup target list --installed rustup target add wasm32-unknown-unknown # 3. Install the following packages to generate the contract: cargo install cargo-generate --features vendored-openssl cargo install cargo-run-script ``` ## Setup `bitsongd` ### From binary The easiest way to install `bitsongd` is by downloading a pre-build binary. You can find the latest binaries on the [releases page](https://github.com/bitsongofficial/go-bitsong/releases/tag/bwasmnet-1) ### From source 1. Get the `go-bitsong` source code Use `git` to retrieve `go-bitsong` and checkout the `bwasmnet-1` branch, wich contains the latest release for the bitsong testnet ``` git clone https://github.com/bitsongofficial/go-bitsong.git cd go-bitsong git checkout bwasmnet-1 ``` 2. Build `go-bitsong` ``` cd go-bitsong make install ``` 3. Verify your `go-bitsong` installation ``` $ bitsongd version bwasmnet-1 ``` ## Config `go-bitsong` 1. set the correct node address ``` bitsongd config node https://rpc.bwasmnet-1.bitsong.network:443 ``` 2. change the chain-id ``` bitsongd config chain-id bwasmnet-1 ``` 3. change the broadcast mode ``` bitsongd config broadcast-mode block ``` 4. change the kayring backend ``` bitsongd config keyring-backend test ``` ## Create your testnet wallet create a wallet with the following command: ``` bitsongd keys add mywallet ``` when you run the commands above, `bitsongd` will prompt you all the information related to that wallet ``` - name: mywallet type: local address: bitsong1a695qts2n3hx0gnqwysau2mf9nj6y6524wmz33 pubkey: '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A7s8GHBMD6FAIbTKu4JiimHpey6++/zY7lPa9Th41TWt"}' mnemonic: "" **Important** write this mnemonic phrase in a safe place. It is the only way to recover your account if you ever forget your password. parent seat survey cook culture pen green ripple advance increase exile curtain carpet orient teach pizza eager large forest author husband mouse lucky extend ``` ## Get testnet faucet tokens You can request tokens from the official [BitSong Discord](https://discord.bitsong.io) server by sending the following message on the `#testnet-faucet` channel: ``` !faucet <address> ``` [TODO: add img] Then you can check that your balance fo your wallet account by typing the command: ``` bitsongd query bank balances $(bitsongd keys show -a mywallet) ``` ## Deploy a Smart Contract ### Clone cw-contracts For this example, we will use the [cw-template](https://github.com/bitsongofficial/cw-template) repo with counter example. ``` cargo generate --git https://github.com/bitsongofficial/cw-template.git --name my-first-contract ``` Select `false` ``` 🔧 Destination: /home/angelo/Progetti/my-first-contract ... 🔧 Generating template ... ? 🤷 Would you like to generate the minimal template? The full template includes some example logic in case you're new to CosmWasm smart contracts. The minimal template assumes you already know how to write your own logic, and doesn't get in your way. › ❯ false true ``` ``` cd my-first-contract ``` ### Compile the wasm contract To deploy smart contracts, you must compile the code and make it an executable wasm binary file. We will compile the wasm contract with stable toolchain. Compile using the command below: ``` # Set 'stable' as the default release channel: rustup default stable cargo wasm ``` After this compiles, it should produce a file in `target/wasm32-unknown-unknown/release/my_first_contract.wasm`. If you check the size of the file by using the `ls -lh` command, it shows around `1.9M`. This is a release build, but not stripped of all unneeded code. To produce a much smaller version, you can run this which tells the compiler to strip all unused code out: ``` RUSTFLAGS='-C link-arg=-s' cargo wasm ``` This produces a file about `155K`. To reduce gas costs, the binary size should be as small as possible. This will result in a less costly deployment, and lower fees on every interaction. Also, if you don’t use compilation optimization, CosmWasm smart contract will not be deployed well due to `exceeds limit` error. ### Optimized Compilation You can do further optimization using [rust-optimizer](https://github.com/CosmWasm/rust-optimizer). **rust-optimizer** produces reproducible builds of CosmWasm smart contracts and does heavy optimization on the build size, using binary stripping and `wasm-opt`. ``` docker run --rm -v "$(pwd)":/code \ --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/rust-optimizer:0.12.8 ``` Binary file will be at `artifacts/my_first_contract.wasm` folder and its size will be about `130K`, which is more smaller than when only `RUTFLAGS` was used. ### Store to BitSong Cosmwasm Testnet We have the wasm binary executable ready. Now it is time to store the code to the **BitSong Cosmwasm Testnet**. ``` RES=$(bitsongd tx wasm store artifacts/my_first_contract.wasm --from mywallet --gas-prices 0.1ubtsg --gas auto --gas-adjustment 1.3 -y --output json -b block) ``` - `bitsongd tx wasm store` : upload a wasm binary - `--from` : name or address of private key with which to sign. - `--gas-prices` : gas prices in decimal format to determine the transaction fee. - `--gas` : gas limit to set per-transaction. set to "auto" to calculate sufficient gas automatically - `--gas-adjustment` : adjustment factor to be multiplied against the estimate returned by the tx simulation. - `-y` : to skip tx broadcasting prompt confirmation. - `--output` : output format. - `-b` : transaction broadcasting mode Once that is complete, you can get the `CODE_ID` easily using `jq`. `jq` is an open source that helps extract data from JSON. Install it according to your OS using the following command: ``` # Linux sudo apt-get install jq # Mac brew install jq ``` Run the following command to set the `CODE_ID` as a variable: ``` # get CODE_ID CODE_ID=$(echo $RES | jq -r '.logs[0].events[-1].attributes[1].value') echo $CODE_ID ``` ### Instantiate the contract We can now create an instance of this wasm contract. First, set the initial state of the instance in the `INIT` variable and run the `instantiate command`. ``` # set the initial state of the instance INIT='{"count":100}' # instantiate the contract bitsongd tx wasm instantiate $CODE_ID "$INIT" \ --from mywallet --label "my first contract" --gas-prices 0.025ubtsg --gas auto --gas-adjustment 1.3 -b block -y --no-admin ``` - `bitsongd tx wasm instantiate` : instantiate a wasm contract using **CODE_ID** of the uploaded binary. - `--label` : human-readable name for this contract in lists. - `--no-admin` : you must set this explicitly if you don’t want an admin. Get the contract address using the command following: ``` CONTRACT_ADDR=$(bitsongd query wasm list-contract-by-code $CODE_ID --output json | jq -r '.contracts[0]') echo $CONTRACT_ADDR ``` ### Query the contract Now, let's see if the contract we deployed works well. #### Get contract’s count Send a `get_count` query to check the count value. The previously set `INIT` state is output as it is.: `{"data":{"count":100}}` ``` QUERY='{"get_count":{}}' bitsongd query wasm contract-state smart $CONTRACT_ADDR "$QUERY" --output json ``` The output will be ``` {"data":{"count":100}} ``` - `bitsongd query wasm contract-state smart` : calls contract with given address with query data and prints the returned result ### Execute the Contract #### Increment contract’s count This time, let's send an `increment` transaction that increases the count value by +1. Because the transaction changes the internal state of the contract, you must pay gas fees. If you run the `get_count` query again after sending the `increment` transaction, you can see that +1 has increased from the previous count value. ``` TRY_INCREMENT='{"increment": {}}' bitsongd tx wasm execute $CONTRACT_ADDR "$TRY_INCREMENT" --from mywallet --gas-prices 0.025ubtsg --gas auto --gas-adjustment 1.3 -y ``` #### Reset contract’s count Lastly, let’s send a `reset` transaction. Like increment, reset transaction also changes the internal state of contract, so you must pay gas fees. ``` RESET='{"reset": {"count": 0}}' bitsongd tx wasm execute $CONTRACT_ADDR "$RESET" --from mywallet --gas-prices 0.025ubtsg --gas auto --gas-adjustment 1.3 -y ``` ## Explorer [TODO: add explorer guide]