솔리디티는 객체지향 프로그래밍 언어입니다.
솔리디티는 이더리움 플랫폼 위에서 스마트 컨트랙트를 작성할 때 사용합니다.
1. 정적 타입(static-typed)의 중괄호(curly-braces) 언어 : 자바스크립트와 달리 컴파일시에 변수 타입이 결정되는 언어다. 소스코드에 타입을 명확히해야한다.
2. 튜링완전언어 : 이더리움은 Gas를 통한 과금 메커니즘을 도입해서 블록체인에서 튜링완전언어를 가능하게 했고 반복문등의 작업이 가능하다.
3. 컴파일 언어 : 솔리디티로 작성한 스마트 컨트랙트는 EVM에서 동작하기 위해 바이트코드(Bytecode)로 컴파일된다.
저작권 문제를 해소하기 위해 SPDX 라이센스를 명시 -> 링크
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: GPL-3.0
pragma 키워드는 특정 컴파일러의 버전을 표기할 때 사용한다.
다음과 같이 코드 최상단에 작성한다.
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.14; // 0.8.14 버전을 사용합니다
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.14; // 0.8.14 이상의 버전을 사용합니다
//다음과 같은 방법으로 많이 사용하는 것 같다.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0; // 0.4.0 이상 0.9.0 미만의 버전을 사용합니다
솔리디티에서 Contract는 데이터와 코드의 모음이다
contract CallerContract is Ownable {
// 1. Declare ethPrice
// 변수 선언
EthPriceOracleInterface private oracleInstance;
address private oracleAddress;
mapping(uint256=>bool) myRequests;
event newOracleAddressEvent(address oracleAddress);
event ReceivedNewRequestIdEvent(uint256 id);
// 2. Declare PriceUpdatedEvent
//함수 선언
function setOracleInstanceAddress (address _oracleInstanceAddress) public onlyOwner {
oracleAddress = _oracleInstanceAddress;
oracleInstance = EthPriceOracleInterface(oracleAddress);
emit newOracleAddressEvent(oracleAddress);
}
function updateEthPrice() public {
uint256 id = oracleInstance.getLatestEthPrice();
myRequests[id] = true;
emit ReceivedNewRequestIdEvent(id);
}
function callback(uint256 _ethPrice, uint256 _id) public {
// 3. Continue here
}
}
javascript와 import 하는 방식은 비슷하며 다음과 같이 파일 경로를 코드 최상단에 보여주면서 import 하면된다.
import "./EthPriceOracleInterface.sol";
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
단일라인은 //
여러 주석처리는 /* */
// 단일 주석 처리
/*
여러 줄 주석 처리
function updateEthPrice() public {
uint256 id = oracleInstance.getLatestEthPrice();
myRequests[id] = true;
emit ReceivedNewRequestIdEvent(id);
}
*/
일반 프로그래밍 언어 : 스택, 힙, 메모리에 저장됨
솔리디티 언어 : 메모리, 스토리지, 콜데이터에 저장됨
데이터 저장위치 각각의 특징
스토리지 (Storage) : 영속적으로 읽기/쓰기 가능, 키(key)-값(value) 쌍으로 이루어진 매핑 구조, 각 키와 값은 32바이트 크기를 가짐, 함수 외부에 정의된 변수(상태변수), 함수와 같은 스마트 컨트랙트의 주요정보가 영속히 저장되서 가스비용이 비쌈
메모리(Memory) : 휘발적으로 읽기/쓰기 가능, 메모리에는 함수나 반복이 실행될 때 매개변수나 반환값, 함수 내부변수 같은 데이터가 잠시 저장되었다가 실행이 완료되면 삭제
콜데이터(Calldata) : 휘발적이지만 읽기만 가능한 공간 / 메모리와 달리 데이터 저장은 불가능함 / 주로 external이 적용된 함수의 매개변수에 콜데이터 공간을 사용함
기본 데이터 위치
함수, 반복문 매개변수(반환 값 포함) : 메모리
모든 지역 변수 : 스토리지
강제 데이터 위치
외부(external)함수의 매개 변수 (반환 값 미포함) : calldata
상태 변수 : 스토리지
다음 코드를 예시로 보면 된다.
pragma solidity ^0.8.7;
contract Example {
//storage에 변수를 저장하는 예시
//함수 외부에 선언된 상태변수라 storage에 저장됨
//public을 사용해서 외부에 선언된 것으로 봐야함
uint public a = 3;
struct Item{
uint price;
uint units;
}
Item[] public items;
function myFunc1() external view returns(uint, uint){
uint b = 4;
return (a,b);
}
function myFunc2(uint _itemIdx) public returns (uint){
Item storage item = items[_itemIdx];
return item.units;
}
//memory에 변수를 저장하는 예시
//함수 등 매개변수가 있기 때문에 메모리에 저장
function myFunc3(string memory str) public pure returns(uint, string memory, bytes memory){
uint num = 99;
bytes memory byt = hex"01";
return (num, str, byt);
}
// calldata에 변수를 저장하는 예시
// external을 사용하기 때문에 calldata에 저장됨
function myFunc4(string calldata str) external pure returns(string memory){
return str;
}
}
함수 외부에 선언되는 변수
스토리지에 저장되서 영속적인 속성을 가짐
1. internal (default) :
2. public
3. private :
참고링크 :
https://programtheblockchain.com/posts/2018/01/02/making-smart-contracts-with-public-variables/
https://docs.soliditylang.org/en/develop/contracts.html#visibility-and-getters
constant : 컴파일 시에 고정되야함
immutable: 선언한 뒤 생성자에서도 할당 할 수 있음
다음 예제코드를 통해 사용방법을 알 수 있습니다.
pragma solidity ^0.8.7;
uint constant bigNum = 32**22 + 8;
contract Example {
//constant는 선언 및 초기화를 해주어야 함
string constant str = "hello";
bytes32 constant hash = keccak256("hello");
//immutable은 선언해두었다. constructor에서 값을 할당할 수 있음
address immutable owner = msg.sender ;
uint immutable decimals;
uint immutable maxBalance;
constructor(uint decimals_, address ref){
decimals = decimals_;
maxBalance = ref.balance;
}
function isBalanceTooHigh(address other) public view returns (bool){
return other.balance > maxBalance;
}
}
지역변수는 함수가 실행될 때까지만 존재하는 변수
지역변수는 동적크기를 갖는 참조형 변수가 아니면 기본적으로 메모리에 저장
동적인 크기의 구조체나 배열 형식의 참조형 변수는 기본적으로 스토리지에 저장
다음 코드예제를 통해 사용방법을 참고하세요
pragma solidity ^0.8.14;
contract SimpleStorage{
//동적 크기의 배열 상태변수 선언
uint256[] stateArray;
function doStuff() public {
//솔리디티는 아래와 같은 지역변수는 자동으로 storage reference로 생성합니다.
//이것은 다음과 같이 명시한 것과 같습니다. uint256[] storage localReference = stateArray
uint256[] localReference = stateArray;
uint256[] memory memArray = new uint256[](5);
}
function simpleFunction() public pure returns(uint){
uint a; //지역변수 선언
uint b = 1; //지역변수 선언 및 초기화
a = 1;
uint result = a + b;
return result ;
}
}
블록체인의 여러 정보를 나타내는 변수로 전역 이름 공간(global name space)에 존재
글로벌한 블록체인에 있는 특수변수임
blockhash(uint blockNumber) | bytes32 | 주어진 블록의 해시를 반한. bytes32 형식. |
block.basefee | uint | 현재 블록의 기본 수수료. uint 형식. |
block.chainid | uint | 현재 블록의 체인 ID. uint 형식. |
block.coinbase | address payable | 현재 블록의 채굴자 주소. address 형식. |
block.difficulty | uint | 현재 블록의 난이도. utint 형식. |
block.gaslimit | uint | 현재 블록의 가스 한도. uint 형식. |
block.number | uint | 현재 블록의 번호. uint 형식. |
block.timestamp | uint | 현재 블록의 유닉스 타임스탬프. uint 형식. |
gasleft() | uint256 | 남아있는 가스의 양을 반환. uint256 형식. |
msg.data | bytes calldata | 전체 콜데이터 본문. bytes 형식. |
msg.sender | address | 현재 호출을 수행하고 있는 메시지 발신자. address 형식. |
msg.sig | bytes4 | 호출 데이터의 첫 4바이트(함수 식별자). bytes4 형식. |
msg.value | uint | 메시지와 함께 보낸 이더(Wei) 금액. uint 형식. |
tx.gasprice | uint | 트랜잭션 가스 비용. uint 형식. |
tx.origin | address | 트랜잭션 발신자. address 형식. |
ERC-20 토큰(나만의 토큰 만들기 실습) (0) | 2023.02.13 |
---|---|
우분투에 솔리디티 컴파일러 설치 (0) | 2023.02.07 |
Solidity - Calling Other Contract (0) | 2023.01.25 |
Solidity - Function Selector (0) | 2023.01.19 |
Solidity - Delegatecall (0) | 2023.01.18 |