Solidity receive, array vs map and array

유지민·2022년 12월 8일
0

solidity

목록 보기
3/4

receive()

해당 컨트랙트를 payable하게 바꿔주는 코드

contract A {
    function getMoney() public payable {}
    function transferTo(address _a) payable public {
        payable(b).transfer(100);
    }
}

contract B {
    function getBalance() public view returns(uint) {
        return address(this).balance;
    }
    receive() external payable {} // B를 patyable하게 바꾸어주는 코드
}

컨트랙트 A의 transferTo로 돈을 보내면 받는 기능을하는 함수라고 생각하면 될듯

Array 오류

contract array_memory {
    function pushNumber() public pure returns(uint[] memory){
        /*
        uint[] memory a; -> 길이가 설정이 안되어 
        */
        /*
        uint[] memory a = new uint[](1);
        a[1]=1; -> 설정된 길이는 1 요구된 길이는 2
        return a;
        */
        uint[] memory a = new uint[](0);
        a[0]=1;
        return a;
    }
}

함수 내부에 uint[] memory a; 로 선언후 push하면 메모리에서는 푸쉬를 못하기 때문에
push말고 a[i] = n; 식으로 위치에 값을 넣어주는 방식으로 함.
처음 배열 선언시 길이를 안정해주고 하면 당연히 오류.

array vs map and array

코드를 짜다가 어떤 struct구조를 관리해야할 일이 생겼는데 Array로 관리할지 Map으로 관리할지 고민이 생겼다. Array로 관리시 전체를 관리할수있다는 장점이 있지만 특정 하나를 조회시 전체적인 for문을 돌려봐야하고 Map시 조회는 편하지만 전체 관리가 힘들다.
map을 쓰려면 전체적으로 관리도 해야하는 상황이면 map, array를 둘다 써야하는데 어떤 방식이 가스비가 더 나올까 하는 실험을 했다.

contract A {
   struct AAA {
       uint a;
       string name;
       address b;
   }

   AAA[] AAAs;
   uint index;

   function setAAA(string memory _name) public {
       AAAs.push(AAA(index++, _name, msg.sender));
   }

   function getAAA() public view returns(AAA memory) {
       for(uint i=0; i<AAAs.length; i++) {
           if(AAAs[i].b == msg.sender) {
               return AAAs[i];
           }
       }
   }
}

contract B {
   struct AAA {
       uint a;
       string name;
       address b;
   }

   AAA[] AAAs;
   mapping(address => AAA) AAAwithMap;
   uint index;

   function setAAA(string memory _name) public {
       AAAs.push(AAA(index++, _name, msg.sender));
       AAAwithMap[msg.sender] = AAA(index, _name, msg.sender);
   }

   function getAAA() public view returns(AAA memory) {
       return AAAwithMap[msg.sender];
   }
}

A는 array로 관리, B는 map, array를 써 관리
각각 지갑 10개로 set으로 등록, get으로 홀수만 조회해보니

contract A {
   struct AAA {
       uint a;
       string name;
       address b;
   }

   AAA[] AAAs;
   uint index;

   function setAAA(string memory _name) public {
       AAAs.push(AAA(index++, _name, msg.sender));
   }

   function getAAA() public view returns(AAA memory) {
       for(uint i=0; i<AAAs.length; i++) {
           if(AAAs[i].b == msg.sender) {
               return AAAs[i];
           }
       }
   }
}

contract B {
   struct AAA {
       uint a;
       string name;
       address b;
   }

   AAA[] AAAs;
   mapping(address => AAA) AAAwithMap;
   uint index;

   function setAAA(string memory _name) public {
       AAAs.push(AAA(index++, _name, msg.sender));
       AAAwithMap[msg.sender] = AAA(index, _name, msg.sender);
   }

   function getAAA() public view returns(AAA memory) {
       return AAAwithMap[msg.sender];
   }
}
A                           B
496125                      500325
--------                    --------
113773                      180900
99473                       166600
99473                       166600
99473                       166600
99473                       166600
99473                       166600
99473                       166600
99473                       166600
99473                       166600
99473                       166600
--------                    --------
32037(1)                    29415(1)
37351(3)                    29415(3)
42665(5)                    29415(5)
47979(7)                    29415(7)
53293(9)                    29415(9)
1,718,480                   2,327,700

라는 결과가 나왔다.
B는 등록시 array, map 둘다 저장해줘야해 등록시 가스비가 배는 들지만 조회시는 좀 더 저렴하다.
그치만 엄청나게 많은 데이터를 저장해 조회로 뽕을 뽑을 생각이 아니면 왠만하면 array, map중 하나만 선택해서 쓰자.

profile
개발 취준생

0개의 댓글