Remix_06

atesi·2022년 10월 18일
0

blockchain

목록 보기
8/12

Immutable & Constant

이번 포스트에서는 계약을 조금 더 전문적으로 만들기이다. 비용을 더 효율적으로 쓰기 위함이다.

uint256 public minimumUsd= 50 * 1e18;은 계약이 배포 되면 고정되고 변하지 않는다. constant 키워드를 통해 이 변수를 조금 더 효율적으로 만든다.

uint256 public constant MINIMUM_USD= 50 * 1e18;
키워드를 추가하면 변수는 저장공간을 차지하지 않고 읽기 쉬워진다. 규칙이 있는데 대문자와 _으로 작성한다.

address public immutable i_owner;
상태변수는 immutable로 표시할수 있는데 읽기 전용이 되지만 constructor에서 할당할 수 있다. i_로 시작해야한다.

Custom Errors

0.8.4버전 이상부터 사용가능하다. 계약외부에 error를 정의해준다.

//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
import "./PriceConverter.sol";

error NotOwner();

contract FundMe{
 ...
...
modifier onlyOwner{
// require(msg.sender == i_owner, "You are not the owner!");
if(msg.sender != i_owner){ revert NotOwner(); }
_;
}

receive & fallback

공식문서

계약에 fund함수를 이용하지 않고 돈을 보낸다면 누가 얼마나 보냈는지 추적할 수 없다.

FallbackExample.sol을 만들어준다.

receive() external payable{
    result= 1;
}

receive 함수는 이더를 받을 때 디폴트 함수로 실행된다.

컴파일후 배포하게 되면 아래쪽에
입력필드가 있는 CALLDATATransact버튼이 있는 Low level interactions을 볼 수 있다. value에 금액을 넣고 트랜잭션을 누르면 result값이 0에서 1로 바뀐다.

CALLDATA을 공백으로 나두지 않으면 어떻게 될까?
데이터를 보냈을때 Receive를 이용하지 않아 알아서 함수를 찾아 준다. 0x00과 일치하지 않아 fallback함수를 찾는다. 아직 정의 해주지 않아서 오류를 반환.

fallback() external payable{
result= 2;
}

이제 오류 대신 성공적으로 전달된다.
유효한 함수 없이 계약이 호출됐지만 solidity에서 이것을 알아차리고 fallback함수를 실행시키고 결과를 반환한다.

...
modifier onlyOwner{
// require(msg.sender == i_owner, "You are not the owner!");
if(msg.sender != i_owner){ revert NotOwner(); }
_;
}

fallback() external payable {
    fund();
}

receive() external payable {
    fund();
}

fallback()receive()를 계약에 추가한다.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import "./PriceConverter.sol";

error NotOwner();

contract FundMe{
    using PriceConverter for uint256;

    uint256 public constant MINIMUM_USD = 50 * 1e18;
    address[] public funders;
    mapping(address => uint256) public addressToAmountFunded;

    address public immutable i_owner;

    constructor(){
        i_owner = msg.sender;
    }

    function fund() public payable{
        require(msg.value.getConversionRate() >= MINIMUM_USD, "Didn't send enough!"); // 1e18 == 1 * 10 ** 18
        funders.push(msg.sender);
        addressToAmountFunded[msg.sender] = msg.value;
    }   

    function withdraw() public onlyOwner {

        for(uint256 funderIndex = 0; funderIndex < funders.length; funderIndex++){
            address funder = funders[funderIndex];
            addressToAmountFunded[funder] = 0;
        }

        funders = new address[](0);
        (bool callSuccess,)= payable(msg.sender).call{value: address(this).balance}("");
        require(callSuccess, "Call failed");
    }

    modifier onlyOwner {
        // require(msg.sender == i_owner, "Sender is not owner!");
        if(msg.sender != i_owner) { revert NotOwner();}
        _;
    }

    receive() external payable{
        fund();
    }

    fallback() external payable{
        fund();
    }
}

여기까지 기초적인 solidity문법을 이용해 FundMe 스마트 컨트렉트를 만들어 보았습니다.




이 시리즈는 freeCodeCamp.org의 강의를 들으면서 공부한 내용을 정리하기 위해 작성했습니다.

profile
Action!

0개의 댓글