[TIL] Part2 - DAY43 Solidity - TEST4 리뷰, TEST5 리뷰, TEST6

박동우·2023년 5월 18일

블록체인 스쿨 3기

목록 보기
41/72

[TIL] 2023-05-18 DAY43


Solidity

GIT 주소 : https://github.com/dowoo303/SOLIDITY


오늘 배운것들

  1. TEST4 리뷰
    1) 문제 리뷰
    2) FixedDynamic 정적 동적 비교
    3) Pop과 Delete 가스비 비교
  2. TEST5 리뷰
    1) 문제 리뷰
    2) While
    3) 배열뒤집기(ReversArray)
    4) Bytes 길이측정 및 string으로 변환법
  3. TEST6

각종 팁

  1. receive() external payable{} 는 스마트 컨트랙트가 To일 경우에만 사용한다.
  2. new: 동적변수지만 일단은 길이를 정해놓은 정적으로 변화시킴
  3. mapping: 머클 패트리시아 트리 형태
  4. calldata: 진짜 memory: 카피해서 사용
  5. 동시스왑: (a[0], a[3]) = (a[3], a[0])
  6. bytes는 특별한 배열이다. bytes일때는 동적이지만 bytes[n]이라고 하면 정적으로 변한다.

회고

  1. 예상문제: 6진수로 표현해보기
  2. abi.encodePacked(a)를 이용하면 문자열 떼어내기 뿐만 아니라, 1bytes들을 입력받아서 하나의 문자열로 내보내기도 가능하다.



💻 Solidity 코딩

✅ TEST4 리뷰

초기 설정에 신경을 써야한다.
mapping(address => User) userList; 구조체를 값으로 하는 매핑을 안했지 ..?
-> 초기설정을 한 다음에 계속 그 처음의 초기설정으로 끼워맞추려는 경향이 있는데 초기설정도 바꾸는 유연함을 기르자.

🟥 코드

contract Answer1 {
    struct User {
        uint number;
        string name;
        address account;
        uint balance;
        uint score;
    }

    mapping(address => User) userList;
    uint count;
    User[] public top4;     // 일단 Dynamic(동적) 배열로 선언
    User[4] public top4_2;


    address payable owner;

    constructor() payable  {
        // 0번 지갑 주소 : 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
        owner = payable(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);
    }

    // * 유저 등록 기능 - 유저는 이름만 등록, 번호는 자동적으로 순차 증가, 주소도 자동으로 설정, 점수도 0으로 시작
    function register(string memory _name) public {
        userList[msg.sender] = User(count++, _name, msg.sender, msg.sender.balance, 0);
    }

    // * 유저 조회 기능 - 유저의 전체정보 번호, 이름, 주소, 점수를 반환. 
    function search(address _a) public view returns(User memory) {
        return userList[_a];
    }

    // * 게임 참가시 참가비 제출 기능 - 참가시 0.01eth 지불 (돈은 smart contract가 보관)
    // 동적배열
    function gameIn() public payable {
        require((userList[msg.sender].balance >= 10**16 && msg.value==0) || msg.value == 0.01 ether);

        if(msg.value==0) {
            userList[msg.sender].balance -= 10**16;
        }

        if(top4.length ==4) {
            for(uint i=4;i>0;i--) {
                userList[top4[i-1].account].score += 5-i;
            }
            delete top4;
        }
        
        top4.push(userList[msg.sender]);
    }


    // 고정(fixed)배열
    function gameIn2() public payable {
        require((userList[msg.sender].balance >= 10**16 && msg.value==0) || msg.value == 0.01 ether);

        if(msg.value==0) {
            userList[msg.sender].balance -= 10**16;
        }

        if(getLengthOfTop4()==4) {
            for(uint i=4;i>0;i--) {
                userList[top4[i-1].account].score += 5-i;
            }
            delete top4_2;
        }
        top4_2[getLengthOfTop4()] = userList[msg.sender];
        
    }

    /*
		위의 gameIn2()를 modifier를 사용해본 버전
		modifier isitFour {
        if(getLengthOfTop4()==4) {
            delete top4_2;
            _;
        }
        _;
    }

    function gameIn2_2() public payable isitFour {
        require((userList[msg.sender].balance >= 10**16 && msg.value==0) || msg.value == 0.01 ether);

        if(msg.value==0) {
            userList[msg.sender].balance -= 10**16;
        }

        top4_2[getLengthOfTop4()] = userList[msg.sender];
        
    }*/

    function getLengthOfTop4() public view returns(uint) {
        // 고정배열의 초기값이 0인 것을 이용한다
        for(uint i=0; i<4; i++) {
            if(top4_2[i].account == address(0)) {
                return i;
            }
        }
        return 4;
    }

    // * 점수를 돈으로 바꾸는 기능 - 10점마다 0.1eth로 환전
    function withdraw(uint _n) public {
        // 10점 단위로 넣는다고 가정
        require(_n%10==0 && userList[msg.sender].score >= _n);
        userList[msg.sender].score -= _n;
        payable(msg.sender).transfer(_n%10*0.1 ether);
    }

    // * 점수를 돈으로 바꾸는 기능 - 10점마다 0.1eth로 환전 (최대 금액 자동 환전)
    function withdraw_All() public {
        require(userList[msg.sender].score >= 10);
        uint a = userList[msg.sender].score /10;
        userList[msg.sender].score = userList[msg.sender].score%10;
        payable(msg.sender).transfer(a*0.1 ether);
    }

    // * 관리자 인출 기능 - 관리자는 0번지갑으로 배포와 동시에 설정해주세요, 관리자는 원할 때 전액 혹은 일부 금액을 인출할 수 있음 (따로 구현)
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    function ownerWithdraw(uint _n) public onlyOwner {
        owner.transfer(_n*1 ether);
    }

    function ownerWithdrawAll() public onlyOwner {
        owner.transfer(address(this).balance);
    }

    // * 예치 기능 - 게임할 때마다 참가비를 내지 말고 유저가 일정금액을 미리 예치하고 게임할 때마다 자동으로 차감시키는 기능.
    function deposit() public payable {
        userList[msg.sender].balance += msg.value;
    }
}

✅ While

for에서 조건문을 설정하기 애매할때 사용한다. 즉, 특정조건을 만족할 때까지 반복해야할 경우 사용한다.
while은 조건 1개만 설정해주면 된다. -> 그러므로 무한반복이 되지 않도록 주의해야한다.

형태: while(조건) -> 조건이 거짓이면 루프종료(처음부터 거짓이면 실행안함!)

🟥 코드

contract While {
    function while1(uint _n) public pure {
        uint ab;
        while(_n < ab) {
            ab++;
        }
    }

    uint[] public a;
    function while_2(uint _n) public returns(uint[] memory) {
        while(a.length <_n) {
            a.push(a.length+1);
        }
        return a;
    }

    function while_3(uint _n) public pure returns(uint) {
        uint _a;
        while(_n > 10**_a) {
            _a++;
        }
        return _a;
    }
}

✅ TEST6

paper.status = paperStatus.voting; 이거 왜 오류냐냐
paperList[_title].status = paperStatus.voting; 이건 왜 되냐
=> paper.status는 그냥 구조체 가르키는 거고 paperList[_title].status는 key값을 통해 어떤 특정한 구조체를 가르키니까 당연하지.. mapping 다시 공부하자 ..

profile
HELLO!

0개의 댓글