Move - 1 [Aptos]

_Block·2022년 12월 1일
1

Aptos

목록 보기
1/1
post-thumbnail

🐾 개요

Move에 대해서 학습을 하고 있습니다.

개인적으로 예전에 Aptos,Sui 쪽에 관심을 가지고 있어서 Move를 학습을 하였는데

다시 학습을 하려고 보니 너무 이해가 안가서 기록을 남기며 작성을 해나가고자 합니다.

🐾 CLI

대표적으로 사용했던 CLI에대해서 다루어 볼 것이고 해당 주제는 계속 업데이트가 가능합니다.

Aptos move init

  • Apots 프로젝트를 생성 합니다.
  • --name <이름>을 통해서 프로젝트 이름을 설정 합니다.

Aptos move compile

  • 일반적으로 compile을 할떄에 사용이 되는 명령어 입니다.

Aptos move test

  • 테스트 코드를 작성하고 테스트를 실행시킬떄 사용합니다.

Aptos move publish

  • 코드를 배포할떄 사용을 하는 명령어입니다.
  • 현재에는 에러가 발생을 하고 있어서 해결이 되면 추가 업로드 하도록 하겠습니다.

🐾 기본 코인 Contract

module BasicCoin::BasicCoin {
    use std::signer;

    struct Coin<phantom CoinType> has store{
        value : u64
    }

    struct Balance<phantom CoinType> has key {
        coin : Coin<CoinType>
    }

    public fun publish_balance<CoinType>(account :  &signer) {
        let empty_coin = Coin<CoinType> {value : 0};
        assert!(!exists<Balance<CoinType>>(signer::address_of(account)), 0);
        move_to(account, Balance<CoinType> {coin : empty_coin});
    }

    public fun mint<CoinType : drop>(mint_addr : address, amount : u64, _witness : CoinType) acquires Balance {
        deposit(mint_addr, Coin<CoinType>{value :amount});
    }

    public fun balance_of<CoinType>(owner : address) : u64 acquires Balance{
        borrow_global<Balance<CoinType>>(owner).coin.value
    }

    public fun transfer<CoinType : drop>(from : &signer, to : address, amount : u64, _witness:CoinType) acquires Balance {
        let from_addr = signer::address_of(from);
        assert!(from_addr != to, 0);

        let check = withdraw<CoinType>(from_addr, amount);
        deposit<CoinType>(to, check);
    }

    public fun withdraw<CoinType>(addr : address, amount : u64) : Coin<CoinType> acquires Balance {
       let balance = balance_of<CoinType>(addr);
        assert!(balance >= amount, 0);
        let balance_ref = &mut borrow_global_mut<Balance<CoinType>>(addr).coin.value;
        *balance_ref = balance - amount;
        Coin<CoinType> { value: amount }
    }

     fun deposit<CoinType>(addr: address, check: Coin<CoinType>) acquires Balance{
        let balance = balance_of<CoinType>(addr);
        let balance_ref = &mut borrow_global_mut<Balance<CoinType>>(addr).coin.value;
        let Coin { value } = check;
        *balance_ref = balance + value;
    }

}
  • 공식 문서에 나와있는 코드 입니다.

use std::signer

기본적인 모듈중 signer라는 모듈을 사용한다는 의미 입니다.
std를 통해서 aptos에서 제공하는 기본적인 모듈을 사용 가능합니다.
Move.toml확인
해당 모듈에서는 특정 account에 대한 주소값들을 확인하는 함수들이 있습니다.

struct

저희가 일반적으로 알고 있는 struct입니다.
Move에서는 해당 구조체에 다양한 특성들이 추가가 가능합니다.

  • copy, store, key, drop

각각의 값들은 이름을 대변하며 추가적인 정보는 해당 링크를 참고하면 됩니다.


public fun publish_balance<CoinType>(account :  &signer) {
        let empty_coin = Coin<CoinType> {value : 0};
        assert!(!exists<Balance<CoinType>>(signer::address_of(account)), 0);
        move_to(account, Balance<CoinType> {coin : empty_coin});
}

Move에서는 특이하게도 특정 값을 미리 형성을 해주어야 합니다.

  • 그 생성된 값을 이후 mint, transfer에서 사용을 하는 구조 입니다.

일반적으로 Solidity에서 constructor와 같이 동작을 하는 것으로 이해를 하면 됩니다.

일단 empty_coin이라는 값을 생성해 줍니다.
해당 값은 Coin이라는 구조체를 의미하며, 내부의 값은 0으로 설정이 됩니다.

이떄 assert를 통해서 만약 신청하는 account가 이미 Coin이라는 값이 있는지를 체크 합니다.

  • 이 부분에서 많이 헷갈렸는데, Solidity에서는 일반적으로 msg.sender라는 값을 통해서 sender를 인식하지만 move에서는 이런식으로 sender값이 들어가게 됩니다.

그후 해당 값을 들어온 address에 할당해 줍니다.

  • 참고로 signer::address_of(account)값은 sender의 address를 return합니다.

public entry fun mint<CoinType : drop>(mint_addr : address, amount : u64, _witness : CoinType) acquires Balance {
        deposit(mint_addr, Coin<CoinType>{value :amount});
}

그후 mint를 실행시키는 함수 입니다.

  • 특정 owner 권한이 없기 떄문에 Balance라는 object만 생성이 되어 있다면 누구나 실행 가능합니다.

_witness를 통해서 어떠한 object = Coin이 사용될지를 정의내리며, drop 옵션을 추가하여 사용되지 않은 _witness를 DROP 시켜 줍니다.


 public entry fun balance_of<CoinType>(owner : address) : u64 acquires Balance{
        borrow_global<Balance<CoinType>>(owner).coin.value
    }

특정 address의 balance를 조회하는 함수 입니다. return타입이 존재하기 떄문에 : u64가 추가된 모습이며,

단순히 값을 보는 역할을 수행하기 떄문에 borrow_global이 사용되었습니다.


 public entry fun transfer<CoinType : drop>(from : &signer, to : address, amount : u64, _witness:CoinType) acquires Balance {
        let from_addr = signer::address_of(from);
        assert!(from_addr != to, 0);

        let check = withdraw<CoinType>(from_addr, amount);
        deposit<CoinType>(to, check);
    }

특정 address에서 다른 address로 전송을 하는 함수 입니다.

signer을 통해서 transaction실행자를 가져올 수있으며, 어떤 obejct를 사용할건지에 대해서 mint와 동일하게 witness를 추가하였습니다.


 public fun withdraw<CoinType>(addr : address, amount : u64) : Coin<CoinType> acquires Balance {
       let balance = balance_of<CoinType>(addr);
        assert!(balance >= amount, 0);
        let balance_ref = &mut borrow_global_mut<Balance<CoinType>>(addr).coin.value;
        *balance_ref = balance - amount;
        Coin<CoinType> { value: amount }
    }

entry 함수가 아니기 떄문에 외부에서 바로 실행이 불가능한 함수 입니다.

기본적으로 transfer에서 사용이 되며, balance를 수정하는 역할을 수행 합니다.

현재 addr의 밸런스를 조회하고, 검증을 한뒤에 mut타입으로 바꾸어서 값을 수정을 합니다.

  • transfer함수에서 sender의 실질적인 balance는 여기에서 수정이 됩니다.
  • *balance_ref = balance - amount

fun deposit<CoinType>(addr: address, check: Coin<CoinType>) acquires Balance{
        let balance = balance_of<CoinType>(addr);
        let balance_ref = &mut borrow_global_mut<Balance<CoinType>>(addr).coin.value;
        let Coin { value } = check;
        *balance_ref = balance + value;
    }

transfer 함수에서 수령자에게 balance를 증가시키는 함수 입니다.
withdraw함수와 유사하게 동작을 하기 떄문에 추가적인 설명은 하지 않겠습니다.

🐾 마무리

기본적으로 간단한 Contract에 대해서 알아보았습니다.

물론 설명이 부족한 부분도 있겠지만 현재 어떠한 것에 집중을 해야하는지에 대해서 고민을 하고 있는 시점이여서 크게 맘이 안가는 것도 사실입니다..

현재 생각하고 있는 기준은 Go에 대해서 다시 학습을 진행을 하고, 추가로 Move를 함께 학습을 진행해볼 예정입니다.

profile
Block_Chain 개발자 입니다. 해당 블로그는 네트워크에 관한 내용을 다루고 있습니다.

0개의 댓글