본문 바로가기
Block Chain/Solidity

[Solidity] Array Memory에서 사용하는 방법 || Solidity 0.8 ||

by 개발이 체질인 나그네 2022. 12. 17.
반응형

안녕하세요. 스마트 컨트렉트 개발자 개발이 체질의 최원혁입니다.

 

Solidity는 변수를 정할 때, 데이터가 저장되는 위치를 정의해야 합니다. EVM은 상태(States) 변수와 지역(Local) 변수 두 종류로 나뉩니다. 상태(States) 변수는 EVM의 Storage에 데이터가 저장되며, 스마트컨트렉트의 Data Storage에 보존됩니다. 지역(Local) 변수는 Memory에 저장되는 데이터로 EVM의 런타임이 실행되는 동안 저장되며, 실행이 끝나면 살아지는 휘발성 데이터입니다.

 

EVM에서 함수 외부의 공간에 변수를 정의하면, 자동으로 데이터는 Storage에 저장됩니다. 하지만 함수(function) 내부에서 정의한 변수는 Memory에 저장되어, 함수가 실행되는 동안만 데이터를 보관하고, 실행이 끝나면 살아지게 됩니다.

 

이번 게시글에서는 함수 내부에서 array를 사용하는 방법에 대해 알아보겠습니다.

 

 


 

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

contract ReturnsArray {
    // 유저가 갖고 있는 잔액
    mapping(address => uint) public balance;

    // 유저들이 갖고 있는 잔액 배열로 리턴
    function getBalanceByAddressList(address[] calldata users) 
    	public returns(uint[] memory) {}

}

예시에서  function getBalanceByAddressList() 는 파라미터  address[] users의 배열에 들어 있는 사람들의 잔액을 

 uint[] result에 넣어 최종 결과로 return 하려고 합니다.

 

 

function getBalanceByAddressList(address[] calldata users) public view returns(uint[] memory) {
    uint[] memory results;
}

 

Solidity는 정적 프로그래밍 언어입니다. 때문에 배열에는 변수 생성 시, 정의한 데이터 타입만 들어갈 수 있습니다.

위 예시 처럼 uint 타입으로 구성된 Array 변수 results를 생성할 수 있습니다. 

EVM Error

 

하지만 함수 내부에서 배열 변수를 생성할 때는, 위와 같이 코드를 짜면 안 됩니다. 데이터를 저장하기 위해 push()를 하면 EVM Error가 발생하는 걸 볼 수 있습니다.

또한 uint[] 처럼 데이터 타입에 배열을 명시하여 사용하면 두 번째 사진처럼 EVM Error가 발생합니다.

 

 

위와 같은 애러가 나타나는 이유는 Memory 타입의 규칙때문입니다.

  • memory는 storage와 달리 메모리의 크기를 동적으로 사용 할 수 없습니다. 즉, 배열의 길이를 정적으로 설정해야 합니다.
  • memory 타입의 정적 배열을 생성할 때, new 연산자를 사용해야 합니다.
  • memory 타입의 정적 배열을 push() 할 수 없다.
Memory arrays with dynamic length can be created using the new operator. As opposed to storage arrays, it is not possible to resize memory arrays (e.g. the .push member functions are not available). You either have to calculate the required size in advance or create a new memory array and copy every element.

by.Solidity Docs https://docs.soliditylang.org/en/v0.8.17/types.html?highlight=memory#allocating-memory-arrays

 

 

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

contract ReturnsArray {
    mapping(address => uint) public balance;

    function getBalanceByAddressList(address[] calldata users) public view returns(uint[] memory) {
        uint _length = users.length;
        
        // uint[] memory results; // Not Good
        // uint[_length] memory results; // 정적 배열 설정 시, 변수 지정 불가능
        uint[] memory results = new uint[](_length);
        
        for(uint i = 0; i < _length; i++) {
            //   results.push(balance[users[i]]); // 사용불가
             results[i] = balance[users[i]];
         }

        return results;
    }
}

 

Memory의 특성을 고려하여 Array를 정적 배열로 만들면, 위와 같은 코드가 됩니다. 

 

 

 

지금까지 EVM의 memory에서 Array를 사용하는 규칙과 방법에 대해 알아봤습니다.

감사합니다.

 

 


📌 Reference :

- https://ethereum.stackexchange.com/questions/141345/return-a-mapping-in-solidity/141353#141353

- https://ethereum.stackexchange.com/questions/12433/invalid-array-length-expected-integer-literal

https://docs.soliditylang.org/en/latest/types.html#allocating-memory-arrays

- https://stackoverflow.com/questions/71360830/member-push-is-not-available-in-bool-memory-outside-of-storage

 

 

 

 

 

반응형

댓글