SlideShare a Scribd company logo
1 of 56
Download to read offline
박일환
목차
 스마트 컨트랙트의 개념
 Metamask와 Testnet을 활용한 스마트 컨트랙트 배포
 ERC20 토큰 개발
 Solidity 개발환경 및 디버깅 방법
 Solidity 문법
스마트 컨트랙트
 스마트 컨트랙트는 특정 계약을 스스로 수립, 검증, 이행하기 위한 컴퓨터 프로토콜
 1996년 닉 자보( Nick Szabo : 컴퓨터과학자, 법학자, 암호학자)에 의해서 개념이 정립
 “a set of promises, specified in digital form, including protocols within which the parties
perform on these promises.”
 조건이 충족되면 사람의 개입 없이 자동으로 실행되는 ‘자동화된 거래규약’
 이더리움에서 스마트 컨트랙트는 이더리움의 상태를 변경할수 있는 프로그램 코드로서 블록
에 포함되어 각 노드에 전파되고, EVM에서 작동되어 상태전이를 발생
 블록헤더의 데이타뿐만 아니라 특정 값이나 발신자 및 수신되는 메시지의 데이타를 조작하는
등 이더리움의 상태변화와 데이타 저장등이 가능한 프로그램 코드
 새로운 스마트 컨트랙트를 생성하거나, 특정 스마트 컨트랙트상의 함수를 실행하거나, 이더
를 전송하는 방식중의 하나로 실행
 사용자 어카운트(EOA)에 의해서 발생한 트랜잭션이나 다른 컨트랙트에 의해서만 실행
 스마트 컨트랙트간의 호출은 메시지라는 특별한 구조체를 사용하여 호출
스마트 컨트랙트의 실행과정
EVM(Ethereum Virtual Machine) 구조
 비휘발성 (non-volatile)
 storage : 상태(state)가 저장
 code : 스마트 컨트랙트의 컴파일된 바이트 코드가 저장
 volatile (휘발성)
 stack : OP 코드를 실행하기위한 스택영역
 args : 컨트랙트 호출시에 넘어오는 인자를 저장
 memory : word 단위로 아이템을 저장하는 바이트 배열
EVM(Ethereum Virtual Machine) 특징
 임시저장소와 영구저장소를 구분하여, 임시저장소에 저장한 값은 해당 인스턴스에서만 유효
하고, 영구저장소에 저장한 값은 해당 컨트랙트 전체에 유효
 EVM에서 바이트 코드를 실행하기 위해서는 다음의 3가지 요소가 필요
 컨테이너에 값을 Push, Pop하기 위한 스택
 바이트 배열을 담을수 있는 메모리
 영속적으로 값을 저장하기 위한 저장소. 현재 저장소로는 레벨DB를 사용
 4,8바이트 워드단위는 크기가 너무작아, 32바이트 워드 단위를 지원
 32바이트 워드크기 등 이더리움에서 요구하는 VM기능과 명세를 지원하기 위해 단순화된
자체 VM을 개발
 메모리 크기가 가변적이고 스택의 크기에 제한이 없음
 반복호출횟수를 1024로 제한
EVM OP코드
[OPCODE 표]
0s: Stop and Arithmetic Operations
10s: Comparison & Bitwise Logic Operations
20s: SHA3
30s: Environmental Information
40s: Block Information
50s: Stack, Memory, Storage and Flow Operations
60s & 70s: Push Operations
80s: Duplication Operations
90s: Exchange Operations
a0s: Logging Operations
[OPCODE 분류표]
EVM OP코드와 동작원리
 “1+2” 계산 OPCODE 실행
First Smart Contract in Remix
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public constant returns (uint) {
return storedData;
}
}
https://solidity.readthedocs.io
Metamask를 사용하여 Contract 배포
Metamask를 사용하여 Contract 배포
Smart Contract의 함수 호출
함수 호출시 InputData
 4바이트의 Function Selector + 32바이트*n 의 함수 arguments
 Function Selector = keccak256(function prototype) 의 앞 4바이트
 Function name
 Parameters
 Return Type은 Function selector에 사용되지않음
최소요건을 갖춘 토큰
pragma solidity ^0.4.16;
contract MinimumViableToken {
mapping (address => uint256) public balanceOf;
function MinimumViableToken(uint256 initialSupply) public {
balanceOf[msg.sender] = initialSupply;
}
function transfer(address _to, uint256 _value) public {
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
}
}
최소요건을 갖춘 토큰
ERC20 Token
// Balances for each account
mapping(address => uint256) balances;
// Owner of account approves the transfer of an amount to another account
mapping(address => mapping (address => uint256)) allowed;
// 현재까지 공급된 토큰수
function totalSupply() constant returns (uint256 supply) {}
// _owner가 보유한 토큰잔액을 반환
function balanceOf(address _owner) constant returns (uint256 balance) {}
// 수신자(_to) 로 해당금액(_value)를 송금. 송금이 성공하면 TRUE를 반환하고, 실패하면 FALSE를 반환.
function transfer(address _to, uint256 _value) returns (bool success) {}
// 송신자(_from)주소에서 수신자(_to) 주소로 해당금액(_value)을 송금. 송금이 성공하면 TRUE,
// 실패하면 FALSE를 반환. transferFrom이 성공하려면 먼저 approve 인터페이스를 사용하여
// 일정금액을 인출할수 있도록 허락하여야 함.
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
// 송신자(msg.sender)가 보유한 토큰에서 일정금액(_value)만큼의 토큰을 인출할수 있는 권한을
// 수신자(_spender)에게 부여.
function approve(address _spender, uint256 _value) returns (bool success) {}
// 토큰 소유자(_owner)가 토큰 수신자(_spender)에게 인출을 허락한 토큰이 얼마인지를 반환.
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
https://theethereum.wiki/w/index.php/ERC20_Token_Standard
Debugging Smart Contract in Remix
EVM Execution Structure
Program Counter
- 다음 차례에 실행할 EVM 명령어의 위치
Program
- EVM이 실행할 스마트 컨트랙트의 EVM 명령어 목록을 보관
Stack
- 연산에 필요한 데이타를 저장하는 공간.
- 32바이트 크기의 값들이 저장되며, 최대 1024개가 저장.
Storage
- 블록체인에 영구적으로 기록하기 위한 저장공간.
- 키/값을 매핑하기위한 구조이며, 256비트 크기를 사용.
Memory
- 함수를 호출하거나 메모리 연산을 수행할때 임시로 사용되는 공간.
- 데이타를 읽을때는 256비트 단위, 쓸때는 8비트단위나 256비트 단위로도 가능.
Log
- 스마트 컨트랙트가 실행될때 부가적인 정보를 저장하기 위한 공간.
Call Data
- 이더리움에 트랜잭션을 요청했을때 전송되는 데이타들이 저장되는 공간.
Debugging Smart Contract in Remix
pragma solidity ^0.4.0;
contract Debugging {
uint[] private vars;
function assignment() {
uint myVal1 = 1;
uint myVal2 = 2;
uint sum = myVal1 + myVal2;
assert(myVal1 == myVal2);
}
function memoryAlloc() {
string memory myString = "test";
assert(bytes(myString).length == 10);
}
function storageAlloc() {
vars.push(2);
vars.push(3);
assert(vars.length == 4);
}
}
Debugging Smart Contract in Remix Ref
Environment가 “JavaScript VM” 인 경우에만 가능
Debugging Smart Contract in Remix
[assignment]
1. Instruction
- 현재 실행중인 OPCODE 를 보여줌
2. Solidity Locals
- 로칼변수를 보여줌
3. Stack
- 연산과정에서의 스택의 내용을 보여줌
Debugging Smart Contract in Remix
[memoryAlloc]
1. Memory
- 현재 메모리 상태를 보여줌
- 단위는 32바이트 단위로 값이 할당됨
Debugging Smart Contract in Remix
[storageAlloc]
1. Solidity States
- 상태변수의 정보를 보여줌
- 상태변수는 블록에 영구적으로 저장
2. Storage completely loaded
- 상태변수를 [key:value]의 형태로 보여줌
Layout of the Solidity source file
 컴파일러 버전 지정
 외부 소스화일 가져오기
 주석
pragma solidity ^0.4.0;
import "./someothercontract.sol";
// This is a single-line comment.
/*
This is a
multi-line comment.
*/
Structure of a Contract
 상태 변수 : contract storage 영역에 영구적으로 저장되는 state variables
 함수 : contract의 실행단위
 function name(a1, a2, a3) option returns (b1, b2, b3){ … }
pragma solidity ^0.4.0;
contract SimpleStorage {
uint storedData; // State variable
// ...
}
pragma solidity ^0.4.16;
contract Simple {
function arithmetics(uint _a, uint _b) public pure
returns (uint o_sum, uint o_product)
{
o_sum = _a + _b;
o_product = _a * _b;
}
}
함수의 option 필드
 가시성
 external : Contract 외부에서만 호출가능
 public : Contract 내부와 외부 모두에서 호출가능
 internal : 함수를 선언한 contract와 함수를 선언한 contract를 상속받은 contract에서 호출가능
 private : 함수를 선언한 contract 내부에서만 호출가능
 constant : 함수가 컨트랙트의 상태를 수정하지않음을 보장하며, gas를 소모하지 않음
 payable : 컨트랙트가 자신의 함수를 통해 다른 지갑이나 컨트랙트에서 이더를 송금받음
Structure of a Contract
 이벤트 : EVM 로깅 기능을 위한 인터페이스
 struct type
pragma solidity ^0.4.0;
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() public payable {
// ...
HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
}
pragma solidity ^0.4.0;
contract Ballot {
struct Voter { // Struct
uint weight;
bool voted;
address delegate;
uint vote;
}
}
 Enum type
pragma solidity ^0.4.0;
contract Purchase {
enum State { Created, Locked, Inactive } // Enum
}
Data type
 Boolean : bool (true or false)
 Integers : int/uint, int8/uint8, … , int256/uint256
 Fixed point numbers : ufixed0x8, ufixed0x16, …, ufixed0x256
 현재 solidit에서는 선언은 할수있지만, 값을 할당할수는 없음.
 Address : address
 멤버 : balance, transfer, send, call, callcode, delegatecall
 정적 바이트 배열 : byte, byte1, byte2, byte3, … , byte32
 멤버 : .length
 동적 바이트 배열 : bytes, string
 멤버 : .length, .push
address type member
 <address>.balance : wei 단위의 address의 잔액
 <address>.transfer(uint256 amount)
 addres로 amount의 wei를 전송, 2300 gas 사용, 실패시 exception을 반환하고 revert 됨
 일반적인 경우 transfer 사용
 <address>.send(uint256 amount) returns (bool)
 addres로 amount의 wei를 전송, 2300 gas 사용, 실패시 false를 반환하고, contract 실행이 중지되지 않음
 <address>.call(…) returns (bool)
 임의의 contract에 있는 함수를 호출시 사용하며 EVM의 CALL을 호출
 <address>.delegatecall(…) returns (bool)
 임의의 contract에 있는 함수를 호출시 사용하며 EVM의 DELEGATECALL을 호출
 호출된 함수에서 현재 contrac의 storage, balance등을 사용할수 있음
 다른 contract에 있는 코드를 라이브러리로 호출할때 사용
address x = 0x123;
address myAddress = this;
if (x.balance < 10 && myAddress.balance >= 10)
x.transfer(10);
Function call in another contract
pragma solidity ^0.4.17;
contract SomeContract {
event callMeMaybeEvent(address _from);
function callMeMaybe() payable public {
callMeMaybeEvent(this);
}
}
contract ThatCallsSomeContract {
function callTheOtherContract(address _contractAddress) public {
require(_contractAddress.call(bytes4(keccak256("callMeMaybe()"))));
require(_contractAddress.delegatecall(bytes4(keccak256("callMeMaybe()"))));
SomeLib.calledSomeLibFun();
}
}
library SomeLib {
event calledSomeLib(address _from);
function calledSomeLibFun() public {
calledSomeLib(this);
}
}
Function call in another contract
Function call in another contract
Function call in another contract
Mapping
 key와 value를 매핑하기 위해 사용
 mapping(_KeyType => _ValueType) name
 _KeyType : 매핑, 동적크기 배열, 컨트랙트, enum 타입을 제외한 모든 타입 가능
 _ValueType : 매핑을 포함한 모든 타입 가능
pragma solidity ^0.4.0;
contract MappingExample {
mapping(address => uint) public balances;
function update(uint newBalance) public {
balances[msg.sender] = newBalance;
}
}
contract MappingUser {
function f() public returns (uint) {
MappingExample m = new MappingExample();
m.update(100);
return m.balances(this);
}
}
이더리움 단위
 이더 통화 단위
 wei, finney, Szabo, ether 단위를 사용하여 단위계산 가능
 “2 ether == 2000 finney” 의 결과는 “true”
 시간 단위
 seconds, minutes, hours, days, weeks, years
 1 == 1 seconds, 1 minutes == 60 seconds, 1 hours == 60 minutes, 1 days == 24 hours
 1 weeks == 7 days, 1 years == 365 days
function f(uint start, uint daysAfter) public {
if (now >= start + daysAfter * 1 days) {
// ...
}
}
특수 변수 및 함수
 블록과 거래 속성
 block.blockhash(uint blocknumber) returns (bytes32)
: 해당 블록의 hash 값을 반환. 현재 블록포함 최근의 256 블록에 대해서만 작동
 block.coinbase (address) : 현재 블록 채굴자의 주소
 block.difficulty (uint) : 현재 블록의 채굴 난이도
 block.gaslimit (uint) : 현재 블록의 gaslimit를 반환
 block.number (uint) : 현재 블록번호
 block.timestamp (uint) : 현재 블록의 유닉스 타임스탬프를 반환
 gasleft() returns (uint256) : 남아있는 gas
 msg.data (bytes) : 메시지에 있는 데이터 전체
 msg.gas (uint) : 메시지의 남아있는 gas, 0.4.21 버전에서 gasleft로 교체
 msg.sender (address) : 메시지를 보낸 송신자의 주소, 즉 현재 스마트 컨트랙트를 실행시킨 사용자의 주소
 msg.sig (bytes4) : calldata의 첫번째 4바이트 function selector
 msg.value (uint) : wei 단위의 메시지의 송금액
 now (uint) : 현재 블록의 타임스탬프, block.timestamp와 동일
 tx.gasprice (uint) : 트랜잭션의 gasprice
 tx.origin (address) : 트랜잭션을 보낸 송신자의 주소
특수 변수 및 함수
 수학함수와 암호화 함수
 addmod(uint x, uint y, uint k) returns (uint) : (x +y) % k 를 계산
 mulmod(uint x, uint y, uint k) returns (uint) : (x * y) % k 를 계산
 keccak256(…) returns (bytes32) : 입력값에 대한 keccak256 hash 값을 반환
 sha256(…) returns (bytes32) : 입력값에 대한 SHA256 hash 값을 반환
 sha3(…) returns (bytes32) : 입력값에 대한 sha3 hash 값을 반환, keccak256과 동일
 ripemd160(…) returns (bytes20) : 입력값에 대한 RIPEMD-160 hash 값을 반환
 ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
 타원곡선 전자서명의 공개키와 관련된 주소를 반환, 에러 발생시 0을 반환
 컨트랙트 관련 함수
 this : 현재 컨트랙트
 selfdestruct(address recipient) : 현재 컨트랙트를 파괴하고 남아있는 잔액을 recipient로 전송
 suicide(address recipient) : selfdesctuct와 동일
함수호출 타입
 Internal function call
 contract 내부에서 직접 또는 재귀호출 방식으로 호출되는 방식
 External function call
 this.func2(8), cont.func2(2) : cont는 contract의 인스턴스
 jump가 아닌 Message call 방식으로 호출되며, Constructor에서는 external call을 할수없음
 external call을 통해 이더를 전송가능하며, value()로 이더를 지정하고, gas()로 gas 지정
 이더전송을 위해서는 해당함수의 상태 변경성을 payable로 지정해야함
pragma solidity ^0.4.16;
contract C {
function g(uint a) returns (uint ret) { return f(); }
function f() returns (uint ret) { return g(7) + f(); }
}
pragma solidity ^0.4.0;
contract DataFeed {
function data() payable returns (uint dataReturn) { return 42; }
}
contract DataConsumer {
DataFeed feed;
function feedSet(address addr) { feed = DataFeed(addr); }
function feedCall() { feed.data.value(10).gas(800)(); }
}
에러 핸들링
 solidity에서는 exception을 사용하여 에러를 다루고, 예외가 발생하면 변경이전 상태로 되돌아감
 revert() : 실행을 종료. 지금까지의 변경사항을 revert하고 미사용 gas를 반환
 assert(bool condition) : 조건이 false이면 실행을 종료. 내부오류 확인에 사용
 require(bool condition) : 조건이 false이면 실행을 종료. 입력값,컨트랙트 상태변수, 다른함수의 반환
값이 유효한지 검사. 외부적인 오류에서 사용
pragma solidity ^0.4.0;
contract TheSharer {
function sendHalfSum(address addrTo) payable returns (uint balance) {
require(msg.value % 2 == 0); // Allow even numbers only
uint balanceBefore = this.balance;
addrTo.transfer(msg.value / 2);
// Because transfer will throw an exception if it fails and
// is unable to call back here, we should have no way to
// = have half of all the money still.
assert(this.balance == balanceBefore - msg.value / 2);
return this.balance;
}
}
가시성
 external
 contract 외부에서만 호출가능
 f()가 external 인 경우 : f() 호출 불가능, this.f() 호출가능
 public
 contract 내부와 외부 모두에서 호출가능
 상태변수를 public으로 선언하면 상태변수를 조회하는 getter 함수를 자동으로 생성
 getter 함수의 이름은 상태변수의 이름과 동일
 internal
 함수나 상태변수를 선언한 contract와 contract를 상속받은 contract에서 호출 및 사용가능
 private
 함수나 상태변수를 선언한 contract 내부에서만 호출가능
가시성 예제// This code does not compile properly
pragma solidity ^0.4.0;
contract cont1 {
uint private data;
function func(uint x) private returns(uint y) { return x + 1; }
function dataSet(uint x) { data = x; }
function dataGet() public returns(uint) { return data; }
function compute(uint x, uint y) internal returns (uint) { return x+y; }
}
contract cont2 {
function dataRead() {
cont1 z = new cont1();
uint local = z.func(7); // error: member "func" is not visible
z.dataSet(3);
local = z.dataGet();
local = z.compute(3, 5); // error: member "compute" is not visible
}
}
contract cont3 is cont1 {
function g() {
cont1 z = new cont1();
uint val = compute(3, 5); // access to internal member (from derived to parent contract)
}
}
Getter 함수
pragma solidity ^0.4.0;
contract cont1 {
uint public data = 42;
}
contract contractCaller {
cont1 c = new cont1();
function func() {
uint local = c.data();
}
}
pragma solidity ^0.4.0;
contract cont1 {
uint public littleNumber;
function func() {
littleNumber = 3; // internal access
uint val = this.littleNumber(); // external access
}
}
함수 제어자(Function modifier)
 함수 정의부 끝에 해당 함수의 작동방식을 바꾸도록 지정
 가장 일반적인 사용은 함수 실행전 require 체크를 넣는것
contract owned {
function owned() public { owner = msg.sender; }
address owner;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}
contract mortal is owned {
function close() public onlyOwner {
selfdestruct(owner);
}
}
view 함수
 해당 함수가 상태를 변경하지 않음을 보장
 Getter 함수가 view 함수의 대표적인 예
 상태를 변경하는 예
 상태변수를 변경
 이벤트를 전송
 다른 컨트랙트를 생성
 selfdestruct가 호출
 call 함수를 통해 이더를 전송
 view나 pure로 선언되지 않은 함수를 호출
 low-level 함수를 호출
 상태변경 opcode를 실행하는 인라인 어셈블리 호출
pragma solidity ^0.4.16;
contract cont {
function func(uint x, uint y) view returns (uint) {
return x * (y + 42) + now;
}
}
pure 함수
 해당 함수가 상태를 변경하지 않는것 뿐만 아니라 상태를 읽지도 않음을 보장
 상태를 읽는 예
 상태변수를 읽음
 <address>.balance나 this.balance를 억세스
 msg, tx, block의 멤버를 억세스 (msg.sig와 msg.data는 제외)
 pure로 선언되지 않은 함수를 호출
 상태를 읽는 opcode가 포함된 인라인 어셈블리 호출
pragma solidity ^0.4.16;
contract cont {
function func(uint x, uint y) pure returns (uint) {
return x * (y + 42);
}
}
fallback 함수
 컨트랙트에 선언된 이름이 없는 함수로 컨트랙트는 단 하나의 폴백 함수만 정의할수 있음
 매개변수를 선언할수 없고, 값도 반환할수 없음
 컨트랙트에서 다른 컨트랙트로 send나 transfer를 호출하여 이더를 전송하면 호출됨
 이더리움 어카운트 주소의 call 함수를 호출할때 함수이름을 지정하지 않아도 폴백함수가 호
출되고, 존재하지 않는 함수를 호출해도 폴백함수가 호출됨
pragma solidity ^0.4.24;
contract Fallback{
uint public counter = 1;
function () public payable {
if(msg.value <= 0) {
revert();
}
counter++;
}
}
이벤트
 EVM 로깅기능을 편하게 사용하기 위한 방법
 Dapp의 사용자 인터페이스에서 JavaScript 콜백함수를 사용하여 이벤트를 수신할수 있음
 EVM은 5개의 로깅함수를 지원 : log0, log1, log2, log3, log4, logi
 Solidity에서 이벤트를 선언하면 이벤트가 호출될때 매개변수에 맞는 log함수가 호출
 이벤트 선언시 매개변수에 indexed 속성을 지정하면 해당 매개변수로 필터링할수 있음
 이벤트 사용 유스 케이스
 트랜잭션의 결과값을 확인하고 싶을때
 컨트랙트에 이더 송금등의 트랜잭션 이력을 기록하고 싶을때
 스토리지 영역은 32바이트당 20,000 가스사용, 로그 영역은 32바이트당 96 가스 사용
 트랜잭션을 생성한 어플리케이션을 트리거하기 위해
 Dapp이 모니터링하는 이벤트가 발생하면 이더리움은 해당 어플리케이션의 이벤트 처리할수를 호출
이벤트
pragma solidity ^0.4.10;
contract Cont {
function func() {
bytes32 _id = 0x420042;
log3(
bytes32(msg.sender),
bytes32(msg.value),
bytes32(/*hexadecimal equivalent to
kecak256("Deposit(address,hash256,uint256)")*/),
_id
);
}
}
pragma solidity ^0.4.0;
contract ClientReceipt {
event Deposit(
address indexed _from,
bytes32 indexed _id,
uint _value
);
function deposit(bytes32 _id) public payable {
// Events are emitted using `emit`, followed by
// the name of the event and the arguments
// (if any) in parentheses. Any such invocation
// (even deeply nested) can be detected from
// the JavaScript API by filtering for `Deposit`.
Deposit(msg.sender, _id, msg.value);
}
}
이벤트
var abi = /* abi as generated by the compiler */;
var ClientReceipt = web3.eth.contract(abi);
var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */);
var event = clientReceipt.Deposit();
// watch for changes
event.watch(function(error, result){
// result will contain various information
// including the argumets given to the `Deposit`
// call.
if (!error)
console.log(result);
});
// Or pass a callback to start watching immediately
var event = clientReceipt.Deposit(function(error, result) {
if (!error)
console.log(result);
});
상속pragma solidity ^0.4.16;
contract owned {
function owned() { owner = msg.sender; }
address owner;
}
contract mortal is owned {
function kill() {
if (msg.sender == owner) selfdestruct(owner);
}
}
contract Config {
function lookup(uint id) public returns (address adr);
}
contract NameReg {
function register(bytes32 name) public;
function unregister() public;
}
contract named is owned, mortal {
function named(bytes32 name) {
Config config =
Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).register(name);
}
function kill() public {
if (msg.sender == owner) {
Config config =
Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).unregister();
mortal.kill();
}
}
}
contract PriceFeed is owned, mortal, named("GoldFeed") {
function updateInfo(uint newInfo) public {
if (msg.sender == owner) info = newInfo;
}
function get() public view returns(uint r) { return info; }
uint info;
}
selfdestruct를 이용한 컨트랙트 제거의 위험성
pragma solidity ^0.4.0;
contract owned {
function owned() public { owner = msg.sender; }
address owner;
}
contract mortal is owned {
function kill() public {
if (msg.sender == owner) selfdestruct(owner);
}
}
contract Base1 is mortal {
function kill() public { /* do cleanup 1 */ mortal.kill(); }
}
contract Base2 is mortal {
function kill() public { /* do cleanup 2 */ mortal.kill(); }
}
contract Final is Base1, Base2 {
}
super로 안전하게 컨트랙트 제거하기
pragma solidity ^0.4.0;
contract owned {
function owned() public { owner = msg.sender; }
address owner;
}
contract mortal is owned {
function kill() public {
if (msg.sender == owner) selfdestruct(owner);
}
}
contract Base1 is mortal {
function kill() public { /* do cleanup 1 */ super.kill(); }
}
contract Base2 is mortal {
function kill() public { /* do cleanup 2 */ super.kill(); }
}
contract Final is Base1, Base2 {
}
 상속 그래프를 사용하여 안전하게 초기화 수행
 Final의 상속그래프
 Final, Base2, Base1, mortal, owned
추상 컨트랙트
 구현되지 않은 함수를 가지고 있는 컨트랙트
 new를 이용하여 인스턴스를 생성하지 못함
 베이스 컨트랙트 역할을 수행하며, 추상 컨트랙트를 상속받은 컨트랙트는 함수를 구현해야함
pragma solidity ^0.4.0;
contract Felinae {
function utterance() returns (bytes32);
}
contract Cheetah is Felinae {
function utterance() returns (bytes32) { return "sneaky cat"; }
}
인터페이스
 인터페이스는 추상 컨트랙트와 유사하지만 다음과 같은 추가적인 제약이 있음
 다른 컨트랙트나 인터페이스를 상속받을수 없음
 생성자, 상태변수, struct, enum 을 정의할수 없음
pragma solidity ^0.4.11;
interface Token {
function transfer(address recipient, uint amount) public;
}
라이브러리
 라이브러리의 목적은 블록체인에 배포된 컨트랙트를 재사용하기 위함
 라이브러리를 호출할때는 EVM의 delegatecall을 호출하여 코드를 재사용
 delegatecall을 호출할경우 실행 컨텍스트가 변경되지않고 호출하는 컨텍스트에서 함수실행
 라이브러리 함수에서 this 를 호출할경우 호출한 컨텍스트를 가리킴
 라이브러리는 컨트랙트에 비해 다음의 제약이 있음
 상태 변수를 정의할수 없음
 상속하거나 상속을 받을수 없음
 이더를 전송받을수 없음
라이브러리
pragma solidity ^0.4.16;
library Set {
struct Data { mapping(uint => bool) flags; }
function insert(Data storage self, uint value)
public returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value)
public returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value)
public view returns (bool)
{
return self.flags[value];
}
}
contract C {
Set.Data knownValues;
function register(uint value) public {
require(Set.insert(knownValues, value));
}
}
using A for B
 A의 라이브러리 함수들을 기존의 B 타입에 추가
pragma solidity ^0.4.16;
library Set {
struct Data { mapping(uint => bool) flags; }
function insert(Data storage self, uint value)
public returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value)
public returns (bool)
{
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value)
public view returns (bool)
{
return self.flags[value];
}
}
contract C {
using Set for Set.Data;
Set.Data knownValues;
function register(uint value) public {
// require(Set.insert(knownValues, value));
require(knownValues.insert(value));
}
}

More Related Content

What's hot

Blockchain Study(4) - Geth & Smart Contract
Blockchain Study(4) - Geth & Smart ContractBlockchain Study(4) - Geth & Smart Contract
Blockchain Study(4) - Geth & Smart ContractFermat Jade
 
세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화Jay JH Park
 
세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝Jay JH Park
 
Blockchain Study(3) - 이더리움(Geth)
Blockchain Study(3) - 이더리움(Geth)Blockchain Study(3) - 이더리움(Geth)
Blockchain Study(3) - 이더리움(Geth)Fermat Jade
 
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍Jay JH Park
 
Ethereum Basics Part 2
Ethereum Basics Part 2Ethereum Basics Part 2
Ethereum Basics Part 2Soobok Jin
 
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing SystemGCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System상현 조
 
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - PerfornanceGCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance상현 조
 
Block chain introduction slideshare
Block chain introduction   slideshareBlock chain introduction   slideshare
Block chain introduction slidesharewonyong hwang
 
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)상현 조
 
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server SampleGCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample상현 조
 
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with ExceptionGCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception상현 조
 
GCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group System
GCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group SystemGCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group System
GCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group System상현 조
 
GCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple Inhertance
GCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple InhertanceGCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple Inhertance
GCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple Inhertance상현 조
 
11_웹서비스활용
11_웹서비스활용11_웹서비스활용
11_웹서비스활용noerror
 
Mastering ethereum(smart contract)
Mastering ethereum(smart contract)Mastering ethereum(smart contract)
Mastering ethereum(smart contract)제호 송
 
Blockchain Study(2) - POW&POS
Blockchain Study(2) - POW&POSBlockchain Study(2) - POW&POS
Blockchain Study(2) - POW&POSFermat Jade
 
예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)
예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)
예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)Colin Chae
 
Ethereum 스마트 컨트랙트 보안
Ethereum 스마트 컨트랙트 보안Ethereum 스마트 컨트랙트 보안
Ethereum 스마트 컨트랙트 보안TIMEGATE
 
GCGC- CGCII 서버 엔진에 적용된 기술 (3) - Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (3) - ExceptionGCGC- CGCII 서버 엔진에 적용된 기술 (3) - Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (3) - Exception상현 조
 

What's hot (20)

Blockchain Study(4) - Geth & Smart Contract
Blockchain Study(4) - Geth & Smart ContractBlockchain Study(4) - Geth & Smart Contract
Blockchain Study(4) - Geth & Smart Contract
 
세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화세션3. geth 클라이언트 실습 및 모니터링과 시각화
세션3. geth 클라이언트 실습 및 모니터링과 시각화
 
세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝세션2. 이더리움 합의 알고리즘과 마이닝
세션2. 이더리움 합의 알고리즘과 마이닝
 
Blockchain Study(3) - 이더리움(Geth)
Blockchain Study(3) - 이더리움(Geth)Blockchain Study(3) - 이더리움(Geth)
Blockchain Study(3) - 이더리움(Geth)
 
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
세션4. 예제로 배우는 스마트 컨트랙트 프로그래밍
 
Ethereum Basics Part 2
Ethereum Basics Part 2Ethereum Basics Part 2
Ethereum Basics Part 2
 
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing SystemGCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
GCGC- CGCII 서버 엔진에 적용된 기술 (4) - Executing System
 
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - PerfornanceGCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
GCGC- CGCII 서버 엔진에 적용된 기술 (2) - Perfornance
 
Block chain introduction slideshare
Block chain introduction   slideshareBlock chain introduction   slideshare
Block chain introduction slideshare
 
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)GCGC- CGCII 서버 엔진에 적용된 기술 (1)
GCGC- CGCII 서버 엔진에 적용된 기술 (1)
 
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server SampleGCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample
 
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with ExceptionGCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (5) - Executor with Exception
 
GCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group System
GCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group SystemGCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group System
GCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group System
 
GCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple Inhertance
GCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple InhertanceGCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple Inhertance
GCGC- CGCII 서버 엔진에 적용된 기술 (7) - Multiple Inhertance
 
11_웹서비스활용
11_웹서비스활용11_웹서비스활용
11_웹서비스활용
 
Mastering ethereum(smart contract)
Mastering ethereum(smart contract)Mastering ethereum(smart contract)
Mastering ethereum(smart contract)
 
Blockchain Study(2) - POW&POS
Blockchain Study(2) - POW&POSBlockchain Study(2) - POW&POS
Blockchain Study(2) - POW&POS
 
예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)
예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)
예제로 배우는 이더리움 결제구현 (거래소 지갑 구현 예시)
 
Ethereum 스마트 컨트랙트 보안
Ethereum 스마트 컨트랙트 보안Ethereum 스마트 컨트랙트 보안
Ethereum 스마트 컨트랙트 보안
 
GCGC- CGCII 서버 엔진에 적용된 기술 (3) - Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (3) - ExceptionGCGC- CGCII 서버 엔진에 적용된 기술 (3) - Exception
GCGC- CGCII 서버 엔진에 적용된 기술 (3) - Exception
 

Similar to Blockchain 3rd smart contract programming

Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)fefe7270
 
Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)fefe7270
 
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안상욱 송
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)문익 장
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화AnselmKim
 
동기화, 스케줄링
동기화, 스케줄링동기화, 스케줄링
동기화, 스케줄링xxbdxx
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?NAVER D2
 
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화sung ki choi
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스noerror
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기jongho jeong
 
Smc–state machinecompiler
Smc–state machinecompilerSmc–state machinecompiler
Smc–state machinecompilerDong Hyeun Lee
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기현철 조
 
안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트병한 유
 
Prometheus Project Journey
Prometheus Project JourneyPrometheus Project Journey
Prometheus Project JourneyJinwoong Kim
 
Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)fefe7270
 
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요NAVER D2
 
Legacy code refactoring video rental system
Legacy code refactoring   video rental systemLegacy code refactoring   video rental system
Legacy code refactoring video rental systemJaehoon Oh
 
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Young-Beom Rhee
 

Similar to Blockchain 3rd smart contract programming (20)

Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)Surface flingerservice(서피스 상태 변경 및 출력 요청)
Surface flingerservice(서피스 상태 변경 및 출력 요청)
 
Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)Surface flingerservice(서피스 상태 변경 jb)
Surface flingerservice(서피스 상태 변경 jb)
 
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
이더리움 스마트계약 보안지침 가이드 2. 솔리디티 권고안
 
8.hooks
8.hooks8.hooks
8.hooks
 
Effective c++(chapter 5,6)
Effective c++(chapter 5,6)Effective c++(chapter 5,6)
Effective c++(chapter 5,6)
 
[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화[스프링 스터디 2일차] 서비스 추상화
[스프링 스터디 2일차] 서비스 추상화
 
동기화, 스케줄링
동기화, 스케줄링동기화, 스케줄링
동기화, 스케줄링
 
Mem cached
Mem cachedMem cached
Mem cached
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
 
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
 
NDC11_슈퍼클래스
NDC11_슈퍼클래스NDC11_슈퍼클래스
NDC11_슈퍼클래스
 
Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Smc–state machinecompiler
Smc–state machinecompilerSmc–state machinecompiler
Smc–state machinecompiler
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트
 
Prometheus Project Journey
Prometheus Project JourneyPrometheus Project Journey
Prometheus Project Journey
 
Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)Surface flingerservice(서피스 플링거 연결 jb)
Surface flingerservice(서피스 플링거 연결 jb)
 
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
[2B7]시즌2 멀티쓰레드프로그래밍이 왜 이리 힘드나요
 
Legacy code refactoring video rental system
Legacy code refactoring   video rental systemLegacy code refactoring   video rental system
Legacy code refactoring video rental system
 
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
Javascript 실행 가능한 코드(Executable Code)와 실행 콘텍스트(Execution Context), Lexical En...
 

Blockchain 3rd smart contract programming

  • 2. 목차  스마트 컨트랙트의 개념  Metamask와 Testnet을 활용한 스마트 컨트랙트 배포  ERC20 토큰 개발  Solidity 개발환경 및 디버깅 방법  Solidity 문법
  • 3. 스마트 컨트랙트  스마트 컨트랙트는 특정 계약을 스스로 수립, 검증, 이행하기 위한 컴퓨터 프로토콜  1996년 닉 자보( Nick Szabo : 컴퓨터과학자, 법학자, 암호학자)에 의해서 개념이 정립  “a set of promises, specified in digital form, including protocols within which the parties perform on these promises.”  조건이 충족되면 사람의 개입 없이 자동으로 실행되는 ‘자동화된 거래규약’  이더리움에서 스마트 컨트랙트는 이더리움의 상태를 변경할수 있는 프로그램 코드로서 블록 에 포함되어 각 노드에 전파되고, EVM에서 작동되어 상태전이를 발생  블록헤더의 데이타뿐만 아니라 특정 값이나 발신자 및 수신되는 메시지의 데이타를 조작하는 등 이더리움의 상태변화와 데이타 저장등이 가능한 프로그램 코드  새로운 스마트 컨트랙트를 생성하거나, 특정 스마트 컨트랙트상의 함수를 실행하거나, 이더 를 전송하는 방식중의 하나로 실행  사용자 어카운트(EOA)에 의해서 발생한 트랜잭션이나 다른 컨트랙트에 의해서만 실행  스마트 컨트랙트간의 호출은 메시지라는 특별한 구조체를 사용하여 호출
  • 5. EVM(Ethereum Virtual Machine) 구조  비휘발성 (non-volatile)  storage : 상태(state)가 저장  code : 스마트 컨트랙트의 컴파일된 바이트 코드가 저장  volatile (휘발성)  stack : OP 코드를 실행하기위한 스택영역  args : 컨트랙트 호출시에 넘어오는 인자를 저장  memory : word 단위로 아이템을 저장하는 바이트 배열
  • 6. EVM(Ethereum Virtual Machine) 특징  임시저장소와 영구저장소를 구분하여, 임시저장소에 저장한 값은 해당 인스턴스에서만 유효 하고, 영구저장소에 저장한 값은 해당 컨트랙트 전체에 유효  EVM에서 바이트 코드를 실행하기 위해서는 다음의 3가지 요소가 필요  컨테이너에 값을 Push, Pop하기 위한 스택  바이트 배열을 담을수 있는 메모리  영속적으로 값을 저장하기 위한 저장소. 현재 저장소로는 레벨DB를 사용  4,8바이트 워드단위는 크기가 너무작아, 32바이트 워드 단위를 지원  32바이트 워드크기 등 이더리움에서 요구하는 VM기능과 명세를 지원하기 위해 단순화된 자체 VM을 개발  메모리 크기가 가변적이고 스택의 크기에 제한이 없음  반복호출횟수를 1024로 제한
  • 7. EVM OP코드 [OPCODE 표] 0s: Stop and Arithmetic Operations 10s: Comparison & Bitwise Logic Operations 20s: SHA3 30s: Environmental Information 40s: Block Information 50s: Stack, Memory, Storage and Flow Operations 60s & 70s: Push Operations 80s: Duplication Operations 90s: Exchange Operations a0s: Logging Operations [OPCODE 분류표]
  • 8. EVM OP코드와 동작원리  “1+2” 계산 OPCODE 실행
  • 9. First Smart Contract in Remix pragma solidity ^0.4.0; contract SimpleStorage { uint storedData; function set(uint x) public { storedData = x; } function get() public constant returns (uint) { return storedData; } } https://solidity.readthedocs.io
  • 13. 함수 호출시 InputData  4바이트의 Function Selector + 32바이트*n 의 함수 arguments  Function Selector = keccak256(function prototype) 의 앞 4바이트  Function name  Parameters  Return Type은 Function selector에 사용되지않음
  • 14. 최소요건을 갖춘 토큰 pragma solidity ^0.4.16; contract MinimumViableToken { mapping (address => uint256) public balanceOf; function MinimumViableToken(uint256 initialSupply) public { balanceOf[msg.sender] = initialSupply; } function transfer(address _to, uint256 _value) public { balanceOf[msg.sender] -= _value; balanceOf[_to] += _value; } }
  • 16. ERC20 Token // Balances for each account mapping(address => uint256) balances; // Owner of account approves the transfer of an amount to another account mapping(address => mapping (address => uint256)) allowed; // 현재까지 공급된 토큰수 function totalSupply() constant returns (uint256 supply) {} // _owner가 보유한 토큰잔액을 반환 function balanceOf(address _owner) constant returns (uint256 balance) {} // 수신자(_to) 로 해당금액(_value)를 송금. 송금이 성공하면 TRUE를 반환하고, 실패하면 FALSE를 반환. function transfer(address _to, uint256 _value) returns (bool success) {} // 송신자(_from)주소에서 수신자(_to) 주소로 해당금액(_value)을 송금. 송금이 성공하면 TRUE, // 실패하면 FALSE를 반환. transferFrom이 성공하려면 먼저 approve 인터페이스를 사용하여 // 일정금액을 인출할수 있도록 허락하여야 함. function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {} // 송신자(msg.sender)가 보유한 토큰에서 일정금액(_value)만큼의 토큰을 인출할수 있는 권한을 // 수신자(_spender)에게 부여. function approve(address _spender, uint256 _value) returns (bool success) {} // 토큰 소유자(_owner)가 토큰 수신자(_spender)에게 인출을 허락한 토큰이 얼마인지를 반환. function allowance(address _owner, address _spender) constant returns (uint256 remaining) {} event Transfer(address indexed _from, address indexed _to, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value); https://theethereum.wiki/w/index.php/ERC20_Token_Standard
  • 17. Debugging Smart Contract in Remix EVM Execution Structure Program Counter - 다음 차례에 실행할 EVM 명령어의 위치 Program - EVM이 실행할 스마트 컨트랙트의 EVM 명령어 목록을 보관 Stack - 연산에 필요한 데이타를 저장하는 공간. - 32바이트 크기의 값들이 저장되며, 최대 1024개가 저장. Storage - 블록체인에 영구적으로 기록하기 위한 저장공간. - 키/값을 매핑하기위한 구조이며, 256비트 크기를 사용. Memory - 함수를 호출하거나 메모리 연산을 수행할때 임시로 사용되는 공간. - 데이타를 읽을때는 256비트 단위, 쓸때는 8비트단위나 256비트 단위로도 가능. Log - 스마트 컨트랙트가 실행될때 부가적인 정보를 저장하기 위한 공간. Call Data - 이더리움에 트랜잭션을 요청했을때 전송되는 데이타들이 저장되는 공간.
  • 18. Debugging Smart Contract in Remix pragma solidity ^0.4.0; contract Debugging { uint[] private vars; function assignment() { uint myVal1 = 1; uint myVal2 = 2; uint sum = myVal1 + myVal2; assert(myVal1 == myVal2); } function memoryAlloc() { string memory myString = "test"; assert(bytes(myString).length == 10); } function storageAlloc() { vars.push(2); vars.push(3); assert(vars.length == 4); } }
  • 19. Debugging Smart Contract in Remix Ref Environment가 “JavaScript VM” 인 경우에만 가능
  • 20. Debugging Smart Contract in Remix [assignment] 1. Instruction - 현재 실행중인 OPCODE 를 보여줌 2. Solidity Locals - 로칼변수를 보여줌 3. Stack - 연산과정에서의 스택의 내용을 보여줌
  • 21. Debugging Smart Contract in Remix [memoryAlloc] 1. Memory - 현재 메모리 상태를 보여줌 - 단위는 32바이트 단위로 값이 할당됨
  • 22. Debugging Smart Contract in Remix [storageAlloc] 1. Solidity States - 상태변수의 정보를 보여줌 - 상태변수는 블록에 영구적으로 저장 2. Storage completely loaded - 상태변수를 [key:value]의 형태로 보여줌
  • 23. Layout of the Solidity source file  컴파일러 버전 지정  외부 소스화일 가져오기  주석 pragma solidity ^0.4.0; import "./someothercontract.sol"; // This is a single-line comment. /* This is a multi-line comment. */
  • 24. Structure of a Contract  상태 변수 : contract storage 영역에 영구적으로 저장되는 state variables  함수 : contract의 실행단위  function name(a1, a2, a3) option returns (b1, b2, b3){ … } pragma solidity ^0.4.0; contract SimpleStorage { uint storedData; // State variable // ... } pragma solidity ^0.4.16; contract Simple { function arithmetics(uint _a, uint _b) public pure returns (uint o_sum, uint o_product) { o_sum = _a + _b; o_product = _a * _b; } }
  • 25. 함수의 option 필드  가시성  external : Contract 외부에서만 호출가능  public : Contract 내부와 외부 모두에서 호출가능  internal : 함수를 선언한 contract와 함수를 선언한 contract를 상속받은 contract에서 호출가능  private : 함수를 선언한 contract 내부에서만 호출가능  constant : 함수가 컨트랙트의 상태를 수정하지않음을 보장하며, gas를 소모하지 않음  payable : 컨트랙트가 자신의 함수를 통해 다른 지갑이나 컨트랙트에서 이더를 송금받음
  • 26. Structure of a Contract  이벤트 : EVM 로깅 기능을 위한 인터페이스  struct type pragma solidity ^0.4.0; contract SimpleAuction { event HighestBidIncreased(address bidder, uint amount); // Event function bid() public payable { // ... HighestBidIncreased(msg.sender, msg.value); // Triggering event } } pragma solidity ^0.4.0; contract Ballot { struct Voter { // Struct uint weight; bool voted; address delegate; uint vote; } }  Enum type pragma solidity ^0.4.0; contract Purchase { enum State { Created, Locked, Inactive } // Enum }
  • 27. Data type  Boolean : bool (true or false)  Integers : int/uint, int8/uint8, … , int256/uint256  Fixed point numbers : ufixed0x8, ufixed0x16, …, ufixed0x256  현재 solidit에서는 선언은 할수있지만, 값을 할당할수는 없음.  Address : address  멤버 : balance, transfer, send, call, callcode, delegatecall  정적 바이트 배열 : byte, byte1, byte2, byte3, … , byte32  멤버 : .length  동적 바이트 배열 : bytes, string  멤버 : .length, .push
  • 28. address type member  <address>.balance : wei 단위의 address의 잔액  <address>.transfer(uint256 amount)  addres로 amount의 wei를 전송, 2300 gas 사용, 실패시 exception을 반환하고 revert 됨  일반적인 경우 transfer 사용  <address>.send(uint256 amount) returns (bool)  addres로 amount의 wei를 전송, 2300 gas 사용, 실패시 false를 반환하고, contract 실행이 중지되지 않음  <address>.call(…) returns (bool)  임의의 contract에 있는 함수를 호출시 사용하며 EVM의 CALL을 호출  <address>.delegatecall(…) returns (bool)  임의의 contract에 있는 함수를 호출시 사용하며 EVM의 DELEGATECALL을 호출  호출된 함수에서 현재 contrac의 storage, balance등을 사용할수 있음  다른 contract에 있는 코드를 라이브러리로 호출할때 사용 address x = 0x123; address myAddress = this; if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
  • 29. Function call in another contract pragma solidity ^0.4.17; contract SomeContract { event callMeMaybeEvent(address _from); function callMeMaybe() payable public { callMeMaybeEvent(this); } } contract ThatCallsSomeContract { function callTheOtherContract(address _contractAddress) public { require(_contractAddress.call(bytes4(keccak256("callMeMaybe()")))); require(_contractAddress.delegatecall(bytes4(keccak256("callMeMaybe()")))); SomeLib.calledSomeLibFun(); } } library SomeLib { event calledSomeLib(address _from); function calledSomeLibFun() public { calledSomeLib(this); } }
  • 30. Function call in another contract
  • 31. Function call in another contract
  • 32. Function call in another contract
  • 33. Mapping  key와 value를 매핑하기 위해 사용  mapping(_KeyType => _ValueType) name  _KeyType : 매핑, 동적크기 배열, 컨트랙트, enum 타입을 제외한 모든 타입 가능  _ValueType : 매핑을 포함한 모든 타입 가능 pragma solidity ^0.4.0; contract MappingExample { mapping(address => uint) public balances; function update(uint newBalance) public { balances[msg.sender] = newBalance; } } contract MappingUser { function f() public returns (uint) { MappingExample m = new MappingExample(); m.update(100); return m.balances(this); } }
  • 34. 이더리움 단위  이더 통화 단위  wei, finney, Szabo, ether 단위를 사용하여 단위계산 가능  “2 ether == 2000 finney” 의 결과는 “true”  시간 단위  seconds, minutes, hours, days, weeks, years  1 == 1 seconds, 1 minutes == 60 seconds, 1 hours == 60 minutes, 1 days == 24 hours  1 weeks == 7 days, 1 years == 365 days function f(uint start, uint daysAfter) public { if (now >= start + daysAfter * 1 days) { // ... } }
  • 35. 특수 변수 및 함수  블록과 거래 속성  block.blockhash(uint blocknumber) returns (bytes32) : 해당 블록의 hash 값을 반환. 현재 블록포함 최근의 256 블록에 대해서만 작동  block.coinbase (address) : 현재 블록 채굴자의 주소  block.difficulty (uint) : 현재 블록의 채굴 난이도  block.gaslimit (uint) : 현재 블록의 gaslimit를 반환  block.number (uint) : 현재 블록번호  block.timestamp (uint) : 현재 블록의 유닉스 타임스탬프를 반환  gasleft() returns (uint256) : 남아있는 gas  msg.data (bytes) : 메시지에 있는 데이터 전체  msg.gas (uint) : 메시지의 남아있는 gas, 0.4.21 버전에서 gasleft로 교체  msg.sender (address) : 메시지를 보낸 송신자의 주소, 즉 현재 스마트 컨트랙트를 실행시킨 사용자의 주소  msg.sig (bytes4) : calldata의 첫번째 4바이트 function selector  msg.value (uint) : wei 단위의 메시지의 송금액  now (uint) : 현재 블록의 타임스탬프, block.timestamp와 동일  tx.gasprice (uint) : 트랜잭션의 gasprice  tx.origin (address) : 트랜잭션을 보낸 송신자의 주소
  • 36. 특수 변수 및 함수  수학함수와 암호화 함수  addmod(uint x, uint y, uint k) returns (uint) : (x +y) % k 를 계산  mulmod(uint x, uint y, uint k) returns (uint) : (x * y) % k 를 계산  keccak256(…) returns (bytes32) : 입력값에 대한 keccak256 hash 값을 반환  sha256(…) returns (bytes32) : 입력값에 대한 SHA256 hash 값을 반환  sha3(…) returns (bytes32) : 입력값에 대한 sha3 hash 값을 반환, keccak256과 동일  ripemd160(…) returns (bytes20) : 입력값에 대한 RIPEMD-160 hash 값을 반환  ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)  타원곡선 전자서명의 공개키와 관련된 주소를 반환, 에러 발생시 0을 반환  컨트랙트 관련 함수  this : 현재 컨트랙트  selfdestruct(address recipient) : 현재 컨트랙트를 파괴하고 남아있는 잔액을 recipient로 전송  suicide(address recipient) : selfdesctuct와 동일
  • 37. 함수호출 타입  Internal function call  contract 내부에서 직접 또는 재귀호출 방식으로 호출되는 방식  External function call  this.func2(8), cont.func2(2) : cont는 contract의 인스턴스  jump가 아닌 Message call 방식으로 호출되며, Constructor에서는 external call을 할수없음  external call을 통해 이더를 전송가능하며, value()로 이더를 지정하고, gas()로 gas 지정  이더전송을 위해서는 해당함수의 상태 변경성을 payable로 지정해야함 pragma solidity ^0.4.16; contract C { function g(uint a) returns (uint ret) { return f(); } function f() returns (uint ret) { return g(7) + f(); } } pragma solidity ^0.4.0; contract DataFeed { function data() payable returns (uint dataReturn) { return 42; } } contract DataConsumer { DataFeed feed; function feedSet(address addr) { feed = DataFeed(addr); } function feedCall() { feed.data.value(10).gas(800)(); } }
  • 38. 에러 핸들링  solidity에서는 exception을 사용하여 에러를 다루고, 예외가 발생하면 변경이전 상태로 되돌아감  revert() : 실행을 종료. 지금까지의 변경사항을 revert하고 미사용 gas를 반환  assert(bool condition) : 조건이 false이면 실행을 종료. 내부오류 확인에 사용  require(bool condition) : 조건이 false이면 실행을 종료. 입력값,컨트랙트 상태변수, 다른함수의 반환 값이 유효한지 검사. 외부적인 오류에서 사용 pragma solidity ^0.4.0; contract TheSharer { function sendHalfSum(address addrTo) payable returns (uint balance) { require(msg.value % 2 == 0); // Allow even numbers only uint balanceBefore = this.balance; addrTo.transfer(msg.value / 2); // Because transfer will throw an exception if it fails and // is unable to call back here, we should have no way to // = have half of all the money still. assert(this.balance == balanceBefore - msg.value / 2); return this.balance; } }
  • 39. 가시성  external  contract 외부에서만 호출가능  f()가 external 인 경우 : f() 호출 불가능, this.f() 호출가능  public  contract 내부와 외부 모두에서 호출가능  상태변수를 public으로 선언하면 상태변수를 조회하는 getter 함수를 자동으로 생성  getter 함수의 이름은 상태변수의 이름과 동일  internal  함수나 상태변수를 선언한 contract와 contract를 상속받은 contract에서 호출 및 사용가능  private  함수나 상태변수를 선언한 contract 내부에서만 호출가능
  • 40. 가시성 예제// This code does not compile properly pragma solidity ^0.4.0; contract cont1 { uint private data; function func(uint x) private returns(uint y) { return x + 1; } function dataSet(uint x) { data = x; } function dataGet() public returns(uint) { return data; } function compute(uint x, uint y) internal returns (uint) { return x+y; } } contract cont2 { function dataRead() { cont1 z = new cont1(); uint local = z.func(7); // error: member "func" is not visible z.dataSet(3); local = z.dataGet(); local = z.compute(3, 5); // error: member "compute" is not visible } } contract cont3 is cont1 { function g() { cont1 z = new cont1(); uint val = compute(3, 5); // access to internal member (from derived to parent contract) } }
  • 41. Getter 함수 pragma solidity ^0.4.0; contract cont1 { uint public data = 42; } contract contractCaller { cont1 c = new cont1(); function func() { uint local = c.data(); } } pragma solidity ^0.4.0; contract cont1 { uint public littleNumber; function func() { littleNumber = 3; // internal access uint val = this.littleNumber(); // external access } }
  • 42. 함수 제어자(Function modifier)  함수 정의부 끝에 해당 함수의 작동방식을 바꾸도록 지정  가장 일반적인 사용은 함수 실행전 require 체크를 넣는것 contract owned { function owned() public { owner = msg.sender; } address owner; modifier onlyOwner { require(msg.sender == owner); _; } } contract mortal is owned { function close() public onlyOwner { selfdestruct(owner); } }
  • 43. view 함수  해당 함수가 상태를 변경하지 않음을 보장  Getter 함수가 view 함수의 대표적인 예  상태를 변경하는 예  상태변수를 변경  이벤트를 전송  다른 컨트랙트를 생성  selfdestruct가 호출  call 함수를 통해 이더를 전송  view나 pure로 선언되지 않은 함수를 호출  low-level 함수를 호출  상태변경 opcode를 실행하는 인라인 어셈블리 호출 pragma solidity ^0.4.16; contract cont { function func(uint x, uint y) view returns (uint) { return x * (y + 42) + now; } }
  • 44. pure 함수  해당 함수가 상태를 변경하지 않는것 뿐만 아니라 상태를 읽지도 않음을 보장  상태를 읽는 예  상태변수를 읽음  <address>.balance나 this.balance를 억세스  msg, tx, block의 멤버를 억세스 (msg.sig와 msg.data는 제외)  pure로 선언되지 않은 함수를 호출  상태를 읽는 opcode가 포함된 인라인 어셈블리 호출 pragma solidity ^0.4.16; contract cont { function func(uint x, uint y) pure returns (uint) { return x * (y + 42); } }
  • 45. fallback 함수  컨트랙트에 선언된 이름이 없는 함수로 컨트랙트는 단 하나의 폴백 함수만 정의할수 있음  매개변수를 선언할수 없고, 값도 반환할수 없음  컨트랙트에서 다른 컨트랙트로 send나 transfer를 호출하여 이더를 전송하면 호출됨  이더리움 어카운트 주소의 call 함수를 호출할때 함수이름을 지정하지 않아도 폴백함수가 호 출되고, 존재하지 않는 함수를 호출해도 폴백함수가 호출됨 pragma solidity ^0.4.24; contract Fallback{ uint public counter = 1; function () public payable { if(msg.value <= 0) { revert(); } counter++; } }
  • 46. 이벤트  EVM 로깅기능을 편하게 사용하기 위한 방법  Dapp의 사용자 인터페이스에서 JavaScript 콜백함수를 사용하여 이벤트를 수신할수 있음  EVM은 5개의 로깅함수를 지원 : log0, log1, log2, log3, log4, logi  Solidity에서 이벤트를 선언하면 이벤트가 호출될때 매개변수에 맞는 log함수가 호출  이벤트 선언시 매개변수에 indexed 속성을 지정하면 해당 매개변수로 필터링할수 있음  이벤트 사용 유스 케이스  트랜잭션의 결과값을 확인하고 싶을때  컨트랙트에 이더 송금등의 트랜잭션 이력을 기록하고 싶을때  스토리지 영역은 32바이트당 20,000 가스사용, 로그 영역은 32바이트당 96 가스 사용  트랜잭션을 생성한 어플리케이션을 트리거하기 위해  Dapp이 모니터링하는 이벤트가 발생하면 이더리움은 해당 어플리케이션의 이벤트 처리할수를 호출
  • 47. 이벤트 pragma solidity ^0.4.10; contract Cont { function func() { bytes32 _id = 0x420042; log3( bytes32(msg.sender), bytes32(msg.value), bytes32(/*hexadecimal equivalent to kecak256("Deposit(address,hash256,uint256)")*/), _id ); } } pragma solidity ^0.4.0; contract ClientReceipt { event Deposit( address indexed _from, bytes32 indexed _id, uint _value ); function deposit(bytes32 _id) public payable { // Events are emitted using `emit`, followed by // the name of the event and the arguments // (if any) in parentheses. Any such invocation // (even deeply nested) can be detected from // the JavaScript API by filtering for `Deposit`. Deposit(msg.sender, _id, msg.value); } }
  • 48. 이벤트 var abi = /* abi as generated by the compiler */; var ClientReceipt = web3.eth.contract(abi); var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */); var event = clientReceipt.Deposit(); // watch for changes event.watch(function(error, result){ // result will contain various information // including the argumets given to the `Deposit` // call. if (!error) console.log(result); }); // Or pass a callback to start watching immediately var event = clientReceipt.Deposit(function(error, result) { if (!error) console.log(result); });
  • 49. 상속pragma solidity ^0.4.16; contract owned { function owned() { owner = msg.sender; } address owner; } contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } } contract Config { function lookup(uint id) public returns (address adr); } contract NameReg { function register(bytes32 name) public; function unregister() public; } contract named is owned, mortal { function named(bytes32 name) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).register(name); } function kill() public { if (msg.sender == owner) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).unregister(); mortal.kill(); } } } contract PriceFeed is owned, mortal, named("GoldFeed") { function updateInfo(uint newInfo) public { if (msg.sender == owner) info = newInfo; } function get() public view returns(uint r) { return info; } uint info; }
  • 50. selfdestruct를 이용한 컨트랙트 제거의 위험성 pragma solidity ^0.4.0; contract owned { function owned() public { owner = msg.sender; } address owner; } contract mortal is owned { function kill() public { if (msg.sender == owner) selfdestruct(owner); } } contract Base1 is mortal { function kill() public { /* do cleanup 1 */ mortal.kill(); } } contract Base2 is mortal { function kill() public { /* do cleanup 2 */ mortal.kill(); } } contract Final is Base1, Base2 { }
  • 51. super로 안전하게 컨트랙트 제거하기 pragma solidity ^0.4.0; contract owned { function owned() public { owner = msg.sender; } address owner; } contract mortal is owned { function kill() public { if (msg.sender == owner) selfdestruct(owner); } } contract Base1 is mortal { function kill() public { /* do cleanup 1 */ super.kill(); } } contract Base2 is mortal { function kill() public { /* do cleanup 2 */ super.kill(); } } contract Final is Base1, Base2 { }  상속 그래프를 사용하여 안전하게 초기화 수행  Final의 상속그래프  Final, Base2, Base1, mortal, owned
  • 52. 추상 컨트랙트  구현되지 않은 함수를 가지고 있는 컨트랙트  new를 이용하여 인스턴스를 생성하지 못함  베이스 컨트랙트 역할을 수행하며, 추상 컨트랙트를 상속받은 컨트랙트는 함수를 구현해야함 pragma solidity ^0.4.0; contract Felinae { function utterance() returns (bytes32); } contract Cheetah is Felinae { function utterance() returns (bytes32) { return "sneaky cat"; } }
  • 53. 인터페이스  인터페이스는 추상 컨트랙트와 유사하지만 다음과 같은 추가적인 제약이 있음  다른 컨트랙트나 인터페이스를 상속받을수 없음  생성자, 상태변수, struct, enum 을 정의할수 없음 pragma solidity ^0.4.11; interface Token { function transfer(address recipient, uint amount) public; }
  • 54. 라이브러리  라이브러리의 목적은 블록체인에 배포된 컨트랙트를 재사용하기 위함  라이브러리를 호출할때는 EVM의 delegatecall을 호출하여 코드를 재사용  delegatecall을 호출할경우 실행 컨텍스트가 변경되지않고 호출하는 컨텍스트에서 함수실행  라이브러리 함수에서 this 를 호출할경우 호출한 컨텍스트를 가리킴  라이브러리는 컨트랙트에 비해 다음의 제약이 있음  상태 변수를 정의할수 없음  상속하거나 상속을 받을수 없음  이더를 전송받을수 없음
  • 55. 라이브러리 pragma solidity ^0.4.16; library Set { struct Data { mapping(uint => bool) flags; } function insert(Data storage self, uint value) public returns (bool) { if (self.flags[value]) return false; // already there self.flags[value] = true; return true; } function remove(Data storage self, uint value) public returns (bool) { if (!self.flags[value]) return false; // not there self.flags[value] = false; return true; } function contains(Data storage self, uint value) public view returns (bool) { return self.flags[value]; } } contract C { Set.Data knownValues; function register(uint value) public { require(Set.insert(knownValues, value)); } }
  • 56. using A for B  A의 라이브러리 함수들을 기존의 B 타입에 추가 pragma solidity ^0.4.16; library Set { struct Data { mapping(uint => bool) flags; } function insert(Data storage self, uint value) public returns (bool) { if (self.flags[value]) return false; // already there self.flags[value] = true; return true; } function remove(Data storage self, uint value) public returns (bool) { if (!self.flags[value]) return false; // not there self.flags[value] = false; return true; } function contains(Data storage self, uint value) public view returns (bool) { return self.flags[value]; } } contract C { using Set for Set.Data; Set.Data knownValues; function register(uint value) public { // require(Set.insert(knownValues, value)); require(knownValues.insert(value)); } }