견고성-퀵 가이드
Solidity는 스마트 계약을 구현하기위한 계약 지향의 고급 프로그래밍 언어입니다. Solidity는 C ++, Python 및 JavaScript의 영향을 많이 받았으며 Ethereum Virtual Machine (EVM)을 대상으로 설계되었습니다.
Solidity는 정적으로 형식화되고 상속, 라이브러리 및 복잡한 사용자 정의 형식 프로그래밍 언어를 지원합니다.
Solidity를 사용하여 투표, 크라우드 펀딩, 블라인드 경매 및 다중 서명 지갑과 같은 용도로 계약을 생성 할 수 있습니다.
이더 리움이란?
이더 리움은 분산 형 즉, 스마트 계약을 실행하는 블록 체인 플랫폼, 즉 다운 타임, 검열, 사기 또는 제 3 자 간섭의 가능성없이 프로그래밍 된대로 정확하게 실행되는 애플리케이션.
Ethereum 가상 머신 (EVM)
EVM이라고도하는 이더 리움 가상 머신은 이더 리움의 스마트 계약을위한 런타임 환경입니다. Ethereum Virtual Machine은 전 세계 컴퓨터에서 보안을 제공하고 신뢰할 수없는 코드를 실행하는 데 중점을 둡니다.
서비스 거부 공격을 방지하는 데 특화된 EVM은 프로그램이 서로의 상태에 액세스하지 못하도록하여 잠재적 인 간섭없이 통신을 설정할 수 있도록합니다.
이더 리움 가상 머신은 이더 리움 기반 스마트 계약을위한 런타임 환경 역할을하도록 설계되었습니다.
스마트 계약이란 무엇입니까?
스마트 계약은 계약의 협상 또는 이행을 디지털 방식으로 촉진, 확인 또는 시행하기위한 컴퓨터 프로토콜입니다. 스마트 계약을 통해 제 3 자없이 신뢰할 수있는 거래를 수행 할 수 있습니다. 이러한 거래는 추적 가능하고 되돌릴 수 없습니다.
스마트 계약의 개념은 1994 년 Nick Szabo에 의해 처음 제안되었습니다. Szabo는 디지털 통화의 토대를 마련한 것으로 알려진 법률 학자이자 암호 학자입니다.
지금 당장 스마트 컨트랙트를 이해하지 못해도 괜찮습니다. 나중에 자세히 설명하겠습니다.
이 장에서는 CentOS 시스템에서 Solidity 컴파일러를 설정하는 방법을 설명합니다. Linux 머신이없는 경우 소규모 계약 및 Solidity 학습을 위해 온라인 컴파일러를 사용할 수 있습니다.
방법 1-npm / Node.js
이것이 CentoS Machine에 Solidity 컴파일러를 설치하는 가장 빠른 방법입니다. Solidity Compiler를 설치하려면 다음 단계가 있습니다.
Node.js 설치
먼저 CentOS 컴퓨터에서 node.js를 사용할 수 있는지 확인하십시오. 사용할 수없는 경우 다음 명령을 사용하여 설치하십시오.
# First install epel-release
$sudo yum install epel-release
# Now install nodejs
$sudo yum install nodejs
# Next install npm (Nodejs Package Manager )
$sudo yum install npm
# Finally verify installation
$npm --version
모든 것이 설치 되었다면 다음과 같은 출력을 볼 수 있습니다.
3.10.10
solc 설치
Node.js 패키지 관리자가 설치되면 다음과 같이 Solidity 컴파일러를 설치할 수 있습니다.
$sudonpm install -g solc
위의 명령은 solcjs 프로그램을 설치하고 시스템을 통해 전역 적으로 사용할 수 있도록합니다. 이제 다음 명령을 실행하여 Solidity 컴파일러를 테스트 할 수 있습니다.
$solcjs-version
모든 것이 잘되면 다음과 같이 인쇄됩니다.
0.5.2+commit.1df8f40c.Emscripten.clang
이제 표준 Solidity 컴파일러보다 기능이 적은 solcjs를 사용할 준비가되었지만 좋은 시작점을 제공 할 것입니다.
방법 2-Docker 이미지
Docker 이미지를 가져 와서 Solidity 프로그래밍을 시작하는 데 사용할 수 있습니다. 다음은 간단한 단계입니다. 다음은 Solidity Docker 이미지를 가져 오는 명령입니다.
$docker pull ethereum/solc:stable
도커 이미지가 다운로드되면 다음 명령을 사용하여 확인할 수 있습니다.
$docker run ethereum/solc:stable-version
다음과 같이 인쇄됩니다.
$ docker run ethereum/solc:stable -version
solc, the solidity compiler commandlineinterfaceVersion: 0.5.2+commit.1df8f40c.Linux.g++
방법 3 : 바이너리 패키지 설치
Linux 시스템에 완전한 컴파일러를 설치하려면 공식 웹 사이트 인 솔리 디티 컴파일러 설치를 확인하십시오.
Solidity 소스 파일에는 여러 계약 정의, 가져 오기 지시문 및 pragma 지시문이 포함될 수 있습니다.
Solidity의 간단한 소스 파일부터 시작하겠습니다. 다음은 Solidity 파일의 예입니다.
pragma solidity >=0.4.0 <0.6.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}
프라 그마
첫 번째 줄은 소스 코드가 Solidity 버전 0.4.0 또는 0.6.0 버전까지 기능을 중단하지 않는 최신 버전에 대해 작성되었음을 알려주는 pragma 지시문입니다.
pragma 지시문은 항상 소스 파일에 대해 로컬이며 다른 파일을 가져 오는 경우 해당 파일의 pragma가 가져 오는 파일에 자동으로 적용되지 않습니다.
따라서 버전 0.4.0 이전에 컴파일되지 않고 버전 0.5.0부터 시작되는 컴파일러에서도 작동하지 않는 파일에 대한 pragma는 다음과 같이 작성됩니다.
pragma solidity ^0.4.0;
여기서 두 번째 조건은 ^를 사용하여 추가됩니다.
계약
Solidity 계약은 이더 리움 블록 체인의 특정 주소에있는 코드 (기능) 및 데이터 (상태)의 모음입니다.
uintstoredData 행은 uint 유형의 storedData라는 상태 변수를 선언하고 set 및 get 함수를 사용하여 변수 값을 수정하거나 검색 할 수 있습니다.
파일 가져 오기
위의 예에는 import 문이 없지만 Solidity는 JavaScript에서 사용할 수있는 것과 매우 유사한 import 문을 지원합니다.
다음 문은 "filename"에서 모든 전역 기호를 가져옵니다.
import "filename";
다음 예제에서는 구성원이 "filename"의 모든 전역 기호 인 새 전역 기호 symbolName을 만듭니다.
import * as symbolName from "filename";
현재 파일과 동일한 디렉토리에서 x 파일을 가져 오려면 import "./x"를 x;로 사용하십시오. import "x"를 x로 사용한다면; 대신 전역 "포함 디렉토리"에서 다른 파일을 참조 할 수 있습니다.
예약 된 키워드
다음은 Solidity에서 예약 된 키워드입니다-
요약 | 후 | 별명 | 대다 |
자동 | 케이스 | 잡기 | 복사본 |
기본 | 밝히다 | 결정적인 | 불변 |
구현 | 에 | 인라인 | 허락하다 |
매크로 | 시합 | 변하기 쉬운 | 없는 |
의 | 우세하다 | 부분적인 | 약속 |
참고 | 재배치 가능 | 봉인 | 크기 |
공전 | 지원 | 스위치 | 시험 |
typedef | 유형 | 선택 취소 |
우리는 Solidity Code 기반을 컴파일하고 실행하기 위해 Remix IDE 를 사용 하고 있습니다.
Step 1 − Remix IDE 코드 섹션에서 주어진 코드를 복사합니다.
예
pragma solidity ^0.5.0;
contract SolidityTest {
constructor() public{
}
function getResult() public view returns(uint){
uint a = 1;
uint b = 2;
uint result = a + b;
return result;
}
}
Step 2 − 컴파일 탭에서 Start to Compile 단추.
Step 3 − 실행 탭에서 Deploy 단추.
Step 4 − 실행 탭에서 선택 SolidityTest at 0x... 드롭 다운에서.
Step 5 − 클릭 getResult 결과를 표시하는 버튼입니다.
산출
0: uint256: 3
Solidity는 C 스타일과 C ++ 스타일 주석을 모두 지원합니다.
//와 줄 끝 사이의 모든 텍스트는 주석으로 처리되며 Solidity Compiler에서 무시됩니다.
/ *와 * / 사이의 모든 텍스트는 주석으로 처리됩니다. 이것은 여러 줄에 걸쳐있을 수 있습니다.
예
다음 예제는 Solidity에서 주석을 사용하는 방법을 보여줍니다.
function getResult() public view returns(uint){
// This is a comment. It is similar to comments in C++
/*
* This is a multi-line comment in solidity
* It is very similar to comments in C Programming
*/
uint a = 1;
uint b = 2;
uint result = a + b;
return result;
}
어떤 언어로든 프로그램을 작성하는 동안 다양한 정보를 저장하려면 다양한 변수를 사용해야합니다. 변수는 값을 저장하기 위해 예약 된 메모리 위치 일뿐입니다. 이것은 변수를 만들 때 메모리에 약간의 공간을 예약한다는 것을 의미합니다.
문자, 와이드 문자, 정수, 부동 소수점, 이중 부동 소수점, 부울 등과 같은 다양한 데이터 유형의 정보를 저장하고 싶을 수 있습니다. 운영 체제는 변수의 데이터 유형에 따라 메모리를 할당하고 저장할 수있는 항목을 결정합니다. 예약 된 메모리.
값 유형
Solidity는 프로그래머에게 다양한 내장 및 사용자 정의 데이터 유형을 제공합니다. 다음 표는 7 가지 기본 C ++ 데이터 유형을 나열합니다.
유형 | 예어 | 가치 |
---|---|---|
부울 | 부울 | 허위 사실 |
정수 | int / uint | 다양한 크기의 부호있는 정수와 부호없는 정수. |
정수 | int8에서 int256 | 8 비트에서 256 비트까지의 부호있는 int입니다. int256은 int와 동일합니다. |
정수 | uint8에서 uint256으로 | 8 비트에서 256 비트까지의 부호없는 정수입니다. uint256은 uint와 동일합니다. |
고정 소수점 수 | 고정 / 비 고정 | 다양한 크기의 부호있는 및 부호없는 고정 소수점 숫자. |
고정 소수점 수 | 고정 / 비 고정 | 다양한 크기의 부호있는 및 부호없는 고정 소수점 숫자. |
고정 소수점 수 | fixedMxN | M은 유형별로 사용되는 비트 수를 나타내고 N은 소수점을 나타내는 부호있는 고정 소수점 숫자입니다. M은 8로 나눌 수 있어야하며 8에서 256까지입니다. N은 0에서 80까지 가능합니다. fixed는 fixed128x18과 동일합니다. |
고정 소수점 수 | ufixedMxN | M은 유형별로 사용되는 비트 수를 나타내고 N은 소수점을 나타내는 부호없는 고정 소수점 숫자입니다. M은 8로 나눌 수 있어야하며 8에서 256까지입니다. N은 0에서 80까지입니다. ufixed는 ufixed128x18과 동일합니다. |
주소
address는 이더 리움 주소의 크기를 나타내는 20 바이트 값을 보유합니다. .balance 방법을 사용하여 잔액을 가져 오는 데 주소를 사용할 수 있으며 .transfer 방법을 사용하여 다른 주소로 잔액을 이체하는 데 사용할 수 있습니다.
address x = 0x212;
address myAddress = this;
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
Solidity는 세 가지 유형의 변수를 지원합니다.
State Variables − 값이 계약 저장소에 영구적으로 저장되는 변수.
Local Variables − 함수가 실행될 때까지 값이 존재하는 변수.
Global Variables − 블록 체인에 대한 정보를 얻는 데 사용되는 글로벌 네임 스페이스에는 특수 변수가 있습니다.
Solidity는 정적으로 형식화 된 언어로 선언 중에 상태 또는 지역 변수 형식을 지정해야 함을 의미합니다. 선언 된 각 변수에는 항상 유형에 따라 기본값이 있습니다. "undefined"또는 "null"이라는 개념이 없습니다.
상태 변수
값이 계약 저장소에 영구적으로 저장되는 변수입니다.
pragma solidity ^0.5.0;
contract SolidityTest {
uint storedData; // State variable
constructor() public {
storedData = 10; // Using State variable
}
}
지역 변수
값이 정의 된 함수 내에서만 사용할 수있는 변수입니다. 함수 매개 변수는 항상 해당 함수에 로컬입니다.
pragma solidity ^0.5.0;
contract SolidityTest {
uint storedData; // State variable
constructor() public {
storedData = 10;
}
function getResult() public view returns(uint){
uint a = 1; // local variable
uint b = 2;
uint result = a + b;
return result; //access the local variable
}
}
예
pragma solidity ^0.5.0;
contract SolidityTest {
uint storedData; // State variable
constructor() public {
storedData = 10;
}
function getResult() public view returns(uint){
uint a = 1; // local variable
uint b = 2;
uint result = a + b;
return storedData; //access the state variable
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: uint256: 10
글로벌 변수
이들은 글로벌 작업 공간에 존재하는 특수 변수이며 블록 체인 및 트랜잭션 속성에 대한 정보를 제공합니다.
이름 | 보고 |
---|---|
blockhash (uint blockNumber) 반환 (bytes32) | 주어진 블록의 해시-현재 블록을 제외하고 가장 최근 256 개에 대해서만 작동합니다. |
block.coinbase (지불 가능 주소) | 현재 블록 채굴 자의 주소 |
block.difficulty (단위) | 현재 블록 난이도 |
block.gaslimit (단위) | 현재 블록 가스 제한 |
block.number (단위) | 현재 블록 번호 |
block.timestamp (단위) | 유닉스 시대 이후 현재 블록 타임 스탬프 (초) |
gasleft () 반환 (uint256) | 남은 가스 |
msg.data (바이트 calldata) | 완전한 통화 데이터 |
msg.sender (지불 가능한 주소) | 메시지 발신자 (현재 발신자) |
msg.sig (bytes4) | calldata (함수 식별자)의 처음 4 바이트 |
msg.value (단위) | 메시지와 함께 보낸 wei의 수 |
지금 (단위) | 현재 블록 타임 스탬프 |
tx.gasprice (단위) | 거래의 가스 가격 |
tx.origin (지불 가능 주소) | 거래 발신자 |
견고성 변수 이름
Solidity에서 변수 이름을 지정할 때 다음 규칙을 염두에 두십시오.
Solidity 예약 키워드를 변수 이름으로 사용해서는 안됩니다. 이러한 키워드는 다음 섹션에서 언급됩니다. 예를 들어, break 또는 boolean 변수 이름은 유효하지 않습니다.
Solidity 변수 이름은 숫자 (0-9)로 시작하지 않아야합니다. 문자 또는 밑줄 문자로 시작해야합니다. 예를 들어 123test는 잘못된 변수 이름이지만 _123test는 유효한 이름입니다.
Solidity 변수 이름은 대소 문자를 구분합니다. 예를 들어 이름과 이름은 서로 다른 두 변수입니다.
지역 변수의 범위는 정의 된 함수로 제한되지만 상태 변수는 세 가지 유형의 범위를 가질 수 있습니다.
Public− 공개 상태 변수는 내부적으로는 물론 메시지를 통해서도 접근 할 수 있습니다. 공용 상태 변수의 경우 자동 getter 함수가 생성됩니다.
Internal − 내부 상태 변수는 현재 계약 또는이를 사용하지 않고 파생 된 계약에서 내부적으로 만 액세스 할 수 있습니다.
Private − 개인 상태 변수는 파생 된 계약이 아닌 현재 계약에서 내부적으로 만 액세스 할 수 있습니다.
예
pragma solidity ^0.5.0;
contract C {
uint public data = 30;
uint internal iData= 10;
function x() public returns (uint) {
data = 3; // internal access
return data;
}
}
contract Caller {
C c = new C();
function f() public view returns (uint) {
return c.data(); //external access
}
}
contract D is C {
function y() public returns (uint) {
iData = 3; // internal access
return iData;
}
function getResult() public view returns(uint){
uint a = 1; // local variable
uint b = 2;
uint result = a + b;
return storedData; //access the state variable
}
}
운영자는 무엇입니까?
간단한 표현을합시다 4 + 5 is equal to 9. 여기서 4와 5는operands 그리고 '+'는 operator. Solidity는 다음 유형의 연산자를 지원합니다.
- 산술 연산자
- 비교 연산자
- 논리 (또는 관계형) 연산자
- 할당 연산자
- 조건부 (또는 삼항) 연산자
모든 연산자를 하나씩 살펴 보겠습니다.
산술 연산자
Solidity는 다음과 같은 산술 연산자를 지원합니다.
변수 A가 10을 보유하고 변수 B가 20을 보유한다고 가정하면-
보기 예
Sr. 아니. | 연산자 및 설명 |
---|---|
1 | + (Addition) 두 개의 피연산자를 더합니다. Ex: A + B는 30을 줄 것입니다 |
2 | - (Subtraction) 첫 번째에서 두 번째 피연산자를 뺍니다. Ex: A-B는 -10을 줄 것입니다. |
삼 | * (Multiplication) 두 피연산자 곱하기 Ex: A * B는 200을 줄 것입니다 |
4 | / (Division) 분자를 분모로 나눕니다. Ex: B / A는 2를 줄 것입니다 |
5 | % (Modulus) 정수 나눗셈의 나머지를 출력합니다. Ex: B % A는 0을 제공합니다. |
6 | ++ (Increment) 정수 값을 1 씩 증가시킵니다. Ex: A ++는 11을 줄 것입니다 |
7 | -- (Decrement) 정수 값을 1 씩 줄입니다. Ex: A-- 9를 줄 것입니다 |
비교 연산자
Solidity는 다음 비교 연산자를 지원합니다-
변수 A가 10을 보유하고 변수 B가 20을 보유한다고 가정하면-
보기 예
Sr. 아니. | 연산자 및 설명 |
---|---|
1 | = = (Equal) 두 피연산자의 값이 같은지 확인합니다. 그렇다면 조건이 참이됩니다. Ex: (A == B)는 사실이 아닙니다. |
2 | != (Not Equal) 두 피연산자의 값이 같은지 확인하고, 값이 같지 않으면 조건이 참이됩니다. Ex: (A! = B)는 참입니다. |
삼 | > (Greater than) 왼쪽 피연산자의 값이 오른쪽 피연산자의 값보다 큰지 확인하고, 그렇다면 조건이 참이됩니다. Ex: (A> B)는 사실이 아닙니다. |
4 | < (Less than) 왼쪽 피연산자의 값이 오른쪽 피연산자의 값보다 작은 지 확인하고, 그렇다면 조건이 참이됩니다. Ex: (A <B)는 사실입니다. |
5 | >= (Greater than or Equal to) 왼쪽 피연산자의 값이 오른쪽 피연산자의 값보다 크거나 같은지 확인합니다. 그렇다면 조건이 참이됩니다. Ex: (A> = B)는 사실이 아닙니다. |
6 | <= (Less than or Equal to) 왼쪽 피연산자의 값이 오른쪽 피연산자의 값보다 작거나 같은지 확인합니다. 그렇다면 조건이 참이됩니다. Ex: (A <= B)는 참입니다. |
논리 연산자
Solidity는 다음 논리 연산자를 지원합니다-
변수 A가 10을 보유하고 변수 B가 20을 보유한다고 가정하면-
보기 예
Sr. 아니. | 연산자 및 설명 |
---|---|
1 | && (Logical AND) 두 피연산자가 모두 0이 아니면 조건이 참이됩니다. Ex: (A && B)는 사실입니다. |
2 | || (Logical OR) 두 피연산자 중 하나가 0이 아니면 조건이 참이됩니다. Ex: (A || B)는 사실입니다. |
삼 | ! (Logical NOT) 피연산자의 논리적 상태를 되돌립니다. 조건이 참이면 논리 NOT 연산자는 조건을 거짓으로 만듭니다. Ex:! (A && B)는 거짓입니다. |
비트 연산자
Solidity는 다음과 같은 비트 연산자를 지원합니다.
변수 A에 2가 있고 변수 B에 3이 있다고 가정하면-
보기 예
Sr. 아니. | 연산자 및 설명 |
---|---|
1 | & (Bitwise AND) 정수 인수의 각 비트에 대해 부울 AND 연산을 수행합니다. Ex: (A & B)는 2입니다. |
2 | | (BitWise OR) 정수 인수의 각 비트에 대해 부울 OR 연산을 수행합니다. Ex: (A | B)는 3입니다. |
삼 | ^ (Bitwise XOR) 정수 인수의 각 비트에 대해 부울 배타적 OR 연산을 수행합니다. 배타적 OR은 피연산자 1이 참이거나 피연산자 2가 참이지만 둘다는 아니라는 것을 의미합니다. Ex: (A ^ B)는 1입니다. |
4 | ~ (Bitwise Not) 단항 연산자이며 피연산자의 모든 비트를 반전하여 작동합니다. Ex: (~ B)는 -4입니다. |
5 | << (Left Shift) 첫 번째 피연산자의 모든 비트를 두 번째 피연산자에 지정된 자릿수만큼 왼쪽으로 이동합니다. 새 비트는 0으로 채워집니다. 값을 한 위치 왼쪽으로 이동하는 것은 2를 곱하는 것과 같고, 두 위치를 이동하는 것은 4를 곱하는 것과 같습니다. Ex: (A << 1)은 4입니다. |
6 | >> (Right Shift) 이진 오른쪽 시프트 연산자. 왼쪽 피연산자의 값은 오른쪽 피연산자가 지정한 비트 수만큼 오른쪽으로 이동합니다. Ex: (A >> 1)은 1입니다. |
7 | >>> (Right shift with Zero) 이 연산자는 >> 연산자와 비슷하지만 왼쪽에서 이동 된 비트가 항상 0이라는 점이 다릅니다. Ex: (A >>> 1)은 1입니다. |
할당 연산자
Solidity는 다음 할당 연산자를 지원합니다-
보기 예
Sr. 아니. | 연산자 및 설명 |
---|---|
1 | = (Simple Assignment ) 오른쪽 피연산자의 값을 왼쪽 피연산자에 할당합니다. Ex: C = A + B는 A + B의 값을 C에 할당합니다. |
2 | += (Add and Assignment) 왼쪽 피연산자에 오른쪽 피연산자를 추가하고 결과를 왼쪽 피연산자에 할당합니다. Ex: C + = A는 C = C + A와 같습니다. |
삼 | −= (Subtract and Assignment) 왼쪽 피연산자에서 오른쪽 피연산자를 빼고 결과를 왼쪽 피연산자에 할당합니다. Ex: C-= A는 C = C-A와 같습니다. |
4 | *= (Multiply and Assignment) 오른쪽 피연산자와 왼쪽 피연산자를 곱하고 결과를 왼쪽 피연산자에 할당합니다. Ex: C * = A는 C = C * A와 같습니다. |
5 | /= (Divide and Assignment) 왼쪽 피연산자를 오른쪽 피연산자로 나누고 결과를 왼쪽 피연산자에 할당합니다. Ex: C / = A는 C = C / A와 같습니다. |
6 | %= (Modules and Assignment) 두 개의 피연산자를 사용하여 모듈러스를 취하고 결과를 왼쪽 피연산자에 할당합니다. Ex: C % = A는 C = C % A와 같습니다. |
Note − 동일한 논리가 비트 연산자에도 적용되므로 << =, >> =, >> =, & =, | = 및 ^ =처럼됩니다.
조건부 연산자 (? :)
조건부 연산자는 먼저 표현식에서 참 또는 거짓 값을 평가 한 다음 평가 결과에 따라 주어진 두 명령문 중 하나를 실행합니다.
보기 예
Sr. 아니. | 연산자 및 설명 |
---|---|
1 | ? : (Conditional ) 조건이 참이면? 그런 다음 값 X : 그렇지 않으면 값 Y |
계약서를 작성하는 동안 작업을 반복해서 수행해야하는 상황이 발생할 수 있습니다. 이러한 상황에서는 줄 수를 줄이기 위해 루프 문을 작성해야합니다.
Solidity는 프로그래밍의 부담을 덜어주기 위해 필요한 모든 루프를 지원합니다.
Sr. 아니요 | 루프 및 설명 |
---|---|
1 | While 루프 Solidity에서 가장 기본적인 루프는이 장에서 논의 할 while 루프입니다. |
2 | do ... while 루프 do ... while 루프는 조건 검사가 루프 끝에서 발생한다는 점을 제외하면 while 루프와 유사합니다. |
삼 | For 루프 for 루프는 가장 컴팩트 한 형태의 루프입니다. 여기에는 다음 세 가지 중요한 부분이 포함됩니다. |
4 | 루프 제어 Solidity는 루프 및 switch 문을 처리하기위한 모든 권한을 제공합니다. |
프로그램을 작성하는 동안 주어진 경로 세트 중 하나를 채택해야하는 상황이있을 수 있습니다. 이러한 경우 프로그램이 올바른 결정을 내리고 올바른 작업을 수행 할 수 있도록하는 조건문을 사용해야합니다.
Solidity는 다양한 조건에 따라 다른 작업을 수행하는 데 사용되는 조건문을 지원합니다. 여기서 우리는if..else 성명서.
if-else의 흐름도
다음 순서도는 if-else 문이 작동하는 방식을 보여줍니다.
Solidity는 다음 형식을 지원합니다. if..else 성명-
Sr. 아니요 | 진술 및 설명 |
---|---|
1 | if 문 if 문은 Solidity가 결정을 내리고 조건부로 문을 실행할 수 있도록하는 기본 제어 문입니다. |
2 | if ... else 문 'if ... else'문은 Solidity가보다 제어 된 방식으로 문을 실행할 수있게 해주는 다음 형태의 제어 문입니다. |
삼 | if ... else if ... 문. if ... else if ... 문은 Solidity가 여러 조건에서 올바른 결정을 내릴 수 있도록하는 if ... else의 고급 형식입니다. |
Solidity는 큰 따옴표 ( ")와 작은 따옴표 ( ')를 모두 사용하는 문자열 리터럴을 지원하며 문자열 유형의 변수를 선언하기위한 데이터 유형으로 문자열을 제공합니다.
pragma solidity ^0.5.0;
contract SolidityTest {
string data = "test";
}
위의 예에서 "test"는 문자열 리터럴이고 data는 문자열 변수입니다. 더 선호되는 방법은 문자열 작업이 바이트 작업에 비해 더 많은 가스를 필요로하기 때문에 문자열 대신 바이트 유형을 사용하는 것입니다. Solidity는 바이트를 문자열로 또는 그 반대로 내장 변환을 제공합니다. Solidity에서는 문자열 리터럴을 byte32 유형 변수에 쉽게 할당 할 수 있습니다. Solidity는이를 byte32 리터럴로 간주합니다.
pragma solidity ^0.5.0;
contract SolidityTest {
bytes32 data = "test";
}
이스케이프 문자
Sr. 아니. | 캐릭터 및 설명 |
---|---|
1 | \n 새 줄을 시작합니다. |
2 | \\ 백 슬래시 |
삼 | \' 작은 따옴표 |
4 | \" 큰 따옴표 |
5 | \b 역행 키이 |
6 | \f 양식 공급 |
7 | \r 캐리지 리턴 |
8 | \t 탭 |
9 | \v 수직 탭 |
10 | \xNN 16 진수 값을 나타내고 적절한 바이트를 삽입합니다. |
11 | \uNNNN 유니 코드 값을 나타내고 UTF-8 시퀀스를 삽입합니다. |
바이트에서 문자열로 변환
string () 생성자를 사용하여 바이트를 String으로 변환 할 수 있습니다.
bytes memory bstr = new bytes(10);
string message = string(bstr);
예
Solidity에서 문자열이 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract SolidityTest {
constructor() public{
}
function getResult() public view returns(string memory){
uint a = 1;
uint b = 2;
uint result = a + b;
return integerToString(result);
}
function integerToString(uint _i) internal pure
returns (string memory) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len - 1;
while (_i != 0) {
bstr[k--] = byte(uint8(48 + _i % 10));
_i /= 10;
}
return string(bstr);
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: string: 3
배열은 동일한 유형의 요소의 고정 크기 순차 컬렉션을 저장하는 데이터 구조입니다. 배열은 데이터 모음을 저장하는 데 사용되지만 배열을 동일한 유형의 변수 모음으로 생각하는 것이 더 유용합니다.
number0, number1, ..., number99와 같은 개별 변수를 선언하는 대신 숫자와 같은 하나의 배열 변수를 선언하고 numbers [0], numbers [1] 및 ..., numbers [99]를 사용하여 개별 변수. 배열의 특정 요소는 인덱스로 액세스됩니다.
Solidity에서 배열은 컴파일 타임 고정 크기 또는 동적 크기 일 수 있습니다. 스토리지 어레이의 경우 다른 유형의 요소도 가질 수 있습니다. 메모리 배열의 경우 요소 유형은 매핑 될 수 없으며 함수 매개 변수로 사용되는 경우 요소 유형은 ABI 유형이어야합니다.
모든 어레이는 연속적인 메모리 위치로 구성됩니다. 가장 낮은 주소는 첫 번째 요소에 해당하고 가장 높은 주소는 마지막 요소에 해당합니다.
배열 선언
Solidity에서 고정 크기의 배열을 선언하기 위해 프로그래머는 다음과 같이 배열에 필요한 요소의 유형과 요소의 수를 지정합니다.
type arrayName [ arraySize ];
이를 1 차원 배열이라고합니다. 그만큼arraySize 0보다 큰 정수 상수 여야하며 type유효한 Solidity 데이터 유형이 될 수 있습니다. 예를 들어, uint 유형의 balance라는 10 개 요소 배열을 선언하려면 다음 명령문을 사용하십시오.
uint balance[10];
Solidity에서 동적 크기의 배열을 선언하기 위해 프로그래머는 다음과 같이 요소의 유형을 지정합니다.
type[] arrayName;
배열 초기화
다음과 같이 Solidity 배열 요소를 하나씩 또는 단일 문을 사용하여 초기화 할 수 있습니다.
uint balance[3] = [1, 2, 3];
중괄호 [] 사이의 값 수는 대괄호 [] 사이의 배열에 대해 선언 한 요소 수보다 클 수 없습니다. 다음은 배열의 단일 요소를 할당하는 예입니다.
배열의 크기를 생략하면 초기화를 저장할 수있을만큼 큰 배열이 생성됩니다. 따라서 다음과 같이 쓰면-
uint balance[] = [1, 2, 3];
이전 예제에서했던 것과 똑같은 배열을 만들 것입니다.
balance[2] = 5;
위의 명령문 은 배열의 3 번째 요소 에 값 5를 할당합니다 .
동적 메모리 배열 만들기
동적 메모리 배열은 new 키워드를 사용하여 생성됩니다.
uint size = 3;
uint balance[] = new uint[](size);
배열 요소에 액세스
배열 이름을 인덱싱하여 요소에 액세스합니다. 이는 배열 이름 뒤에 대괄호 안에 요소의 인덱스를 배치하여 수행됩니다. 예를 들면-
uint salary = balance[2];
위의 문은 배열에서 세 번째 요소를 가져와 급여 변수에 값을 할당합니다. 다음은 위에서 언급 한 세 가지 개념을 모두 사용하는 예입니다. 선언, 할당 및 액세스 배열-
회원
length− 길이는 배열의 크기를 반환합니다. length는 동적 배열의 크기를 변경하는 데 사용할 수 있습니다.
push− 푸시는 끝에 동적 스토리지 배열에 요소를 추가 할 수 있습니다. 배열의 새 길이를 반환합니다.
예
Solidity에서 배열이 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract test {
function testArray() public pure{
uint len = 7;
//dynamic array
uint[] memory a = new uint[](7);
//bytes is same as byte[]
bytes memory b = new bytes(len);
assert(a.length == 7);
assert(b.length == len);
//access array variable
a[6] = 8;
//test array variable
assert(a[6] == 8);
//static array
uint[3] memory c = [uint(1) , 2, 3];
assert(c.length == 3);
}
}
열거 형은 미리 정의 된 몇 가지 값 중 하나만 갖도록 변수를 제한합니다. 이 열거 형 목록의 값을 열거 형이라고합니다.
열거 형을 사용하면 코드의 버그 수를 줄일 수 있습니다.
예를 들어, 신선한 주스 가게에 대한 응용 프로그램을 고려하면 유리 크기를 소형, 중형 및 대형으로 제한 할 수 있습니다. 이렇게하면 누구도 소형, 중형 또는 대형 이외의 크기를 주문할 수 없습니다.
예
Solidity에서 열거 형이 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract test {
enum FreshJuiceSize{ SMALL, MEDIUM, LARGE }
FreshJuiceSize choice;
FreshJuiceSize constant defaultChoice = FreshJuiceSize.MEDIUM;
function setLarge() public {
choice = FreshJuiceSize.LARGE;
}
function getChoice() public view returns (FreshJuiceSize) {
return choice;
}
function getDefaultChoice() public pure returns (uint) {
return uint(defaultChoice);
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
첫 번째 클릭 setLarge 값을 LARGE로 설정하는 버튼을 클릭 한 다음 getChoice 선택한 선택을 얻으려면.
산출
uint8: 2
딸깍 하는 소리 getDefaultChoice 기본 선택을 가져 오는 버튼입니다.
산출
uint256: 1
구조 유형은 레코드를 나타내는 데 사용됩니다. 도서관에서 책을 추적하고 싶다고 가정 해 보겠습니다. 각 책에 대한 다음 속성을 추적 할 수 있습니다.
- Title
- Author
- Subject
- 도서 ID
구조체 정의
Struct를 정의하려면 struct예어. struct 키워드는 둘 이상의 멤버가있는 새 데이터 유형을 정의합니다. struct 문의 형식은 다음과 같습니다.
struct struct_name {
type1 type_name_1;
type2 type_name_2;
type3 type_name_3;
}
예
struct Book {
string title;
string author;
uint book_id;
}
구조체 및 해당 변수에 액세스
구조체의 멤버에 액세스하려면 멤버 액세스 연산자 (.)를 사용합니다. 멤버 액세스 연산자는 구조 변수 이름과 액세스하려는 구조 멤버 사이의 마침표로 코딩됩니다. 구조체를 사용하여 구조체 유형의 변수를 정의합니다. 다음 예제는 프로그램에서 구조를 사용하는 방법을 보여줍니다.
예
Solidity에서 구조체가 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract test {
struct Book {
string title;
string author;
uint book_id;
}
Book book;
function setBook() public {
book = Book('Learn Java', 'TP', 1);
}
function getBookId() public view returns (uint) {
return book.book_id;
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
첫 번째 클릭 setBook 값을 LARGE로 설정하는 버튼을 클릭 한 다음 getBookId 선택한 도서 ID를 가져옵니다.
산출
uint256: 1
매핑은 배열 및 구조체와 같은 참조 유형입니다. 다음은 매핑 유형을 선언하는 구문입니다.
mapping(_KeyType => _ValueType)
어디
_KeyType− 모든 내장 유형과 바이트 및 문자열이 될 수 있습니다. 참조 유형이나 복잡한 개체는 허용되지 않습니다.
_ValueType − 모든 유형이 될 수 있습니다.
고려 사항
매핑은 다음 유형 만 가질 수 있습니다. storage 일반적으로 상태 변수에 사용됩니다.
매핑은 공개로 표시 할 수 있습니다. Solidity는 자동으로 getter를 생성합니다.
예
Solidity에서 매핑 유형이 작동하는 방식을 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract LedgerBalance {
mapping(address => uint) public balances;
function updateBalance(uint newBalance) public {
balances[msg.sender] = newBalance;
}
}
contract Updater {
function updateBalance() public returns (uint) {
LedgerBalance ledgerBalance = new LedgerBalance();
ledgerBalance.updateBalance(10);
return ledgerBalance.balances(address(this));
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
첫 번째 클릭 updateBalance 값을 10으로 설정하는 버튼은 다음과 같이 디코딩 된 출력을 표시하는 로그를 살펴 봅니다.
산출
{
"0": "uint256: 10"
}
견고성은 암시 적 변환과 명시 적 변환을 허용합니다. Solidity 컴파일러는 암시 적 변환이 가능하지 않고 정보 손실이없는 경우 두 데이터 유형 간의 암시 적 변환을 허용합니다. 예를 들어 uint8은 uint16으로 변환 가능하지만 int8은 uint256에서 허용되지 않는 음수 값을 포함 할 수 있으므로 int8은 uint256으로 변환 할 수 있습니다.
명시 적 변환
생성자 구문을 사용하여 데이터 유형을 다른 유형으로 명시 적으로 변환 할 수 있습니다.
int8 y = -3;
uint x = uint(y);
//Now x = 0xfffff..fd == two complement representation of -3 in 256 bit format.
더 작은 유형으로 변환하면 더 높은 순서의 비트가 필요합니다.
uint32 a = 0x12345678;
uint16 b = uint16(a); // b = 0x5678
더 높은 유형으로 변환하면 왼쪽에 패딩 비트가 추가됩니다.
uint16 a = 0x1234;
uint32 b = uint32(a); // b = 0x00001234
더 작은 바이트로 변환하면 더 많은 데이터가 필요합니다.
bytes2 a = 0x1234;
bytes1 b = bytes1(a); // b = 0x12
더 큰 바이트로 변환하면 오른쪽에 패딩 비트가 추가됩니다.
bytes2 a = 0x1234;
bytes4 b = bytes4(a); // b = 0x12340000
고정 크기 바이트와 int 간의 변환은 둘 다 동일한 크기 일 때만 가능합니다.
bytes2 a = 0x1234;
uint32 b = uint16(a); // b = 0x00001234
uint32 c = uint32(bytes4(a)); // c = 0x12340000
uint8 d = uint8(uint16(a)); // d = 0x34
uint8 e = uint8(bytes1(a)); // e = 0x12
잘림이 필요하지 않은 경우 16 진수를 모든 정수 유형에 할당 할 수 있습니다.
uint8 a = 12; // no error
uint32 b = 1234; // no error
uint16 c = 0x123456; // error, as truncation required to 0x3456
견고 함에서 우리는 wei, finney, szabo 또는 ether를 문자에 대한 접미사로 사용하여 다양한 에테르 기반 교단을 변환하는 데 사용할 수 있습니다. 가장 낮은 단위는 wei이고 1e12는 1 x 10 12를 나타냅니다 .
assert(1 wei == 1);
assert(1 szabo == 1e12);
assert(1 finney == 1e15);
assert(1 ether == 1e18);
assert(2 ether == 2000 fenny);
시간 단위
통화와 유사하게 Solidity에는 가장 낮은 단위가 초인 시간 단위가 있으며 시간을 나타내는 접미사로 초, 분, 시간, 일 및 주를 사용할 수 있습니다.
assert(1 seconds == 1);
assert(1 minutes == 60 seconds);
assert(1 hours == 60 minutes);
assert(1 day == 24 hours);
assert(1 week == 7 days);
특수 변수는 전역 적으로 사용 가능한 변수이며 블록 체인에 대한 정보를 제공합니다. 다음은 특수 변수 목록입니다.
Sr. 아니. | 특수 변수 및 설명 |
---|---|
1 | blockhash(uint blockNumber) returns (bytes32) 주어진 블록의 해시-현재 블록을 제외하고 가장 최근 256 개에 대해서만 작동합니다. |
2 | block.coinbase (address payable) 현재 블록 채굴 자의 주소. |
삼 | block.difficulty (uint) 현재 블록 난이도. |
4 | block.gaslimit (uint) 현재 블록 가스 제한. |
5 | block.number (uint) 현재 블록 번호. |
6 | block.timestamp 유닉스 시대 이후의 현재 블록 타임 스탬프 (초). |
7 | gasleft() returns (uint256) 남은 가스. |
8 | msg.data (bytes calldata) 완전한 통화 데이터. |
9 | msg.sender (address payable) 메시지 발신자 (현재 통화). |
10 | msg.sig (bytes4) calldata의 처음 4 바이트 (예 : 함수 식별자) |
11 | msg.value (uint) 메시지와 함께 보낸 wei의 수입니다. |
12 | now (uint) 현재 블록 타임 스탬프 (block.timestamp의 별칭). |
13 | tx.gasprice (uint) 거래의 가스 가격. |
14 | tx.origin (address payable) 트랜잭션 발신자 (전체 콜 체인). |
예
Solidity에서 보낸 사람 주소를 가져 오는 특수 변수 인 msg의 사용을 보려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract LedgerBalance {
mapping(address => uint) public balances;
function updateBalance(uint newBalance) public {
balances[msg.sender] = newBalance;
}
}
contract Updater {
function updateBalance() public returns (uint) {
LedgerBalance ledgerBalance = new LedgerBalance();
ledgerBalance.updateBalance(10);
return ledgerBalance.balances(address(this));
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
첫 번째 클릭 updateBalance 값을 10으로 설정하는 버튼은 다음과 같이 디코딩 된 출력을 표시하는 로그를 살펴 봅니다.
산출
{
"0": "uint256: 10"
}
스타일 가이드는 코드 레이아웃을 일관되게 유지하고 코드를 더 읽기 쉽게 만드는 데 도움이됩니다. 다음은 Solidity와 계약을 작성하는 동안 따르는 모범 사례입니다.
코드 레이아웃
Indentation− 들여 쓰기 수준을 유지하려면 탭 대신 4 개의 공백을 사용하십시오. 탭과 공백을 혼합하지 마십시오.
Two Blank Lines Rule − 두 계약 정의 사이에 빈 줄 2 개를 사용합니다.
pragma solidity ^0.5.0;
contract LedgerBalance {
//...
}
contract Updater {
//...
}
One Blank Line Rule− 두 기능 사이에 빈 줄 1 개를 사용합니다. 선언 만하는 경우 빈 줄이 필요하지 않습니다.
pragma solidity ^0.5.0;
contract A {
function balance() public pure;
function account() public pure;
}
contract B is A {
function balance() public pure {
// ...
}
function account() public pure {
// ...
}
}
Maximum Line Length − 독자가 코드를 쉽게 구문 분석 할 수 있도록 한 줄이 79자를 넘지 않아야합니다.
Wrapping rules− 첫 번째 인수는 여는 괄호없이 새 줄에 있습니다. 인수 당 단일 들여 쓰기를 사용하십시오. 종료 요소); 마지막이어야합니다.
function_with_a_long_name(
longArgument1,
longArgument2,
longArgument3
);
variable = function_with_a_long_name(
longArgument1,
longArgument2,
longArgument3
);
event multipleArguments(
address sender,
address recipient,
uint256 publicKey,
uint256 amount,
bytes32[] options
);
MultipleArguments(
sender,
recipient,
publicKey,
amount,
options
);
Source Code Encoding − UTF-8 또는 ASCII 인코딩을 사용하는 것이 좋습니다.
Imports − import 문은 pragma 선언 바로 뒤에 파일 상단에 위치해야합니다.
Order of Functions − 기능은 가시성에 따라 그룹화되어야합니다.
pragma solidity ^0.5.0;
contract A {
constructor() public {
// ...
}
function() external {
// ...
}
// External functions
// ...
// External view functions
// ...
// External pure functions
// ...
// Public functions
// ...
// Internal functions
// ...
// Private functions
// ...
}
Avoid extra whitespaces − 괄호, 대괄호 또는 중괄호 바로 안에 공백을 사용하지 마십시오.
Control structures− 중괄호는 선언과 같은 줄에 열어야합니다. 동일한 들여 쓰기를 유지하면서 자체 줄에서 닫습니다. 여는 중괄호가있는 공간을 사용하십시오.
pragma solidity ^0.5.0;
contract Coin {
struct Bank {
address owner;
uint balance;
}
}
if (x < 3) {
x += 1;
} else if (x > 7) {
x -= 1;
} else {
x = 5;
}
if (x < 3)
x += 1;
else
x -= 1;
Function Declaration− 중괄호에는 위의 규칙을 사용하십시오. 항상 가시성 레이블을 추가하십시오. 사용자 지정 수정 자 앞에 가시성 레이블이 먼저 와야합니다.
function kill() public onlyowner {
selfdestruct(owner);
}
Mappings − Avoid whitespaces while declaring mapping variables.
mapping(uint => uint) map;
mapping(address => bool) registeredAddresses;
mapping(uint => mapping(bool => Data[])) public data;
mapping(uint => mapping(uint => s)) data;
Variable declaration − Avoid whitespaces while declaring array variables.
uint[] x; // not unit [] x;
String declaration − Use double quotes to declare a string instead of single quote.
str = "foo";
str = "Hamlet says, 'To be or not to be...'";
Order of Layout
Elements should be layout in following order.
Pragma statements
Import statements
Interfaces
Libraries
Contracts
Within Interfaces, libraries or contracts the order should be as −
Type declarations
State variables
Events
Functions
Naming conventions
Contract and Library should be named using CapWords Style. For example, SmartContract, Owner etc.
Contract and Library name should match their file names.
In case of multiple contracts/libraries in a file, use name of core contract/library.
Owned.sol
pragma solidity ^0.5.0;
// Owned.sol
contract Owned {
address public owner;
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
//....
}
function transferOwnership(address newOwner) public onlyOwner {
//...
}
}
Congress.sol
pragma solidity ^0.5.0;
// Congress.sol
import "./Owned.sol";
contract Congress is Owned, TokenRecipient {
//...
}
구조체 이름
− SmartCoin과 같은 CapWords 스타일을 사용하십시오.이벤트 이름
− Deposit, AfterTransfer와 같은 CapWords 스타일을 사용하십시오.기능 명
− initializeSupply와 같은 mixedCase 스타일을 사용합니다.지역 및 상태 변수
− creatorAddress, supply와 같은 mixedCase 스타일을 사용합니다.상수
− MAX_BLOCKS와 같은 단어를 구분하려면 밑줄과 함께 모두 대문자를 사용하십시오.수정 자 이름
− onlyAfter와 같이 mixCase 스타일을 사용합니다.열거 형 이름
− TokenGroup과 같은 CapWords Style을 사용합니다.
함수는 프로그램의 어느 곳에서나 호출 할 수있는 재사용 가능한 코드 그룹입니다. 이렇게하면 동일한 코드를 반복해서 작성할 필요가 없습니다. 프로그래머가 모듈 식 코드를 작성하는 데 도움이됩니다. 함수를 사용하면 프로그래머가 큰 프로그램을 여러 개의 작고 관리 가능한 함수로 나눌 수 있습니다.
다른 고급 프로그래밍 언어와 마찬가지로 Solidity는 함수를 사용하여 모듈 식 코드를 작성하는 데 필요한 모든 기능을 지원합니다. 이 섹션에서는 Solidity에서 자신 만의 함수를 작성하는 방법을 설명합니다.
기능 정의
함수를 사용하기 전에 정의해야합니다. Solidity에서 함수를 정의하는 가장 일반적인 방법은function 키워드, 고유 한 함수 이름, 매개 변수 목록 (비어있을 수 있음) 및 중괄호로 둘러싸인 명령문 블록이 뒤 따릅니다.
통사론
기본 구문이 여기에 표시됩니다.
function function-name(parameter-list) scope returns() {
//statements
}
예
다음 예제를 시도하십시오. 매개 변수가없는 getResult라는 함수를 정의합니다.
pragma solidity ^0.5.0;
contract Test {
function getResult() public view returns(uint){
uint a = 1; // local variable
uint b = 2;
uint result = a + b;
return result;
}
}
함수 호출
나중에 계약의 어딘가에서 함수를 호출하려면 다음 코드에 표시된대로 해당 함수의 이름을 작성하기 만하면됩니다.
Solidity에서 문자열이 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract SolidityTest {
constructor() public{
}
function getResult() public view returns(string memory){
uint a = 1;
uint b = 2;
uint result = a + b;
return integerToString(result);
}
function integerToString(uint _i) internal pure
returns (string memory) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len - 1;
while (_i != 0) {
bstr[k--] = byte(uint8(48 + _i % 10));
_i /= 10;
}
return string(bstr);//access local variable
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: string: 3
기능 매개 변수
지금까지 매개 변수가없는 함수를 보았습니다. 그러나 함수를 호출하는 동안 다른 매개 변수를 전달하는 기능이 있습니다. 이러한 전달 된 매개 변수는 함수 내에서 캡처 할 수 있으며 이러한 매개 변수를 통해 모든 조작을 수행 할 수 있습니다. 함수는 쉼표로 구분 된 여러 매개 변수를 사용할 수 있습니다.
예
다음 예제를 시도하십시오. 우리는uint2str여기에 기능. 하나의 매개 변수가 필요합니다.
pragma solidity ^0.5.0;
contract SolidityTest {
constructor() public{
}
function getResult() public view returns(string memory){
uint a = 1;
uint b = 2;
uint result = a + b;
return integerToString(result);
}
function integerToString(uint _i) internal pure
returns (string memory) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len - 1;
while (_i != 0) {
bstr[k--] = byte(uint8(48 + _i % 10));
_i /= 10;
}
return string(bstr);//access local variable
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: string: 3
반환 진술
Solidity 함수는 옵션을 가질 수 있습니다. return성명서. 함수에서 값을 반환하려는 경우 필요합니다. 이 문은 함수의 마지막 문이어야합니다.
위의 예에서와 같이 uint2str 함수를 사용하여 문자열을 반환합니다.
Solidity에서 함수는 여러 값을 반환 할 수도 있습니다. 아래 예를 참조하십시오-
pragma solidity ^0.5.0;
contract Test {
function getResult() public view returns(uint product, uint sum){
uint a = 1; // local variable
uint b = 2;
product = a * b;
sum = a + b;
//alternative return statement to return
//multiple values
//return(a*b, a+b);
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: uint256: product 2
1: uint256: sum 3
함수 수정자는 함수의 동작을 수정하는 데 사용됩니다. 예를 들어 함수에 전제 조건을 추가합니다.
먼저 매개 변수가 있거나없는 수정자를 만듭니다.
contract Owner {
modifier onlyOwner {
require(msg.sender == owner);
_;
}
modifier costs(uint price) {
if (msg.value >= price) {
_;
}
}
}
특수 기호 "_;"가있는 곳에 함수 본문이 삽입됩니다. 수정 자 정의에 나타납니다. 따라서이 함수를 호출하는 동안 modifier의 조건을 만족하면 함수가 실행되고 그렇지 않으면 예외가 발생합니다.
아래 예를 참조하십시오-
pragma solidity ^0.5.0;
contract Owner {
address owner;
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
modifier costs(uint price) {
if (msg.value >= price) {
_;
}
}
}
contract Register is Owner {
mapping (address => bool) registeredAddresses;
uint price;
constructor(uint initialPrice) public { price = initialPrice; }
function register() public payable costs(price) {
registeredAddresses[msg.sender] = true;
}
function changePrice(uint _price) public onlyOwner {
price = _price;
}
}
보기 기능은 상태를 수정하지 않도록합니다. 함수는 다음과 같이 선언 할 수 있습니다.view. 함수에있는 경우 다음 문은 상태를 수정하는 것으로 간주되며 컴파일러는 이러한 경우 경고를 발생시킵니다.
상태 변수 수정.
이벤트 방출.
다른 계약 생성.
자기 파괴 사용.
통화를 통해 이더를 전송합니다.
보기 또는 순수로 표시되지 않은 함수를 호출합니다.
저수준 호출 사용.
특정 opcode를 포함하는 인라인 어셈블리 사용.
Getter 메서드는 기본적으로 뷰 함수입니다.
보기 기능을 사용하는 아래 예를 참조하십시오.
예
pragma solidity ^0.5.0;
contract Test {
function getResult() public view returns(uint product, uint sum){
uint a = 1; // local variable
uint b = 2;
product = a * b;
sum = a + b;
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: uint256: product 2
1: uint256: sum 3
순수 함수는 상태를 읽거나 수정하지 않도록합니다. 함수는 다음과 같이 선언 할 수 있습니다.pure. 함수에있는 경우 다음 문은 상태를 읽는 것으로 간주되며 컴파일러는 이러한 경우 경고를 발생시킵니다.
상태 변수 읽기.
address (this) .balance 또는 <address> .balance에 액세스합니다.
block, tx, msg (msg.sig 및 msg.data를 읽을 수 있음)의 특수 변수에 액세스합니다.
순수로 표시되지 않은 함수를 호출합니다.
특정 opcode를 포함하는 인라인 어셈블리 사용.
순수 함수는 revert () 및 require () 함수를 사용하여 오류가 발생하는 경우 잠재적 인 상태 변경을 되돌릴 수 있습니다.
보기 기능을 사용하는 아래 예를 참조하십시오.
예
pragma solidity ^0.5.0;
contract Test {
function getResult() public pure returns(uint product, uint sum){
uint a = 1;
uint b = 2;
product = a * b;
sum = a + b;
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: uint256: product 2
1: uint256: sum 3
대체 기능은 계약에 사용할 수있는 특수 기능입니다. 그것은 다음과 같은 특징이 있습니다-
계약에 존재하지 않는 함수가 호출 될 때 호출됩니다.
외부로 표시해야합니다.
이름이 없습니다.
인수가 없습니다
어떤 것도 반환 할 수 없습니다.
계약 당 하나씩 정의 할 수 있습니다.
지불 가능으로 표시되지 않은 경우 계약이 데이터없이 일반 에테르를 수신하면 예외가 발생합니다.
다음 예는 계약 별 대체 기능의 개념을 보여줍니다.
예
pragma solidity ^0.5.0;
contract Test {
uint public x ;
function() external { x = 1; }
}
contract Sink {
function() external payable { }
}
contract Caller {
function callTest(Test test) public returns (bool) {
(bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()"));
require(success);
// test.x is now 1
address payable testPayable = address(uint160(address(test)));
// Sending ether to Test contract,
// the transfer will fail, i.e. this returns false here.
return (testPayable.send(2 ether));
}
function callSink(Sink sink) public returns (bool) {
address payable sinkPayable = address(sink);
return (sinkPayable.send(2 ether));
}
}
동일한 범위에서 동일한 함수 이름에 대해 여러 정의를 가질 수 있습니다. 함수의 정의는 인수 목록의 인수 유형 및 / 또는 수에 따라 서로 달라야합니다. 반환 유형 만 다른 함수 선언을 오버로드 할 수 없습니다.
다음 예제는 Solidity에서 함수 오버로딩의 개념을 보여줍니다.
예
pragma solidity ^0.5.0;
contract Test {
function getSum(uint a, uint b) public pure returns(uint){
return a + b;
}
function getSum(uint a, uint b, uint c) public pure returns(uint){
return a + b + c;
}
function callSumWithTwoArguments() public pure returns(uint){
return getSum(1,2);
}
function callSumWithThreeArguments() public pure returns(uint){
return getSum(1,2,3);
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
callSumWithTwoArguments 버튼을 먼저 클릭 한 다음 callSumWithThreeArguments 버튼을 클릭하여 결과를 확인합니다.
산출
0: uint256: 3
0: uint256: 6
Solidity는 내장 된 수학 함수도 제공합니다. 다음은 많이 사용되는 방법입니다-
addmod(uint x, uint y, uint k) returns (uint)- 계산하여 (X + Y) % K 첨가가 임의의 정밀도로 수행되고, 2에서 랩 어라운드하지 않는 경우 (256) .
mulmod(uint x, uint y, uint k) returns (uint)- 계산하여 (X * Y)의 첨가가 임의의 정밀도로 수행되고, 2에서 랩 어라운드하지 않는 % K 여기서 256 .
다음 예제는 Solidity에서 수학 함수의 사용법을 보여줍니다.
예
pragma solidity ^0.5.0;
contract Test {
function callAddMod() public pure returns(uint){
return addmod(4, 5, 3);
}
function callMulMod() public pure returns(uint){
return mulmod(4, 5, 3);
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
먼저 callAddMod 버튼을 클릭 한 다음 callMulMod 버튼을 클릭하여 결과를 확인합니다.
산출
0: uint256: 0
0: uint256: 2
Solidity는 내장 된 암호화 기능도 제공합니다. 다음은 중요한 방법입니다-
keccak256(bytes memory) returns (bytes32) − 입력의 Keccak-256 해시를 계산합니다.
sha256(bytes memory) returns (bytes32) − 입력의 SHA-256 해시를 계산합니다.
ripemd160(bytes memory) returns (bytes20) − 입력의 RIPEMD-160 해시를 계산합니다.
sha256(bytes memory) returns (bytes32) − 입력의 SHA-256 해시를 계산합니다.
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)− 타원 곡선 서명에서 공개 키와 관련된 주소를 복구하거나 오류시 0을 반환합니다. 함수 매개 변수는 서명의 ECDSA 값에 해당합니다. r-서명의 처음 32 바이트; s : 서명의 두 번째 32 바이트; v : 서명의 마지막 1 바이트. 이 메서드는 주소를 반환합니다.
다음 예제는 Solidity에서 암호화 기능의 사용을 보여줍니다.
예
pragma solidity ^0.5.0;
contract Test {
function callKeccak256() public pure returns(bytes32 result){
return keccak256("ABC");
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: bytes32: result 0xe1629b9dda060bb30c7908346f6af189c16773fa148d3366701fbaa35d54f3c8
인출 패턴은 보안 위협이되는 직접 호 전환이 이루어지지 않도록합니다. 다음 계약은 이더를 보내기 위해 전송 호출의 안전하지 않은 사용을 보여줍니다.
pragma solidity ^0.5.0;
contract Test {
address payable public richest;
uint public mostSent;
constructor() public payable {
richest = msg.sender;
mostSent = msg.value;
}
function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
// Insecure practice
richest.transfer(msg.value);
richest = msg.sender;
mostSent = msg.value;
return true;
} else {
return false;
}
}
}
위의 계약은 가장 부자가 실패한 폴백 기능의 계약이되게하여 사용할 수없는 상태로 렌더링 될 수 있습니다. 폴백 함수가 실패하면 becomeRichest () 함수도 실패하고 계약이 영원히 멈 춥니 다. 이 문제를 완화하기 위해 인출 패턴을 사용할 수 있습니다.
인출 패턴에서는 각 이체 전에 미결제 금액을 재설정합니다. 호출자 계약 만 실패하도록합니다.
pragma solidity ^0.5.0;
contract Test {
address public richest;
uint public mostSent;
mapping (address => uint) pendingWithdrawals;
constructor() public payable {
richest = msg.sender;
mostSent = msg.value;
}
function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
pendingWithdrawals[richest] += msg.value;
richest = msg.sender;
mostSent = msg.value;
return true;
} else {
return false;
}
}
function withdraw() public {
uint amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
msg.sender.transfer(amount);
}
}
계약에 대한 제한된 액세스는 일반적인 관행입니다. 기본적으로 계약 상태는 공개로 지정되지 않는 한 읽기 전용입니다.
계약의 상태를 수정할 수있는 사람을 제한하거나 수정자를 사용하여 계약의 기능을 호출 할 수 있습니다. 아래에 설명 된대로 여러 수정자를 만들고 사용합니다.
onlyBy − 함수에서 사용하면 언급 된 호출자 만이 함수를 호출 할 수 있습니다.
onlyAfter − 함수에 한 번 사용하면 특정 시간 후에 해당 함수를 호출 할 수 있습니다.
costs − 함수에서 사용하면 특정 값이 제공되는 경우에만 호출자가이 함수를 호출 할 수 있습니다.
예
pragma solidity ^0.5.0;
contract Test {
address public owner = msg.sender;
uint public creationTime = now;
modifier onlyBy(address _account) {
require(
msg.sender == _account,
"Sender not authorized."
);
_;
}
function changeOwner(address _newOwner) public onlyBy(owner) {
owner = _newOwner;
}
modifier onlyAfter(uint _time) {
require(
now >= _time,
"Function called too early."
);
_;
}
function disown() public onlyBy(owner) onlyAfter(creationTime + 6 weeks) {
delete owner;
}
modifier costs(uint _amount) {
require(
msg.value >= _amount,
"Not enough Ether provided."
);
_;
if (msg.value > _amount)
msg.sender.transfer(msg.value - _amount);
}
function forceOwnerChange(address _newOwner) public payable costs(200 ether) {
owner = _newOwner;
if (uint(owner) & 0 == 1) return;
}
}
Solidity의 계약은 C ++의 클래스와 유사합니다. 계약에는 다음과 같은 속성이 있습니다.
Constructor − 컨트랙트 당 한 번 실행되며 컨트랙트 생성시 호출되는 생성자 키워드로 선언 된 특수 함수.
State Variables − 계약 상태를 저장하기위한 계약 당 변수.
Functions − 계약 상태를 변경하기 위해 상태 변수를 수정할 수있는 계약 별 기능.
가시성 한정자
다음은 계약의 기능 / 상태 변수에 대한 다양한 가시성 수량 자입니다.
external− 외부 기능은 다른 계약에 의해 호출됩니다. 내부 통화에는 사용할 수 없습니다. 계약 내에서 외부 함수를 호출하려면 this.function_name () 호출이 필요합니다. 상태 변수는 외부로 표시 할 수 없습니다.
public− 공용 기능 / 변수는 외부 및 내부에서 모두 사용할 수 있습니다. 공개 상태 변수의 경우 Solidity는 자동으로 getter 함수를 생성합니다.
internal − 내부 기능 / 변수는 내부적으로 또는 파생 된 계약에 의해서만 사용될 수 있습니다.
private − 개인 함수 / 변수는 내부적으로 만 사용할 수 있으며 파생 된 계약에서도 사용할 수 없습니다.
예
pragma solidity ^0.5.0;
contract C {
//private state variable
uint private data;
//public state variable
uint public info;
//constructor
constructor() public {
info = 10;
}
//private function
function increment(uint a) private pure returns(uint) { return a + 1; }
//public function
function updateData(uint a) public { data = a; }
function getData() public view returns(uint) { return data; }
function compute(uint a, uint b) internal pure returns (uint) { return a + b; }
}
//External Contract
contract D {
function readData() public returns(uint) {
C c = new C();
c.updateData(7);
return c.getData();
}
}
//Derived Contract
contract E is C {
uint private result;
C private c;
constructor() public {
c = new C();
}
function getComputedResult() public {
result = compute(3, 5);
}
function getResult() public view returns(uint) { return result; }
function getData() public view returns(uint) { return c.info(); }
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 . 다양한 방법의 계약을 실행합니다. E.getComputedResult () 다음에 E.getResult ()가 표시됩니다.
산출
0: uint256: 8
상속은 계약의 기능을 확장하는 방법입니다. Solidity는 단일 및 다중 상속을 모두 지원합니다. 다음은 주요 하이라이트입니다.
파생 계약은 내부 메서드 및 상태 변수를 포함하여 모든 비 개인 멤버에 액세스 할 수 있습니다. 그러나 이것을 사용하는 것은 허용되지 않습니다.
함수 서명이 동일하게 유지되는 경우 함수 재정의가 허용됩니다. 출력 매개 변수가 다른 경우 컴파일이 실패합니다.
super 키워드를 사용하거나 슈퍼 계약 이름을 사용하여 슈퍼 계약의 함수를 호출 할 수 있습니다.
다중 상속의 경우 super를 사용한 함수 호출은 대부분의 파생 계약을 우선합니다.
예
pragma solidity ^0.5.0;
contract C {
//private state variable
uint private data;
//public state variable
uint public info;
//constructor
constructor() public {
info = 10;
}
//private function
function increment(uint a) private pure returns(uint) { return a + 1; }
//public function
function updateData(uint a) public { data = a; }
function getData() public view returns(uint) { return data; }
function compute(uint a, uint b) internal pure returns (uint) { return a + b; }
}
//Derived Contract
contract E is C {
uint private result;
C private c;
constructor() public {
c = new C();
}
function getComputedResult() public {
result = compute(3, 5);
}
function getResult() public view returns(uint) { return result; }
function getData() public view returns(uint) { return c.info(); }
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 . 다양한 방법의 계약을 실행합니다. E.getComputedResult () 다음에 E.getResult ()가 표시됩니다.
산출
0: uint256: 8
생성자는 다음을 사용하여 선언 된 특수 함수입니다. constructor예어. 선택적 기능이며 계약의 상태 변수를 초기화하는 데 사용됩니다. 다음은 생성자의 주요 특성입니다.
계약에는 생성자가 하나만있을 수 있습니다.
컨트랙트가 생성 될 때 생성자 코드는 한 번 실행되며 컨트랙트 상태를 초기화하는 데 사용됩니다.
생성자 코드가 실행 된 후 최종 코드가 블록 체인에 배포됩니다. 이 코드에는 공용 함수와 공용 함수를 통해 도달 할 수있는 코드가 포함됩니다. 생성자 코드 또는 생성자 만 사용하는 내부 메서드는 최종 코드에 포함되지 않습니다.
생성자는 공용 또는 내부 일 수 있습니다.
내부 생성자는 계약을 추상으로 표시합니다.
생성자가 정의되지 않은 경우 계약에 기본 생성자가 있습니다.
pragma solidity ^0.5.0;
contract Test {
constructor() public {}
}
기본 계약에 인수가있는 생성자가있는 경우 각 파생 계약은 인수를 전달해야합니다.
기본 생성자는 다음 방법을 사용하여 직접 초기화 할 수 있습니다.
pragma solidity ^0.5.0;
contract Base {
uint data;
constructor(uint _data) public {
data = _data;
}
}
contract Derived is Base (5) {
constructor() public {}
}
기본 생성자는 다음과 같은 방법으로 간접적으로 초기화 될 수 있습니다.
pragma solidity ^0.5.0;
contract Base {
uint data;
constructor(uint _data) public {
data = _data;
}
}
contract Derived is Base {
constructor(uint _info) Base(_info * _info) public {}
}
기본 계약 생성자를 초기화하는 직접 및 간접 방법은 허용되지 않습니다.
파생 계약이 기본 계약 생성자에 인수를 전달하지 않으면 파생 계약이 추상이됩니다.
추상 계약은 구현없이 최소한 하나의 기능을 포함하는 계약입니다. 이러한 계약은 기본 계약으로 사용됩니다. 일반적으로 추상 계약에는 구현 된 기능과 추상적 인 기능이 모두 포함됩니다. 파생 된 계약은 추상 기능을 구현하고 필요한 경우 기존 기능을 사용합니다.
파생 계약이 추상 기능을 구현하지 않는 경우이 파생 계약은 추상으로 표시됩니다.
예
Solidity에서 추상 계약이 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract Calculator {
function getResult() public view returns(uint);
}
contract Test is Calculator {
function getResult() public view returns(uint) {
uint a = 1;
uint b = 2;
uint result = a + b;
return result;
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
산출
0: uint256: 3
인터페이스는 추상 계약과 유사하며 다음을 사용하여 생성됩니다. interface예어. 다음은 인터페이스의 주요 특징입니다.
인터페이스는 구현과 함께 어떤 기능도 가질 수 없습니다.
인터페이스의 기능은 외부 유형 만 가능합니다.
인터페이스는 생성자를 가질 수 없습니다.
인터페이스는 상태 변수를 가질 수 없습니다.
인터페이스는 인터페이스 이름 점 표기법을 사용하여 액세스 할 수있는 열거 형 구조체를 가질 수 있습니다.
예
Solidity에서 인터페이스가 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
interface Calculator {
function getResult() external view returns(uint);
}
contract Test is Calculator {
constructor() public {}
function getResult() external view returns(uint){
uint a = 1;
uint b = 2;
uint result = a + b;
return result;
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
Note − 배포 버튼을 클릭하기 전에 드롭 다운에서 테스트를 선택합니다.
산출
0: uint256: 3
라이브러리는 계약과 유사하지만 주로 재사용을 목적으로합니다. 라이브러리에는 다른 계약에서 호출 할 수있는 함수가 포함되어 있습니다. Solidity에는 라이브러리 사용에 대한 특정 제한이 있습니다. 다음은 Solidity Library의 주요 특징입니다.
라이브러리 함수는 상태를 수정하지 않으면 직접 호출 할 수 있습니다. 즉, pure 또는 view 함수는 라이브러리 외부에서만 호출 할 수 있습니다.
라이브러리는 상태 비 저장으로 간주되므로 삭제할 수 없습니다.
라이브러리는 상태 변수를 가질 수 없습니다.
라이브러리는 어떤 요소도 상속 할 수 없습니다.
라이브러리는 상속 될 수 없습니다.
예
Solidity에서 라이브러리가 작동하는 방식을 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
library Search {
function indexOf(uint[] storage self, uint value) public view returns (uint) {
for (uint i = 0; i < self.length; i++) if (self[i] == value) return i;
return uint(-1);
}
}
contract Test {
uint[] data;
constructor() public {
data.push(1);
data.push(2);
data.push(3);
data.push(4);
data.push(5);
}
function isValuePresent() external view returns(uint){
uint value = 4;
//search if value is present in the array using Library function
uint index = Search.indexOf(data, value);
return index;
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
Note − 배포 버튼을 클릭하기 전에 드롭 다운에서 테스트를 선택합니다.
산출
0: uint256: 3
사용
지침 using A for B; 라이브러리 A의 라이브러리 함수를 지정된 유형 B에 연결하는 데 사용할 수 있습니다. 이러한 함수는 호출자 유형을 첫 번째 매개 변수로 사용합니다 (self를 사용하여 식별 됨).
예
Solidity에서 라이브러리가 작동하는 방식을 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
library Search {
function indexOf(uint[] storage self, uint value) public view returns (uint) {
for (uint i = 0; i < self.length; i++)if (self[i] == value) return i;
return uint(-1);
}
}
contract Test {
using Search for uint[];
uint[] data;
constructor() public {
data.push(1);
data.push(2);
data.push(3);
data.push(4);
data.push(5);
}
function isValuePresent() external view returns(uint){
uint value = 4;
//Now data is representing the Library
uint index = data.indexOf(value);
return index;
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
Note − 배포 버튼을 클릭하기 전에 드롭 다운에서 테스트를 선택합니다.
산출
0: uint256: 3
Solidity는 Solidity 소스 코드 내에서 인라인 어셈블리를 작성하기 위해 어셈블리 언어를 사용하는 옵션을 제공합니다. 또한 독립형 어셈블리 코드를 작성하여 바이트 코드로 변환 할 수도 있습니다. Standalone Assembly는 Solidity 컴파일러의 중간 언어이며 Solidity 코드를 Standalone Assembly로 변환 한 다음 바이트 코드로 변환합니다. 인라인 어셈블리에서 사용되는 것과 동일한 언어를 사용하여 독립 실행 형 어셈블리에서 코드를 작성할 수 있습니다.
인라인 어셈블리
인라인 어셈블리 코드는 Solidity 코드베이스 내에서 인터리브되어 EVM을보다 세밀하게 제어 할 수 있으며 특히 라이브러리 함수를 작성하는 동안 사용됩니다.
어셈블리 코드는 assembly { ... } 블록.
예
Solidity에서 라이브러리가 작동하는 방식을 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
library Sum {
function sumUsingInlineAssembly(uint[] memory _data) public pure returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i) {
assembly {
o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
}
}
}
}
contract Test {
uint[] data;
constructor() public {
data.push(1);
data.push(2);
data.push(3);
data.push(4);
data.push(5);
}
function sum() external view returns(uint){
return Sum.sumUsingInlineAssembly(data);
}
}
Solidity First Application 장에 제공된 단계를 사용하여 위 프로그램을 실행하십시오 .
Note − 배포 버튼을 클릭하기 전에 드롭 다운에서 테스트를 선택합니다.
산출
0: uint256: 15
이벤트는 계약의 상속 가능한 구성원입니다. 이벤트가 발생하면 트랜잭션 로그에 전달 된 인수가 저장됩니다. 이러한 로그는 블록 체인에 저장되며 계약이 블록 체인에 존재할 때까지 계약 주소를 사용하여 액세스 할 수 있습니다. 생성 된 이벤트는 계약 내에서 액세스 할 수 없으며이를 생성하고 생성 한 이벤트도 액세스 할 수 없습니다.
이벤트 키워드를 사용하여 이벤트를 선언 할 수 있습니다.
//Declare an Event
event Deposit(address indexed _from, bytes32 indexed _id, uint _value);
//Emit an event
emit Deposit(msg.sender, _id, msg.value);
예
Solidity에서 이벤트가 작동하는 방식을 이해하려면 다음 코드를 시도하십시오.
먼저 계약을 작성하고 이벤트를 내 보냅니다.
pragma solidity ^0.5.0;
contract Test {
event Deposit(address indexed _from, bytes32 indexed _id, uint _value);
function deposit(bytes32 _id) public payable {
emit Deposit(msg.sender, _id, msg.value);
}
}
그런 다음 JavaScript 코드에서 계약의 이벤트에 액세스하십시오.
var abi = /* abi as generated using compiler */;
var ClientReceipt = web3.eth.contract(abi);
var clientReceiptContract = ClientReceipt.at("0x1234...ab67" /* address */);
var event = clientReceiptContract.Deposit(function(error, result) {
if (!error)console.log(result);
});
다음과 유사한 세부 정보를 인쇄해야합니다.
산출
{
"returnValues": {
"_from": "0x1111...FFFFCCCC",
"_id": "0x50...sd5adb20",
"_value": "0x420042"
},
"raw": {
"data": "0x7f...91385",
"topics": ["0xfd4...b4ead7", "0x7f...1a91385"]
}
}
Solidity는 오류 처리를위한 다양한 기능을 제공합니다. 일반적으로 오류가 발생하면 상태가 원래 상태로 되돌아갑니다. 다른 검사는 무단 코드 액세스를 방지하는 것입니다. 다음은 오류 처리에 사용되는 몇 가지 중요한 방법입니다.
assert(bool condition)− 조건이 충족되지 않는 경우이 메서드 호출은 유효하지 않은 opcode를 유발하고 상태에 대한 변경 사항이 되돌려집니다. 이 방법은 내부 오류에 사용됩니다.
require(bool condition)− 조건이 충족되지 않을 경우이 메서드 호출은 원래 상태로 되돌아갑니다. -이 방법은 입력 또는 외부 구성 요소의 오류에 사용됩니다.
require(bool condition, string memory message)− 조건이 충족되지 않을 경우이 메서드 호출은 원래 상태로 되돌아갑니다. -이 방법은 입력 또는 외부 구성 요소의 오류에 사용됩니다. 사용자 지정 메시지를 제공하는 옵션을 제공합니다.
revert() −이 방법은 실행을 중단하고 상태에 대한 변경 사항을 되돌립니다.
revert(string memory reason)−이 방법은 실행을 중단하고 상태에 대한 변경 사항을 되돌립니다. 사용자 지정 메시지를 제공하는 옵션을 제공합니다.
예
Solidity에서 오류 처리가 어떻게 작동하는지 이해하려면 다음 코드를 시도하십시오.
pragma solidity ^0.5.0;
contract Vendor {
address public seller;
modifier onlySeller() {
require(
msg.sender == seller,
"Only seller can call this."
);
_;
}
function sell(uint amount) public payable onlySeller {
if (amount > msg.value / 2 ether)
revert("Not enough Ether provided.");
// Perform the sell operation.
}
}
revert가 호출되면 다음과 같이 16 진수 데이터를 반환합니다.
산출
0x08c379a0 // Function selector for Error(string)
0x0000000000000000000000000000000000000000000000000000000000000020 // Data offset
0x000000000000000000000000000000000000000000000000000000000000001a // String length
0x4e6f7420656e6f7567682045746865722070726f76696465642e000000000000 // String data