[TIL]23.05.15 solidity(예외처리, constructor, modifier)

dalCoding·2023년 5월 15일
0

solidity에서 예외처리하기: require, assert, revert

require

:조건이 충족되지 않으면 예외를 발생하고 함수 실행을 중단, 예외 메시지를 함께 출력가능

function require(uint _n) public pure returns(uint){
	require(_n < 10, "error");
  	return _n;
}

assert

:조건이 충족되지 않으면 예외를 발생하고 함수 실행을 중단한다. 예외 메시지 출력 가능. 가스를 소모하지 않고 일반적으로 불변식을 검증하는데 사용된다.

function transfer(address _to, uint256 _value) public {
    require(_value <= balances[msg.sender], "insufficient balance");
    require(_to != address(0), "invalid address.");
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    assert(balances[msg.sender] + balances[_to] == previousBalances); // 불변식 검증
    emit Transfer(msg.sender, _to, _value);
}
//emit:solidity에서 event를 발생 시키는 키워드ㅡ

revert

:예외를 발생시키고, 상태를 롤백한다. 예외 메세지 출력가능

function transfer(address _to, uint256 _value) public {
    require(_value <= balances[msg.sender], "Insufficient balance.");
    require(_to != address(0), "Invalid address.");
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    emit Transfer(msg.sender, _to, _value);
    if (balances[msg.sender] == 0) {
        revert("Balance cannot be zero.");
    }
}
  • balances[msg.sender]가 0이 되는 경우 예외를 발생, 상태를 롤백한다. -> 이전 상태로 돌아감

Constructor

  • smartContract를 배포 할 때 실행, 스마트 컨트랙트의 초기화를 담당하며, 컨트랙트가 생성 될 때 한 번만 실행된다.
  • constructor 함수를 사용하여 컨트랙트의 소유자를 설정하거나, 컨트랙트에 초기 자금을 지급할 수 있다.
  • 다른 스마트 컨트랙트와의 상호 작용을 위한 인터페이스를 설정하는 등의 작업을 수행 할 수 있다.
constructor함수는 solidity 0.5.0 버전부터 도입된 기능으로, 이전 버전에서는 컨트랙트 생성자를 정의하기 위해 function 키워드를 사용해야 했다. constructor 함수를 사용하면 코드의 가독성을 높일 수 있다.
contract CONSTRUCTOR{
    address payable owner;
  
    constructor () payable{

 //생성자 함수가 호출 될 때, msg.value로 전송된 이더리움을 컨트랙트 계정으로 전송
      payable(this).transfer(msg.value);
        owner = payable(msg.sender);
    }

  //owner 변수의 값을 반환하는 함수
    function getOwner() public view returns(address){
        return owner;
    }

  //owner만 호출 가능한 함수, _to 주소로 _amount만큼의 이더리움을 전송
    function transferTo(address payable _to, uint _amount) public {
        require(msg.sender == owner, "only owner can transfer asset");
        _to.transfer(_amount);
    }

  //fallback함수로, 이더리움을 컨트택트 계정으로 전송 할 때 호출된다.
//receive()가 호출되는 경우 - 컨트랙트 주소로 이더리움을 전송 or selfdestruct() 함수를 호출하여 컨트랙트를 파괴하는 경우 or 잘못된 함수 이름을 호출하는 경우
    receive() external payable{}

  //이더리움을 컨트랙트로 전송하는 함수, 함수가 호출 될 때 msg.value로 전송된 이더리움을 컨트랙트 계정으로 전송하고 전송된 이더리움의 양을 반환한다.
    function deposit() public payable returns(uint){
        return msg.value;
    }

  //owner만 호출 할 수 있는 함수, 컨트랙트 계정에 있는 모든 이더리움을 owner 주소로 전송한다.
    function withdraw() public {
        require(msg.sender == owner, "only owner can withdraw asset");
        owner.transfer(address(this).balance);
    }

  //_amount만큼의 이더리움을 owner주소로 전송, owner만 호출 가능한 함수
    function withdraw(uint _amount) public{
       require(msg.sender == owner, "only owner can withdraw asset");
       owner.transfer(_amount);
    }

  //owner만 호출 가능한 함수로 1이더리움을 owner 주소로 전송
    function withdraw3() public{
       require(msg.sender == owner, "only owner can withdraw asset");
       owner.transfer(1 ether);
    }
}

modifier

  • 함수의 실행 전후에 실행되는 코드 블록
  • modifier는 함수의 코드를 수정하지 않고도 함수의 동작을 변경 할 수 있다.
  • modifier는 함수의 실행 전후에 실행되며, 함수의 실행 전에 modifier의 코드가 실행되고, modifier의 코드가 실행된 후에 함수의 코드가 실행된다.(함수의 코드를 변경하지 않고도 함수의 동작을 변경할 수 있으므로, 코드의 재사용성을 높이고 코드의 중복을 줄일 수 있다.)
  • 함수 실행 전에 사용자의 권한을 확인하거나, 함수 실행 후에 로그를 기록하는 등의 작업을 수행 할 수 있다.
contract MODIFIER {
    struct Person {
        uint age;
        string name;
    }

    Person P;

    modifier overTwenty(uint _age, string memory _criminal) {
 //_age가 20 보다 큰지 확인, 만약 20 보다 작다면 예외 발생
        require(_age >20, "Too young");
  
 //_criminal이 "Bob"이라는 문자열과 같은지 확인, 같다면 예외 발생
      require(keccak256(abi.encodePacked(_criminal)) != keccak256(abi.encodePacked("Bob")), "Bob is criminal. She can't buy it");
 //require 두 조건을 모두 통과화면 _; 함수 실행
        _;
    }

    function buyCigar(uint _a, string memory _name) public pure overTwenty(_a, _name) returns(string memory) {
        return "Passed";
    }

    function buyAlcho(uint _a, string memory _name) public pure overTwenty(_a, _name) returns(string memory) {
        return "Passed";
    }

    function buyGun(uint _a, string memory _name) public pure overTwenty(_a, _name) returns(string memory) {
        return "Passed";
    }

0개의 댓글