솔리디티에서 함수란 컨트랙트의 호출 및 실행의 단위로서 함수에서의 주요 작업은 변수에 대한 읽기, 연산, 쓰기, 조건문, 반목문 등을 실행하는 것입니다.
함수의 선언은 function이라는 키워드로 시작해야 하며, 그 다음 함수 이름, 함수 인자들의 목록, 그리고 가시성, 상태변경성 유형, 마지막으로 return 값들의 목록이 등장해야합니다.
function getName(uint index) public view returns(string memory) {
...
}
함수의 기본 구조
또한 솔리디티에서는 함수가 여러 개의 값을 리턴하는 것도 가능합니다.
function returnMany(uint index) public pure returns(uint, bool, uint) {
return (1,true,2);
}
복수의 반환 값 예시
함수 내부에서는 조건문을 이용해서 실행 흐름을 제어하는 것이 가능합니다.
솔리디티는 C나 JavaScript와 유사한 문법과 의미를 가지는 if 및 else 키워드 그리고 이러한 if 및 else 키워드의 사용방법은 다른 프로그래밍 언어와 크게 다르지 않습니다.
contract IfElse{
function foo(uint index) public pure returns(uint) {
if (x < 10) {
return 0;
} else if (x < 20) {
return 1;
} else {
return 2;
}
}
}
if 및 else 예시
Solidity는 반복문도 지원하는데요, C언어와 동일한 방법으로 for문과 while문을 사용할 수가 있습니다. 그리고 반복문에서 탈출하는 브레이크와 컨티뉴와 같은 키워드 기능들도 함께 제공을 합니다.
contract Loop {
//for loop
function loop() public {
for (uint i = 0; i < 10; i++) {
if (i == 3) {
continue;
}
if (i == 5) {
break;
}
}
//while loop
uint i;
while (i < 10) {
i++;
}
}
}
for 및 while 반복문 예시
변수에 대해서 가시성, 즉 Visibility를 지정하는 것과 유사한 방법으로 함수에 대해서도 가시성, Visibility를 지정할 수 있습니다. 모든 함수는 가시성이 지정되어야하는데요, 4가지의 가시성이 존재합니다.
먼저, 컨트랙트 내부에서만 접근할 수 있는 internal과 private이 있으며, 여기에서 internal은 상속을 받은 자식 컨트랙트에서도 접근이 가능한 반면, private는 자식 컨트랙트에서는 접근이 불가능한 가시성 유형입니다.
반면에 public은 컨트랙트 내부 및 외부에서 모두 접근이 가능합니다. external로 지정된 경우에는 외부 컨텍스트에서만 또는 외부에서만 접근이 가능합니다.
솔리디티의 함수는 상태변경성, 즉, state mutability라는 속성을 가지는데요. 이는 함수의 권한범위를 지정하는 것과 비슷한 개념입니다. 여기에는 총 4가지 종류가 있습니다.
먼저, 상태변경성을 별도로 지정하지 않으면 상태변수를 포함해 블록체인의 상태를 변경하는 것이 가능하며, 두 번째로는 상태를 변경하지 않고 상태값을 읽기만 하는 것을 허용하는 view, 세 번째는 상태를 변경 하지도 또 읽지도 않는 pure, 마지막으로 상태 변경을 물론이고 누군가 자신에게 이더를 송금 했을 때 그 송금된 이더를 수신할 수 있는 payable이 있습니다.
대부분의 컨트랙트에 기본적으로 포함되는 함수는 생성자 함수 입니다. 생성자 함수는 두 가지의 특징 또는 용도가 있는데요.
먼저, 생성자 함수는 컨트랙트를 배포할 때만 1회 실행되는 함수입니다. 이러한 특징을 이용해서 보통 컨트랙트에서는 배포자의 주소를 얻어 낼 때, 즉 msg라는 객체에 sender라는 필드. 그 변수 값을 얻어내는 용도로 많이 활용이 되기도 합니다.
그리고 두 번째로, 생성자 함수에서는 컨트랙트의 상태변수들을 초기화하는 것이 일반적인데요. 만약에 이 생성자함수에서 컨트랙트 변수, 상태변수들을 초기화 하지 않았을 경우에는, 기본적으로 'zero state'를 갖도록, 즉 int나 uint형은 0, bool형은 false로 초기화됩니다.
컨트랙트에 포함되는 또다른 기본적인 함수로 겟터 함수란 것이 있습니다. 겟터 함수는 public 유형의 가시성을 가지는 상태변수를 반환하는 함수입니다. 이 경우는 프로그래머가 별도로 상태변수를 읽는 함수를 정의하지 않아도 솔리디티로 작성된 컨트랙트 코드가 컴파일 될 때, 컴파일러에 의해서 상태 변수를 읽는 겟터 함수라는 것이 자동으로 생성됩니다. 그래서 겟터함수는 함수의 이름이 상태변수의 이름과 동일하고, 가시성은 기본적으로 external로 설정이 됩니다. 또한 상태변수가 배열일 경우에는 원소를 하나씩 반환하는 특징이 있습니다.
솔리디티에서는 프로그래머가 정의하지 않고 사용할 수 있는 내장형 특수전역함수들이 다수 제공이 됩니다.
하나는 수학 및 암호 연산에 필요한 함수들이 있습니다.
예를 들면, 두 개의 값을 더한 후에 나머지를 구하는 addmod, 또는 두 개의 값을 곱한 후에 나머지를 구하는 mulmod, 그리고 keccack이나 sha256 같은 해시 함수들도 제공이 되고 있습니다.
그리고 ABI 인코딩 및 디코딩 함수들이 있습니다.
ABI라는 것은 컨트랙트간 어떤 데이터난 정보교환을 할 때, 사용되는 일종의 Low level interface에 해당됩니다. 그리고, 인코딩과 디코딩은 보통 우리가 네트워크를 통해서 어떤 데이터를 주고 받을 때 부호화 및 복호화 하는 것을 의미합니다. 예를 들면 알파벳 "A"라는 것은 ASCII Code에 의해서 65라는 숫자로 변환이 된 다음에 네크워크 상의 컴퓨터들이 그 정보를 교환하도록 약속된 부호화, 복호화 과정이 필요한데요. 그래서 그런 ABI 인코딩과 디코딩에 필요한 abi.encode, abi.decode 등의 함수들이 제공이 됩니다.
그리고 컨트랙트 간의 상태방의 함수 호출에 필요한 함수의 이름 또는 그 문법적인 성질을 시그니처라고 하는데요. 그런 시그니처와 함께 함수호출에 필요한 실제 파라미터 값들과 함께 ABI 인코딩 또는 디코딩을 할 수 있습니다. 그래서 그런 기능을 제공하는 abi.encodeWithSignature 또는 유사한 abi.encodeWithSelector 등의 함수들도 제공이 되고 있습니다.