본문 바로가기
BlockChain

Solidity개념 (delete연산자까지)

by hyun-am 2019. 5. 25.

Solidity 개념

Solidity란?

  • solidity란 계약 지향 프로그래밍 언어로 다양한 블록체인 플랫폼의 스마트계약 작성 및 구현에 사용됩니다.
  • 이더리움 핵심 기여자들이 이더리움과 같은 블록체인 플랫폼 상에 스마트계약 작성 할 수 있도록 개발하였다.

Solidity 특성

  • 솔리디티는 정적타입의 프로그래밍 언어로 EVM상에서 작동하느 스마트계약을 개발하기 위해 설계되었습니다.
  • 솔리디티는 EVM에서 작동 가능한 바이트 코드로 컴파일 됩니다.
  • 개발자는 솔리디티를 통해서 스스로 실행되는 비즈니스 로직을 스마트 계약에 담아서 Application을 구현할 수 있습니다.
  • 솔리디티와 같은 구체적인 스마트계약용 언어를 사용한 스마트 계약의 작성은 프로그래밍 기술을 보유한 사람들에게는 어렵지 않은 것으로 보입니다.

Solidity 스마트 컨트랙트 구조

// 1. 컨트랙트 선언
contract Sample {
    // 2. 상태 변수 선언
    uint256 data;
    address owner;

    // 3. 이벤트 정의
    event logData(uint256 dataToLog);

    // 4. 함수 변경자 정의
    modifier onlyOwner() {
        if(msg.sender != owner) throw;
        _;
    }

    // 5. 생성자
    function Sample(uint256 initData, address initOwner) {
        data = initData;
        onwer = initOwner;
    }

    // 6. 함수(메소드) 정의
    function getData() returns (uint256 returned) {
        return data;
    }
    function setData(uint256 newData) onlyOwner {
        logData(newData);
        data = newData;
    }
}

데이터 위치

솔리디티의 변수는 컨텍스트에 따라 메모리 또는 파일 시스템에 저장됩니다. 그러나 문자열, 배열, 구조체와 같은 복합 유형의 경우 이더 스토리지 또는 메모리를 유형에 추가해 정의할 수 있습니다.

  • 상태 변수 : contract 최상단에 선언된 변수(스토리지에 저장)
  • 로컬 변수 : 함수 아래에 선언된 변수(스토리지에 저장 / memory 키워드로 메모리 저장 가능)

다른 데이터 유형은 무엇인가?

솔리디티는 정적 유형의 언어이다. 솔리디티에서 변수의 범위는 함수이다. 즉, 변수 선언 위치와 상관없이 함수 안 어디에서든 사용할 수 있다. 데이터 유형은 아래와 같다.

  • bool(true or false)
  • uint8, uint16, uint24, ~ uint256(부호 없는 8, 16, 24, ... 비트의 정수)
  • ufixed0x8, ufixed0x16, ..., ufixed0x256(부호 없는 실수)
  • fixed0x8, fixed0x16, ..., fixed0x256(부호 있는 실수)
  • address(16진수 할당, 최대 20바이트 저장. 이더리움의 주소 제공)
    • balancesend 속성 제공. balance는 계정의 잔액을 확인하고, send는 주소로 이더를 송금하는데에 사용한다.

배열

솔리디티는 일반 및 바이트 배열을 모두 지원하며, 정적 배열동적 배열, 다차원 배열을 지원한다. 일반 배열은 다음과 같이 사용할 수 있다.

contract sample {
    // 동적 배열
    // 배열 리터럴이 보일 때마다 새로운 배열 생성
    // 배열 리터럴이 명시되어 있으면 스토리지에 저장되고, 함수 내부에서 발견되면 메모리에 저장된다.
    int[] myArray = [0, 0];
    function sample(uint index, int value) {
        myArray[index] = value;

        // myArray2는 myArray의 포인터를 저장!
        int[] myArray2 = myArray;
        // 메모리 내 고정된 크기의 배열
        uint24[3] memory myArray3 = [1, 2, 99999];
        // myArray4에 메모리에 있는 값을 스토리지에 할당할 수 없으므로 예외가 발생한다.
        // memory를 이용, 메모리에 할당해 주어야 에러가 없다.
        uint8[2] myArray4 = [1, 2];
    }
}

문자열

문자열의 길이는 언제나 동적으로 할당된다.

  • bytes : 원시 문자열(raw string)을 만드는 데 사용된다.

  • string : UTF-8 문자열을 만드는 데 사용된다.

    contract sample {

      // 문자열 리터럴이 있으므로 스토리지에 저장
      string myString = "";
      // 문자열 리터럴이 없어서 myRawString은 memory에 있다.
      bytes myRawString;
    
      function sample(string initString, bytes rawStringInit) {
          // 스토리지
          myString = initString;
    
          // myString2에 myString의 포인터를 저장
          string myString2 = myString
    
          // myString3은 메모리 내의 문자열
          string memory myString3 = "ABCDE";
    
          // 길이 및 내용 변경
          // myString3은 메모리에 위치해서 에러 X
          myString3 = "XYZ";
          myRawString = rawStringInit;
    
          // myRawString의 길이 증가
          myRawString.length++;
    
          // 메모리에 있는 "Example"을 스토리지의 myString에 저장하려 해서 에러 발생
          string myString4 = "Example";
          // 메모리에 있는 매개 변수(initString)을 스토리지의 myString5에 저장하려 해서 에러 발생
          string myString5 = initString;
      }

    }

구조체

  • 함수 외부에서 구조체 메소드 명시 : 스토리지 저장

  • 함수 내부에서 구조체 메소드 명시 : 메모리 저장

    contract sample {

      struct myStruct {
          bool myBool;
          string myString;
      }
      // s1은 메모리에 있다. (구조체 메소드 명시 x)
      myString s1;
    
      // 스토리지에 인스턴스 저장
      myStruct s2 = myStruct(true, "");
      function sample(bool initBool, stirng initString) {
          // 메모리에 인스턴스 저장
          s1 = myStruct(initBool, initString);
          mySturct memory s3 = myStruct(initBool, initString);
      }

    }

열거형

contract sample {
    enum OS { windows, Linux, OSX, UNIX }

    OS choice;

    function sample(OS chosen) {
        choice = chosen;
    }

    function setLinuxOS() {
        choice OS.Linux;
    }

    function getChoice() returns (OS chosenOS) {
        return choice;
    }
}

매핑

스토리지에만 사용할 수 있기 때문에 오직 상태 변수로만 선언된다. 매핑은 키-값의 쌍으로 이루어진 해시 테이블이다. 키는 실제로 저장되지 않고, 키의 keccak256 해시 값이 검색에 사용된다. 매핑은 길이를 가지지 않으며, 다른 매핑에 할당될 수 없다.

contract sample {
    mapping (int => string) myMap;

    function sample(int key, string value) {
        myMap[key] = value;

        // myMap2는 myMap의 참조다
        mapping(int => string) myMap2 = myMap;
    }
}

delete 연산자

delete는 어떤 변수라도 기본 값으로 재설정하기 위해 사용될 수 있다.

동적 배열에 delete를 적용하면 모든 요소가 지워지고 길이가 0이 된다. 정적 배열에 적용하면 모든 인덱스가 재설정된다. 물론 특정 인덱스에만 적용하는 것도 가능하다.

맵에 delete를 적용하면 아무 일도 발생하지 않지만, 맵의 key에 delete를 적용하면 키와 연관된 값이 삭제된다.

contract sample {
    struct Struct {
        mapping (int => string) myMap;
        int myNumber;
    }

    int[] myArray;
    Struct myStruct;

    // 생성자
    function sample(int key, int value, int number, int[] array) {
        myStruct = Struct(number);
        myStruct.myMap[key] = value;
        myArray = array;
    }

    function reset() {
        delete myArray;
        // myNumber는 0이나 myMap은 그대로
        delete myStruct;
    }

    function deleteKey(int key) {
        // 여기에서 myMap의 key 삭제
        delete myStruct.myMap[key];
    }
}

'BlockChain' 카테고리의 다른 글

이더리움 플랫폼  (0) 2021.06.06
디앱(DApp)이란?  (1) 2019.06.26
블록체인이란?  (0) 2019.05.25

댓글