[Solidity] Data types

Seokhun Yoon·2022년 2월 14일
0
post-thumbnail

1. Value Types

value type의 변수들은 단일 메모리 공간인 EVM stack에 저장된다.
함수의 인자로 사용되는 경우, 값을 복사해서 전달한다.
따라서 함수 내에서 값을 아무리 바꿔도 원래 변수의 값은 변하지 않는다.

1-1. Boolean type

논리식은 반드시 true 또는 false로 표현돼야 한다.
주의!! 0 또는 1로 정의할 수 없다!

연산자

  • ! : 논리적 부정
  • && : AND
  • || : OR
  • == : 같다
  • != : 다르다

1-2. Integer type

부호

  • int : 부호 있음, -128~127
  • uint : 부호 없음, 0~255

비트

  • int8, int16, int32, int64, int256 (== int)
  • uint8, uint16, uint32, uint64, uint256 (== uint)

좌변의 타입 크기가 우변의 타입 크기보다 크면 타입이 달라도 같이 사용이 가능하다.
그러나 우변의 타입 크기가 더 크다면 같이 사용할 수 없다.

연산자

  • 비교 : <=, <, ==, !=, >=, >
  • 비트 연산 : &, |, ^ (XOR), ~ (부정)
  • 시프트 연산 : <<, >>
  • 사칙 연산 : +, -, /, % (나머지), ** (제곱)

1-3. Fixed-size byte arrays

1~32bytes 크기로 고정 크기의 바이트 배열을 선언할 수 있다.

  • bytes1 (== bytes), bytes2, ..., bytes32
    1바이트의 배열을 사용할 경우, bytes1 보다 bytes를 사용하는 것이 낫다.
    (padding rules에 의해 bytes1가 실제로 1바이트만 사용하지만 32바이트를 차지함)

연산자

  • 비교 : <=, <, ==, !=, >=, >
  • 비트 연산 : &, |, ^ (XOR), ~ (부정)
  • 시프트 연산 : <<, >>
  • 인덱스 접근 : 예를 들어 xbytes32인 경우, x[k] (0<=k<32)로 각 바이트를 출력할 수 있다.

[참고]
Dynamically-size byte arrays
(동적 바이트 배열은 Value-type이 아님!)

  • bytes : 동적으로 크기를 갖는 바이트 배열
  • string : 동적으로 크기를 갖는 UTF-8 인코딩된 문자열

1-4. Address

  • 0x로 시작하는 최대 40자리 16진수 문자열 (크기: 20바이트)
  • sha3 해시 함수를 통해 생성된다.
  • 알파벳 대소문자를 구분한다.
  • address 타입에 제공되는 함수들
함수명설명
balance()해당 주소의 잔액 (Wei 단위)
transfer()- 지정된 양의 Ether를 주소로 전송하는 함수 (Wei 단위)
- 전송 실패시 자동으로 이전 상태로 되돌린다.
- 소모 가스 : 2300 gas, 조정 불가
send()- Ether를 보내는 함수
- 전송 실패시 false값만 반환할 뿐, 자동으로 지불이 취소되지 않는다. (직접 revert를 해줘야함)
- 소모 가스 : 2300 gas, 조정 불가
call()- success condition과 return data를 반환한다.
- 소모 가스 : 조정 가능, 제한 없음

send() 사용시 주의점
호출 스택의 depth가 1024면 전송이 실패하는데 호출한 사람이 이를 의도할 수 있다.
또한, 가스가 소진되면 전송이 실패하기 때문에 안정적인 전송이 어렵다.
send()를 사용하려면 리턴값을 항상 확인하고 revert()를 넣어주자.
그래도 웬만하면 transfer()와 같이 더 좋은 함수를 사용하는 것이 낫다.

call() 사용시 주의점
다른 컨트랙트 함수를 실행할 때 형식 검사, 함수 존재 검사, 인수 패킹을 우회하므로 call()은 사용하지 않는 것이 좋다.


1-5. Enums

유한한 상수값을 이용해서 사용자 지정 형식을 만든다.

아래 예시를 보면, Low, Medium, High 순서로 0, 1, 2의 값이 부여된다.

enum InvestmentLevel {Low, Medium, High}			
InvestmentLevel level = InvestmentLevel.Medium; 	// level = 1



2. Reference Types

reference type의 변수는 그 값이 저장된 주소를 통해 접근한다.
이런 변수들은 세가지 타입의 데이터 영역에 저장할 수 있다.

  • memory : 값을 영구적으로 보존되지 않고 메모리에서만 존재한다.
  • storage : state 변수 처럼 블록체인에 영구적으로 저장한다.
  • calldata : 오직 external 함수의 파라미터에서만 사용할 수 있다. 수정이 불가능하고 영구 보존이 되지않는 영역으로 memory와 비슷하게 동작한다.
CaseData location
Local variableMemory or Storage
State variableOnly Storage
Parameter of internal functionMemory or Storage or Calldata

2-1. Arrays

2-1-1. Static Arrays

선언시 배열의 크기를 지정한다.

  1. 선언 후 값 할당하는 방법

    function f() {
        int32[5] memory fixedArray;
        fixedArray[0] = 5;
    }
  2. 인라인으로 할당하는 방법

    function f() {
      	int32[5] memory fixedArray = [int32(5), 9, 1, 3, 4];
    }

2-1-2. Dynamic Arrays

선언시 배열의 크기를 지정할 필요가 없다.
항목을 추가하려면 push()를 사용한다.

    // 배열에 항목 추가
    dynamicArray.push(2);

데이터 영역에 따라 크기 조정 방식이 다르다.

  1. storage 일때

    function f() {
        int32[] dynamicArray; 		// 암시적으로 스토리지 영역 사용
        dynamicArray.length = 5; 	// 배열 길이 재설정
    }
  2. memory 일때

    function f() {
        int32[] memory dynamicArray; 	// 명시적으로 메모리 영역 사용
        ...
        dynamicArray = new int32[](5); 	// 새로 생성해서 크기 조정
    }

2-2. String

bytes와 동일하지만 lengthpush() 멤버가 없다.

string name = "SOKURI";

2-3. Struct

struct는 서로 다른 데이터 타입의 항목을 포함하는 집합 타입으로, 사용자 정의 타입이다.

// 구조체 정의
struct Candidate {
	address account;
    string description;
}
// 구조체 초기화
function addCandidate(address candidateAddress, string candidateDescription) {
	Candidate memory candidate = Candidate({account:candidateAddress, description:candidateDescription});
}

2-4. Mapping

스토리지 데이터 영역에서만 사용할 수 있다.
상태변수 또는 스토리지 참조형으로만 선언할 수 있다.
해시 테이블로 키에 대응하는 값을 저장한다.
keyvalue의 유형을 반드시 선언해야 한다.

mapping(address => int) public coinBalance;
profile
블록체인 개발자를 꿈꾸다

0개의 댓글