Rules of memory VS storage in Solidity

Rules of memory VS storage in Solidity

memory vs storage

컨트렉트 내 사용되는 각각의 변수가 EVM 내에서 저장되는 위치는 다음과 같음.
  • 1 storage: 컨트렉트 내 모든 함수가 사용할 수 있는 전역 메모리 영역, 네트워크 내 모든 노드에 영구적으로 저장된다.
  • 2 memory: 컨트렉트 내 모든 함수가 사용가능한 로컬 메모리, function 이 끝나면 사라짐, 휘발성
variable의 저장 위치를 정하는 규칙
  • 1 state variable(global variable)로 선언되는 변수들은 항상 스토리지에 저장
  • 2 함수 파라미터로 선언되는 변수들은 항상 메모리에 저장
  • 3 함수 내에서 선언되는 변수들은 기본적으로 메모리에 저장,
    • 3.1 reference 타입(array, struct, string, mapping)의 변수는 기본적으로 스토리지, value 타입(int등 그 외)은 기본이 메모리
    • 3.2 reference 타입 변수의 기본 위치를 무시하고 메모리에 저장할 수 있다.
    • 3.3 함수 내에서 선언된 reference 타입 & 스토리지 변수는 state variable을 가르켜야 한다.
    • 3.4 함수 내에서 선언된 value타입 변수는 스토리지 위치에 저장할 수 없다.
...

function test() return (uint) {
    int storage myInt; // error
}
    • 3.5 매핑은 항상 스토리지 위치에 선언된다. 즉, 함수 내에서 메모리로 선언될 수 없음(컴파일 안된다. 스토리지 변수로 만들고, 글로벌 변수를 참조시켜주면 가능.
...

mapping(int => int) public intMapp;

function test() public returns (int) {
    mapping(int => int) memory map = intMapp; // error
  map[0] = 11;
  return map[0];
}

function test() public returns (int) {
  mapping(int => int) storage map = intMapp; // OK
  map[0] = 11;
  return map[0];
}
  • 4 function 내에서 한 글로벌 변수에 다른 글로벌 변수를 할당하면, 레퍼런스 카피가 아니라 벨류 카피
...

uint stateVal1 = 10;
uint stateVal2 = 20;

function test() return (uint) {
    stateVal1 = stateVal2; // now both are 20.
    stateVal2 = 30; // stateVal1 is still 20, only stateVal2 is 30
    return stateVal1; // return 20
}
  • 5 메모리 변수를 스토리지 변수에 할당할 때 에는 레퍼런스 카피가 아니라 벨류 카피
...

uint[2] stateArr;

function test() return (uint) {
    uint[2] memory localArr = [uint(1), 2];
    stateArr = localArr; // now, both are [1, 2], [1, 2]

    localArr[1] = 10;
    return stateArr[1]; // return 2, not 10
}
  • 6 함수 내 메모리 변수에 global 변수를 할당하면 벨류 카피
  • 7 함수 내 메모리 변수에 다른 메모리 변수 할당하면 벨류 카피