Rust Stella Soroban Basic

이정후·2023년 9월 7일
0

Rust

목록 보기
13/13

Soroban은 Stellar Rust로 만들어진 Smart Contract 플랫폼이다.
WASM과 Rust기반으로 전송 분야에 특화되어 있는 스텔라 블록체인에서 최근에 발표된 프로젝트다.

Solidity와 다르게 어떤 식으로 컨트랙트를 작성하는지 비교해보고자 한다.

Setting

Install target

rustup target add wasm32-unknown-unknown

Install Soroban CLI

cargo install --locked --version 0.9.4 soroban-cli

Usage

soroban
$ soroban
Build, deploy, & interact with contracts; set identities to sign with; configure networks; generate keys; and more.

Intro: https://soroban.stellar.org
CLI Reference: https://github.com/stellar/soroban-tools/tree/main/docs/soroban-cli-full-docs.md

Usage: soroban [OPTIONS] <COMMAND>

Commands:
  contract    Tools for smart contract developers
  config      Read and update config
  events      Watch the network for contract events
  lab         Experiment with early features and expert tools
  version     Print version information
  completion  Print shell completion code for the specified shell

Options:
      --global                     Use global config
  -f, --filter-logs <FILTER_LOGS>  Filter logs output. To turn on "soroban_cli::log::footprint=debug" or off "=off". Can also use env var `RUST_LOG`
  -q, --quiet                      Do not write logs to stderr including `INFO`
  -v, --verbose                    Log DEBUG events
      --very-verbose               Log DEBUG and TRACE events
      --list                       List installed plugins. E.g. `soroban-hello`
  -h, --help                       Print help (see more with '--help')
  -V, --version                    Print version

TESTING_OPTIONS:
      --config-dir <CONFIG_DIR>

작업환경 세팅

cargo new --lib 프로젝트명

Cargo.toml

// Cargo.toml

...

[lib]
crate-type = ["cdylib"]

[features]
testutils = ["soroban-sdk/testutils"]

[dependencies]
soroban-sdk = "0.9.2"

[dev_dependencies]
soroban-sdk = { version = "0.9.2", features = ["testutils"] }

[profile.release]
opt-level = "z"
overflow-checks = true
debug = 0
strip = "symbols"
debug-assertions = false
panic = "abort"
codegen-units = 1
lto = true

[profile.release-with-logs]
inherits = "release"
debug-assertions = true

profile.release는 contract build를 최적화 하기 위해 생성한다. soroban의 contract 최대 크기는 256KB이지만, 위 설정이 없는 Rust 프로그램은 거의 이 크기를 초과한다고 한다.

Contract 작성

// lib.rs
#![no_std]

Rust std가 Build에 포함되지 않도록 설정해준다. std의 크기가 크기때문에 블록체인상에 배포되는 것과 같은 상황에는 적합하지 않다고 한다.

use soroban_sdk::{contract, contractimpl, symbol_short, vec, Env, Symbol, Vec};

크레이트에서 필요한 macro와 soroban-sdk를 가져와야 한다.

또한 Rust에서 처럼 std::vec::Vec과 같은 힙 할당자와 메모리가 없기때문에 사용할 수 없고 자체적으로 네이티브 기능을 제공하는 Vec, Map, Bytes, Symbol과 같은 타입들을 제공한다.

Floats와 부동 소수점 연산은 지원되지 않는다고 한다.

#[Contract]

#[contract]
pub struct Contract;

#[contractimpl]
impl Contract {
	pub fn hello(env: Env, to: Symbol) -> Vec<Symbol> {
    	todo!()
    }
}

#[contract]속성은 Contract 구조체를 계약 기능이 연결된 유형으로 지정한다. impl이 들어갔으니 유추 가능하겠지만, #[contractimpl]은 계약 구조체에 계약 기능을 구현하는 부분이다.

또한 함수가 외부에서 호출되도록 의도적으로 pub 키워드로 만들어야 한다.
Env는 soroban 환경에 대한 엑세스를 허용하는 유형이다.

#![no_std]
use soroban_sdk::{contract, contractimpl, symbol_short, vec, Env, Symbol, Vec};

#[contract]
pub struct Contract;

#[contractimpl]
impl Contract {
    pub fn greet(env: Env, to: Symbol) -> Vec<Symbol> {
        vec![&env, symbol_short!("Hello"), to]
    }
}

Symbol은 짧은 문자열을 표시한다. 유효한 문자는 a-z, A-Z, 0-9까지 이며 최대 길이는 32자이다.
또한 함수명이나 struct, enum 식별자에 사용되어 길이가 제한되었다고 한다. 최대가 32자이나 9자 미만일 경우 런타임에 더 효율적이며 컴파일 타임에도 차이가 있다고 한다.

Testing

test.rs 파일을 생성해준다.

// test.rs
use crate::{Contract, ContractClient};
use soroban_sdk::{symbol_short, vec, Env};

#[test]
fn greet() {
    let env = Env::default();
    let contract_id = env.register_contract(None, Contract);
    let client = ContractClient::new(&env, &contract_id);

    let words = client.greet(&symbol_short!("Dev"));
    assert_eq!(
        words,
        vec![&env, symbol_short!("Hello"), symbol_short!("Dev"),]
    );
}

모든 테스트에서 필요한 것은 컨트랙트 내부에서 실행되는 soroban 환경인 Env를 만들어줘야 한다.

let env = Env::default();

컨트랙트는 컨트랙트 타입을 이용해 테스트 환경에 적용하는데, 컨트랙트의 register_contract의 첫 번째 인자로 계약자의 ID를 명시해주거나 None을 넣을 수 있다. None이 들어가면 ID가 새로 생성된다.

let contract_id = env.register_contract(None, Contract);

lib.rs에서 impl로 구현한 컨트랙트의 이름은 Contract였다. client를 생성할때컨트랙트명client:new()를 사용하면 될 것 같다.

let client = ContractClient::new(&env, &contract_id);
let words = client.hello(&symbol_short!("Dev"));

test 실행

cargo test
soroban contract build // equal, cargo build --target wasm32-unknown-unknwon --release

빌드가 완료되면 파일명과 동일한 wasm 파일이 생성된다.

soroban contract invoke \
    --wasm target/wasm32-unknown-unknown/release/[project-name].wasm \
    --id 1 \
    -- \
    greet \
    --to friend

to의 인자로 friend를 보내주면 vec!에 "Hello"와 "friend"가 담겨서 출력된다.

In Solidity

Solidity에서는 우선 작성하는 Solidity의 버전을 명시해줘야 한다.

pragma solidity ^0.8.21;

contract 작성을 위해서는 contract라는 키워드를 사용한다.

Solidity

contract Greet {
	function greet() public pure returns (string memory) {
        return "Hello Solidity!";
    }
}

public 키워드를 통해 외부 컨트랙에서도 함수를 호출할 수 있게 해주고, pure를 통해 외부 변수들과의 관계없이 내부요소들만 사용한다고 명시한다. 이후에 이 함수가 리턴할 반환 유형을 명시하는데 string memory 라고 작성하는 이유는 함수 실행 동안만 유효하며, 함수 호출이 완료되면 데이터가 삭제된다. 함수 내부에서 생성되고 사용되는 임시 데이터를 나타낸다.

Rust


#[contract]
pub struct Contract;

#[contractimpl]
impl Contract {
    pub fn greet(env: Env, to: Symbol) -> Vec<Symbol> {
        vec![&env, symbol_short!("Hello"), to]
    }
}

soroban은 스텔라 재단에서 만들었으며 출시된지 얼마 되지 않은듯 해보인다. Rust로 smart contract을 작성할 수 있는게 큰 매력인것 같다.

profile
꾸준하게

0개의 댓글