안녕하세요. 스크립토 6기 이희제입니다.
이번 시간에는 이더리움 기반으로 개발하기 위해서 필수적인 스마트 컨트랙트와 솔리디티에 대해서 알아보겠습니다.
이더리움에는 외부 소유 계정(EOA)과 컨트랙트 계정 이렇게 두 가지 유형의 계정이 있습니다.
컨트랙트 계정은 이더리움 가상 머신에 의해 실행되는 프로그램 코드가 제어합니다. 즉 관련 코드와 데이터 저장소를 모두 가지고 있습니다.
➡️ **스마트 컨트랙트(smart contract)**의 정의는 다음과 같습니다.
스마트 컨트랙트는 단순히 컴퓨터 프로그램입니다.
스마트 컨트랙트 코드는 일단 배포되면, 변경할 수 없습니다. 스마트 컨트랙트를 수정하기 유해서는 무조건 새로운 인스터스를 배포해야 합니다.
스마트 컨트랙트를 실행한 결과물은 그것을 실행한 모든이에게 동일합니다. 이는 실행을 시작한 트랜잭션의 컨텍스트와 실행 시점에 이더리움 블록체인의 상태가 동일하다는 전제가 있기 때문입니다.
스마트 컨트랙트는 매우 제한적인 실행 컨텍스트에서 작동됩니다. 이들은 자신의 상태, 호출한 트랜잭션의 컨텍스트 및 가장 최근 블록의 일부 정보에 접근할 수 있습니다.
EVM의 모든 인스터스는 동일한 초기 상태에서 작동하고 동일한 최종 상태를 생성하기 때문에 시스템 전체가 단일 월드 컴퓨터로 작동합니다.
✅ 스미트 컨트랙트는 보통 솔디디티와 같은 고급 언어로 작성됩니다. 컨트랙트를 실행하기 위해서는 EVM에서 실행되는 바이트코드로 컴파일되어야 합니다.
[바이트코드 예시]
컨트랙트가 컴파일되면 고유한 컨트랙트 생성 트랜잭션을 사용하여 이더리움 플랫폼에 배포되면, 이 트랜잭션은 고유한 컨트랙트 생성 주소(0x0)으로 전송됩니다.
컨트랙트는 이더리움 주소로 식별되고, 이 주소는 원래 계정 및 논스의 함수로 컨트랙트 생성 트랜잭션에서 파생됩니다.
컨트랙트의 이더리움 주소는 트랜잭션에서 수신자로 사용되거나 컨트랙트에 자금을 보내거나 컨트랙트 함수를 호출하는 데 사용할 수 있습니다.
💡** 컨트랙트는 트랜잭션에 의해 호출된 경우에만 실행되는 것이 중요합니다!
**
이더리움의 모든 스마트 컨트랙트는 EOA에서 시작된 트랜잭션으로 인해 실행됩니다.
컨트랙트는 다른 컨트랙트를 호출할 수 있고 그 컨트랙트는 또 다른 컨트랙트를 호출할 수 있지만, 이 체인에서 첫 번째 컨트랙트 실행은 항상 EOA로부터 트랜잭션이 호출됩니다.
💡 트랜잭션은 원자성(atomic)의 특징을 지닙니다.
트랜잭션은 모든 실행이 성공적으로 종료된 경우에만 글로벌 상태(컨트랙트, 계정 등)의 모든 변경사항이 기록되고 전체가 실행됩니다.
오류로 인해 실행이 실패하면 모든 영향은 트랜잭션이 실행되지 않은 것처럼 '롤백(rollback)'됩니다.
실패한 트랜잭션은 여전히 시도된 것으로 기록되며, 실행을 위해 가스로 소비된 이더는 원 계정에서 차감되지만, 컨트랙트 또는 계좌 상태에는 영향을 미치지 않는다.
[실패 예시]
$ sudo add-apt-repository ppa:ethereum/ethereum
$ sudo apt update
$ sudo apt install solc
$ brew update
$ brew upgrade
$ brew tap ethereum/ethereum
$ brew install solidity
➡️ 솔리디티를 설치를 했으니 간단하게 솔리디티 프로그램을 작성해 봅니다.
solc
의 인수 --bin
, --optimize
를 이용하여 예저 컨트랙트의 최적화된 바이너리를 생성합니다.➡️ solc
가 생성하는 결과는 이더리움 블록체인에서 실행될 수 있는 시리얼라이즈된 16진수 바이너리입니다.
✅ 컴퓨터 소트프웨어에서 **애플리케이션 바이너리 인터페이스(ABI)**는 두 프로그램 모듈 간 또는 운영체제와 사용자 프로그램 간의 인터페이스입니다.
컨트랙트의 ABI는 함수 설명 및 이벤트의 json 배열로 지정됩니다.
--abi
옵션을 이용해 컨트랙트의 ABI를 아래와 같이 생성했습니다.
➡️ 결과값을 보면 fauset.sol에서 정의된 함수를 설명하는 json 배열인 것을 확인할 수 있습니다.
애플리케이션이 컨트랙트와 상호작용하는 데 필요한 것은 ABI와 컨트랙트가 배포된 주소입니다.
✅ 솔리디티에 대해서 기본적인 것에 알아보겠습니다.
➡️ 솔리디티에서 제공되는 기본 데이터 타입을 살펴보겠습니다.
1. bool
(u)fixedMxN
으로 선언된 고정소수점 숫자. 여기서 M은 비트 단위의 크기이고, N은 소수점 이하 자릿수이다.enum NAME {HEEJE 1, HEEJE 2, ...}
struct Peson {
uint age;
uint birthday;
}
mapping(KEY_TYPE => VALUE_TYPE) NAME
require(amount <= 100000000000000000);
변경 후 :require(amount <= 0.1 ether);
➡️ msg 객체는 이 컨트랙트 실행을 시작한 트랜잭션 호출(EOA) 또는 메시지 호출(컨트랙트 발신)입니다.
1. msg.sender
➡️ tx 객체는 트랜잭션 관련 정보에 접근하는 방법을 제공합니다.
1. tx.gasprice
➡️ block 객체에는 현재 블록에 대한 정보가 포함되어 있습니다.
1. blockhash(uint blockNumber) returns (bytes32)
아래와 같이 address 는 여러가지 객체를 가지고 있습니다.
address.balance, address.transfer(amount), address.send(amount), address.call(payload), address.callcode(payload), address.delegatecall()
자세한 설명: https://docs.soliditylang.org/en/v0.8.0/units-and-global-variables.html?highlight=msg.gas#block-and-transaction-properties
1. addmod, mulmod
7장은 양이 많은 관계로 2개의 파트로 나눠서 글을 올리려고 합니다.
다음 글에 이어서 솔리디틴의 함수부터 시작하도록 하겠습니다. 👍🏻
정리깔끔해서 좋아요👍