본문 바로가기
블록체인교육/솔리디티

[솔리디티] 5. 배열, 열거형(enum), 구조체 (calldata, memory)

by Danny_Kim 2022. 6. 8.

[NEW] 누구나 쉽게 따라하는 솔리디티 강의(솔리디티 버전 0.8.13)

1. Helloworld, 카운터컨트랙트, 데이터타입

2. 변수, 상수, 불변, 상태변수 읽고 쓰기

3. 이더 단위, 가스와 가스가격

4. 조건문, 반복문, 맵핑(mapping)

5. 배열, 열거형(enum), 구조체(calldata,memory) 

6. 데이터 저장공간, 함수(view,pure 속성)

7. 에러(error), 함수수정자(modifier)

8. 이벤트(events), 생성자(constructor), 상속

9. 상속, 섀도잉,super키워드 함수 속성들

10. 인터페이스(interface), payable, 이더전송,받기 관련

11. Fallback, Call, Delegate(솔리디티 업그레이드 기법)

12. 함수 선택자(function selector), 다른 컨트랙트 사용 및 생성기법

13. Try Catch, Import(임포트), Library(라이브러리)

14. ABI 디코드, hash 함수, 서명검증, 가스최적화

* 블록체인 전문가들도 놓치기 쉬운 비트코인, 이더리움의 핵심가치 강의

 

블록체인 전문가들도 놓치기 쉬운 비트코인, 이더리움의 핵심 가치 - 인프런 | 강의

블록체인 기획자,개발자,회사 대표라면 반드시 한번은 봐야 하는 강의입니다. 따로 공부할 시간이 없었다면, 이 요약본 강의를 통해서 비트코인,이더리움 백서의 핵심을 이해할 수 있습니다., -

www.inflearn.com

1. 배열

 1.1 솔리디티 배열

 - 솔리디티에서 배열은 정적배열(컴파일시점), 동적배열로 사용이 가능하다.

- 아래 예제에서 getArr()의 경우 전체 배열을 반환할 수 있음.

   그러나, 길이가 무한정 늘어날 수 있으므로 이러한 형태의 함수는 피해야 함.

 

push - 배열에 추가 (배열 길이가 1 증가)

pop - 배열에서 제거 (배열 길이가 1 감소)

remove - 삭제는 배열길이를 변경하진 않음. 아래 함수에서는 index의 값을 기본값으로 재설정 (이 경우 0)

example() - 메모리에 배열 생성, 정적 배열만 생성 가능

소스파일

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Array {
    // Several ways to initialize an array
    uint[] public arr;
    uint[] public arr2 = [1, 2, 3];
    // Fixed sized array, all elements initialize to 0
    uint[10] public myFixedSizeArr;

    function get(uint i) public view returns (uint) {
        return arr[i];
    }

    // Solidity can return the entire array.
    // But this function should be avoided for
    // arrays that can grow indefinitely in length.
    function getArr() public view returns (uint[] memory) {
        return arr;
    }

    function push(uint i) public {
        // Append to array
        // This will increase the array length by 1.
        arr.push(i);
    }

    function pop() public {
        // Remove last element from array
        // This will decrease the array length by 1
        arr.pop();
    }

    function getLength() public view returns (uint) {
        return arr.length;
    }

    function remove(uint index) public {
        // Delete does not change the array length.
        // It resets the value at index to it's default value,
        // in this case 0
        delete arr[index];
    }

    function examples() external {
        // create array in memory, only fixed size can be created
        uint[] memory a = new uint[](5);
    }
}

 

 1.2 솔리디티 배열 요소 제거 예제1)

 - 원하는 배열의 요소를 제거하고 이후부터 오른쪽에서 왼쪽으로 배열의 요소들을 이동

- remove() 에 입력된 배열의 데이터가 삭제되고, 배열의 데이터가 오른쪽에서 왼쪽으로 차례로 이동됨.

 - remove() 함수 활용을 위한 test() 함수 작성 후, assert() 로 동작여부 확인

 - assert()의 경우는 false일 경우 에러를 발생시키는데, 코딩 시 값 테스트를 위해서 유용하게 사용될 수 있음.

소스파일

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract ArrayRemoveByShifting {
    // [1, 2, 3] -- remove(1) --> [1, 3, 3] --> [1, 3]
    // [1, 2, 3, 4, 5, 6] -- remove(2) --> [1, 2, 4, 5, 6, 6] --> [1, 2, 4, 5, 6]
    // [1, 2, 3, 4, 5, 6] -- remove(0) --> [2, 3, 4, 5, 6, 6] --> [2, 3, 4, 5, 6]
    // [1] -- remove(0) --> [1] --> []

    uint[] public arr;

    function remove(uint _index) public {
        require(_index < arr.length, "index out of bound");

        for (uint i = _index; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr.pop();
    }

    function test() external {
        arr = [1, 2, 3, 4, 5];
        remove(2);
        // [1, 2, 4, 5]
        assert(arr[0] == 1);
        assert(arr[1] == 2);
        assert(arr[2] == 4);
        assert(arr[3] == 5);
        assert(arr.length == 4);

        arr = [1];
        remove(0);
        // []
        assert(arr.length == 0);
    }
}

 1.3  솔리디티 배열 요소 제거 예제2)

 - 원하는 배열 요소를 제거하고 제일 끝에 있는 요소를 제거한 배열로 대체

소스파일

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract ArrayReplaceFromEnd {
    uint[] public arr;

    // Deleting an element creates a gap in the array.
    // One trick to keep the array compact is to
    // move the last element into the place to delete.
    function remove(uint index) public {
        // Move the last element into the place to delete
        arr[index] = arr[arr.length - 1];
        // Remove the last element
        arr.pop();
    }

    function test() public {
        arr = [1, 2, 3, 4];

        remove(1);
        // [1, 4, 3]
        assert(arr.length == 3);
        assert(arr[0] == 1);
        assert(arr[1] == 4);
        assert(arr[2] == 3);

        remove(2);
        // [1, 4]
        assert(arr.length == 2);
        assert(arr[0] == 1);
        assert(arr[1] == 4);
    }
}

 

2. Enum(열거형)

 - 솔리디티에서는 열거형(enum)을 지원하며, 상태 추적 및 모델 선택에 유용함.

 - Enum은 컨트랙트 밖에서 선언될 수 있음

소스파일

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract Enum {
    // Enum representing shipping status
    enum Status {
        Pending,
        Shipped,
        Accepted,
        Rejected,
        Canceled
    }

    // Default value is the first element listed in
    // definition of the type, in this case "Pending"
    Status public status;

    // Returns uint
    // Pending  - 0
    // Shipped  - 1
    // Accepted - 2
    // Rejected - 3
    // Canceled - 4
    function get() public view returns (Status) {
        return status;
    }

    // Update status by passing uint into input
    function set(Status _status) public {
        status = _status;
    }

    // You can update to a specific enum like this
    function cancel() public {
        status = Status.Canceled;
    }

    // delete resets the enum to its first value, 0
    function reset() public {
        delete status;
    }
}

 

- 파일형태로 enum을 선언하고 불러오는 방법

- 아래와 같이 EnumDeclaration.sol 파일로 선언하고,

- import를 통해서 해당 enum 솔리디티 파일을 불러 온 후, 컨트랙트에서 선언된 Status enum 사용가능

 

3. 구조체(Structs)

 - 구조체를 사용하여 자신만의 타입을 만들 수 있음.

 - 연관된 데이터들을 그룹핑 하는 등에 사용하는 경우에 유용함.

 - 컨트랙트 밖에서 선언될 수 있고 다른 컨트랜트로 가져올(imported) 수 있음

 

- 구조체를 아래와 같이 선언 후, 3가지 형태로 데이터를 입력 가능

 

- 구조체 선언 후, 데이터 입력 함수

 

솔리디티 calldata(콜데이터), memory(메모리) 차이점 

- 위 예제에서 calldata 와 memory가 나온다.

- 잠깐 정리하면,

   Memory : 함수 호출시에만 존재하는 휘발성 데이터가 위치하는 곳

   Calldata : Call에 사용되는 Data, 함수 호출시 인자로 포함된 데이터들이 위치하는 공간.

 

( 흠..비슷한듯 뭔가 다른듯한데??)

   * Memory와 Calldata의 차이점은 Memory는 수정이 가능하지만 Calldata는 수정이 불가함.

   * Calldata는 Calldata에 포함된 데이터를 사용, memory는 calldata로부터 데이터를 가져와서 별도의 카피본을 만들어서 사용.

   * memory를 사용하면 calldata에 비해서 가스비가 더 발생함

 - 사용시 유의점,

  읽기와 수정이 필요하지만 블록체인 상태 업데이트는 필요없는 경우 (블록체인에 기록하지 않음) memory를 사용

  함수 파라미터로 calldata 키워드를 사용하면 가스비를 아낄 수 있음.

 

 

- 구조체를 파일로 선언하고 불러오는 방법은 아래와 같다.

사용은 아래와 같이

 

소스파일 참고 : https://solidity-by-example.org/

 

블록체인 교육 문의는 아래 링크 참고 바랍니다. 

https://kimsfamily.kr/414

 

블록체인 교육 커리큘럼 및 프로필

안녕하세요 제 프로필을 간략하게 정리하였습니다. 비즈니스 문의는 dannykim@kakao.com 으로 연락주시기 바랍니다. 감사합니다. 프로필) 블록체인 강의 경력) 1. 블록체인 강의 (20년~현재) 2022년  -

kimsfamily.kr

 

반응형

댓글0