3 분 소요

솔리디티


함수

// 값 반환 없는 경우
function 함수이름(파리미터 형식 파라미터, ...) {
	...
}

// 값 반환 있는 경우
function 함수이름(파라미터, ...) returns (반환 형식) {
	...
}

함수 접근 수준


  • public(default)
    • 외부에서도 접근 가능
    • 컨트랙트 내부, 외부, 클라이언트 코드에서 모두 호출 가능
  • external
    • public과 비슷함
    • 외부 컨트랙트나 클라이언트 코드에서 호출 가능
    • 내부에서는 호출 불가능
    • 내부로부터 불릴 경우, this.f()와 같이 this를 활용한 호출 가능
  • internal
    • 컨트랙트 멤버와 상속된 컨트랙트에서 호출 가능
  • private
    • 컨트랙트 멤버만 호출 가능

-> internal or private은 다른 계약이 정보를 읽거나 수정하는 것을 방지

-> 퍼블릭 블록체인 특성상 데이터는 공개

contract exampleC {
	function changeName(address account, string newName) internal {...}
	function checkGas(uint256 amount) private returns (bool) {...}
}

Qualifier(view, pure, payable)


함수가 컨트랙트의 내부 상태를 변경할 수 있는 능력을 선언한다.

view, pure

  • view : 상태를 변경하지 않는 읽기 전용 함수
  • pure : 스토리지에서 변수를 읽거나 쓰지 않는 함수
pragma solidity ^0.8.14;
contract exampleC {
	uint256 public constant maxLimit = 1000;
	mapping(address => bool) public frozenAccount;
	
	function checkGas(uint256 amount) private pure returns (bool) {
		if(amount < maxLimit) return true;
		return false;
	}
	
	function validateAccount(address account) internal view returns (bool) {
		if(frozenAccount[account]) return true;
		return false;
	}
}

Payable

  • 함수에서 이더를 받을 수 있는 함수
pragma solidity ^0.8.14;
contract exampleC {
	function getEther() payable returns (bool) {
		if(msg.value === quoteFee) {
			// ...
		}
	}
}

생성자 함수(constructor)


컨트랙트가 생성될 때 생성자 함수가 실행되며 컨트랙트의 상태를 초기화할 수 있다.

pragma solidity ^0.8.14;
contract exampleC {
	address public account;
	
	constructor(address _account) {
		account = _account;
	}
}

selfdestruct


컨트랙트 소멸 함수

selfdesturct(컨트랙트 생성자의 주소);

함수 제어자(modifier)

  • 함수 선언에 modifier를 추가하여 함수에 변경자를 적용할 수 있다.
    • 변경자 : 함수를 실행하기 전, 요구 조건을 만족하는지 확인하는 작업
  • 변경자를 작성할 때는 _; 사용
    • _; 는 함수를 실행하는 시점을 나타내며, 변경자 코드는 _; 코드를 기준으로 실행 시점이 달라진다.
      • _; 이전의 코드는 함수가 실행되기 전에 실행
      • _; 이후의 코드는 함수 실행이 종료되고 실행
int public num = 0;
modifier changeNum {
	num++; // 함수 실행 전 실행됨
	_;	// 함수 실행
	num--;	// 함수 실행 후 실행됨
}

function func() public changeNum {
	if(num == 1) {
		//...
	}
}

// Logic
/*
	1. chageNum => num++;
	2. changeNum => 실행 if문
	3. changeNum 종료 => num--;
*/
  • 함수를 선언적으로 사용할 수 있다.

이벤트 및 에러 핸들링

이벤트


  • 어떤 결과가 발생했을 때 해당 컨트랙트에서 dApp 클라이언트, 또는 다른 컨트랙트에게 전달
  • event 키워드를 사용해 이벤트를 설정하고, 때에 따라 emit 키워드를 사용해 이벤트를 실행
    • 이벤트가 실행된 경우, 트랜잭션에 기록
contract coinTransfer {
	//event 이벤트명(파리미터형식 파라미터, ...)
	event Transfer(address from, address to, uint256 value);
	
	function transfer(address to, uint256 amount) {
		// ...
		
		//emit 이벤트명(인자1, 인자2, ...)
		emit Transfer(msg.sender, to, amount);
	}
}

에러 핸들링


  • revert : 해당 함수를 종료하고 에러를 반환
pragma solidity ^0.8.14;

contract VendingMachine {
	address owner;
	
	function buy(uint amount) public payable {
		if(amount > msg.value / 2 ether)
			revert("Not enough Ether provided"); // 에러 반환
	}
}
  • require, assert : 설정한 조건이 참인지 확인하고, 조건이 거짓이면 에러를 반환
    • assert의 경우, require과 사용법은 같으나, 사용하지 않은 가스를 호출자에게 반환하지 않고, 공급된 가스를 모두 소모하며 원래대로 되돌린다.
pragma solidity ^0.8.14;

contract VendingMachine {
	address owner;
	
	function buy(uint amount) public payable {
		require(
			amount <= msg.value / 2 ether, // 조건
      "Not enough Ether provided" // 거짓일 경우 에러 메시지
		)
	}
}

상속 및 라이브러리

상속


  • 상속을 사용하려면 부모 컨트랙트에 is 키워드를 지정한다.
contract ChildContract is ParentContract {
	//...
}
  • 다중 상속
contract ChildContract is ParentContract1, ParentContract2 {

}

라이브러리


  • 컨트랙트 간에 코드를 공유하거나 공통적인 기능을 재사용하고자 할 때 라이브러리 활용
  • 기존 컨트랙트 호출과는 다른 방식으로 진행
    • contract 키워드 대신 library 키워드 사용
    • 상태 변수, 상속 관계, fallback 함수, payable 함수 지원 안 됨
    • 파라미터 받는 것 가능
    • 호출 방법
      • 라이브러리 이름.메소드 이름()
      • using 라이브러리 이름 for 데이터타입
import "./UIntFunctions.sol";
contract Example {
	function isEven(uint x) public pure returns(bool) {
		return UIntFunctions.isEven(x);
	}
}
import "./UIntFunctions.sol";
contract Example {
	using UIntFunctions for uint;
	function isEven(uint x) public pure returns(bool) {
		return x.isEven(x);
	}
}

간단한 가위바위보 게임

본 포스팅은 코드스테이츠 BEB 과정을 수강하며 작성한 글입니다.