솔리디티 문법 2
솔리디티
함수
// 값 반환 없는 경우
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 {
}
라이브러리
- 컨트랙트 간에 코드를 공유하거나 공통적인 기능을 재사용하고자 할 때 라이브러리 활용
- Ex. OpenZepplin
- 기존 컨트랙트 호출과는 다른 방식으로 진행
- 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 과정을 수강하며 작성한 글입니다.