fullstack

[Solidity] 함수제어자 modifier

Web3/Solidity

contract의 소유자만 호출할 수 있는 함수를 만들고 싶다고 가정해봅시다

함수의 첫 줄에 require문을 넣어 처리할 수도 있지만 더욱 좋은 방법은 함수제어자를 사용하는 것 입니다

 

함수제어자는 다음과 같이 만들 수 있습니다

modifier onlyOwner() {
  require(msg.sender == owner);
  _;
}

함수제어자는 위와같이 function 키워드 대신 modifier 키워드를 사용합니다

그리고 require 등으로 실행조건을 체크하고, 마지막에는 _; 으로 끝나야 합니다

 

그럼 함수에서 함수제어자를 사용해 보겠습니다

function withdraw() external onlyOwner {
  owner.transfer(this.balance);
}

위에서 만든 함수제어자 onlyOwner를 함수에 붙여주었습니다

그럼 이제 withdraw 함수가 호출되면 함수제어자 onlyOwner가 실행되고,

함수제어자 내부의 _; 부분에서 함수로 되돌아와 함수가 실행되게 됩니다

이제 이 함수는 contract의 소유자만이 호출할 수 있는 함수가 되었습니다

 

함수제어자를 이용하면 이처럼 특정조건에 부합할때만 함수가 실행되도록 간편하게 설정할 수 있습니다

[Solidity] 상속, 다중상속, 함수 오버라이드(override)

Web3/Solidity

Solidity의 contract는 객체지향언어에서의 class와 닮은 점이 많습니다

그 중 상속에 대해서도 매우 유사한 형태를 보입니다

 

상속

상속은 다음과 같이 사용하면 됩니다

contract Doge {
  function catchphrase() public returns (string) {
    return "So Wow CryptoDoge";
  }
}

contract BabyDoge is Doge {
  function anotherCatchphrase() public returns (string) {
    return "Such Moon BabyDoge";
  }
}

contract 이름 뒤에 is 키워드를 이용하여 뒤에 상속받을 부모 contract의 이름을 써주면 됩니다

그럼 자식 contract는 상속받은 부모 contract의 모든 public 변수와 함수에 접근이 가능합니다

 

다중 상속

다중상속은 다음과 같이 사용하면 됩니다

contract MomDoge {
  function catchphrase() public returns (string) {
    return "So Wow CryptoDoge";
  }
}

contract DadDoge {
  function catchphrase() public returns (string) {
    return "So Wow CryptoDoge";
  }
}

contract BabyDoge is MomDoge, DadDoge {
  function anotherCatchphrase() public returns (string) {
    return "Such Moon BabyDoge";
  }
}

이미 상속받은 부모 contract가 있다면 뒤에 ','를 붙여 구분하여 다중상속을 할 수 있습니다

 

함수 오버라이드

상속을 받으면 부모의 public함수에 접근이 가능합니다

이때 부모의 함수의 이름과 같은 이름과 매개변수를 사용하여 함수를 재정의 하고 싶을 때가 있습니다

이를 함수 오버라이드(Override)라고 합니다

 

기본적인 단일상속에서는 다음과 같이 사용하면 됩니다

contract MomDoge {
  function catchphrase() public virtual returns (string) {
    return "So Wow CryptoDoge";
  }
}

contract BabyDoge is MomDoge {
  function catchphrase() public override returns (string) {
    return "Such Moon BabyDoge";
  }
}

부모 contract의 함수에서는 virtual을 자식 contract의 함수에서는 override를 명시해 주면 됩니다

 

만약 다중상속이고 오버라이드 하려는 함수가 여러 부모가 가지고 있는 함수라면

다음과 같이 괄호를 사용하여 해당 함수를 가진 contract들을 명시해 주어야 합니다

 

contract MomDoge {
  function catchphrase() public virtual returns (string) {
    return "So Wow CryptoDoge";
  }
}

contract DadDoge {
  function catchphrase() public virtual returns (string) {
    return "So Wow CryptoDoge";
  }
}

contract BabyDoge is MomDoge, DadDoge {
  function catchphrase() public override(MomDoge, DadDoge) returns (string) {
    return "Such Moon BabyDoge";
  }
}

[Solidity] error handler (require, assert, revert)

Web3/Solidity

Solidity의 에러 핸들러에는 require, assert, revert 세가지가 있습니다

각각 어떤 경우에 사용하는지, 어떻게 사용하는지 알아보겠습니다

 

require

require는 특정 조건이 참이 아니라면 에러 메시지를 발생하고 실행을 멈춥니다

require로 에러를 발생시키면 사용하려던 gas를 환불 시켜 줍니다

주로 사용자 사용자의 입력을 확인하는데 사용합니다

 

사용방법은 다음과 같습니다

require(msg.value % 2 == 0, "Even value required.");

 

assert

assert는 특정 조건이 참이 아니라면 에러를 발생시켜 실행을 멈춥니다

assert는 gas를 환불 시켜 주지 않습니다

주로 내부적 코드결함이 있는지 확인하는데 사용합니다

(오버플로우나 언더플로우 등 치명적인 문제를 찾을 때 사용)

 

사용방법은 다음과 같습니다

 assert(address(this).balance == balanceBeforeTransfer - msg.value / 2);

 

revert

revert는 조건없이 에러를 발생시킬 때 사용합니다

require와 마찬가지로 에러를 발생시키면 사용하려던 gas를 환불 시켜 줍니다

 

사용방법은 다음과 같습니다

revert("Not enough Ether provided.");

revert를 사용하려면 어쨋든 특정 조건문 안에 넣어야 하는데, 이는 require로 대체가 되기 때문에 

주로 require가 사용되고 revert는 잘 사용되지 않습니다

[Solidity] view, pure 함수

Web3/Solidity

contract를 만들때 중요하게 생각해야 하는 것 중 하나가 가스비용 최적화입니다

블록체인에 데이터를 쓸 때 마다 가스비용이 들기 때문에 이를 최소화 하는게 중요합니다

 

이 때 필요한 것이 view 함수입니다

view 함수는 function 밖의 변수를 읽기만 할 뿐, 변경할 수 없습니다

따라서 view 함수를 쓰는 것은 블록체인에 어떤 트랜젝션도 만들지 않는다는 것을 의미 합니다

 

view 함수는 사용자에 의해 외부에서 호출되었을 경우 가스를 전혀 소모하지 않습니다

(내부에서 다른 함수에 의해 호출되었을 경우 가스를 소모할 수 있음)

그래서 여기에 접근제어자 중 외부에서만 호출할 수 있게하는 exturnal을 같이 사용한다면

이 함수는 가스비용을 절대 소모하지 않는 함수가 됩니다

 

사용방법은 다음 예시와 같습니다

 

function func() exturnal view {
	...
}

 

pure 함수는 view 함수보다 조금 더 빡센(?) 함수입니다

view 함수가 읽기만 가능하다면, pure 함수는 읽기 조차도 불가능 합니다

 

[Solidity] 접근 제어자 (public, private, internal, external)

Web3/Solidity

접근 제어자는 함수가 언제, 어디서 호출될 수 있는지 제어합니다

Solidity에서 접근 제어자의 종류는 다음과 같습니다

 

public

이 함수는 contract의 내외부 모두에서, 어디서든지 호출될 수 있습니다

 

private

이 함수는 contract의 내부의 다른 함수들에 의해서만 호출될 수 있습니다

 

internal

이 함수는 contract의 내부 혹은, 해당 contract를 상속하는 다른 contract에서도 호출될 수 있습니다

 

external

이 함수는 오직 contract 외부에서만 호출될 수 있습니다