Chapter 4
Remind
접근 제어자
- private : 컨트랙트 내부의 함수에서만 호출 가능
- internal : private + 상속에서도 호출 가능
- external : 컨트랙트 외부에서만 호출 가능
- public : 어디서든 호출 가능
상태 제어자
- view : 해당 함수 실행해봤자 데이터 저장/변경 X
- pure : view + 블록체인으로부터 어떤 데이터도 불러오지 않음
이 둘 모두 가스 소모하지 않지만, 다른 함수로부터 호출됐을 경우에는 가스 소모
payable 제어자
- 이더를 받을 수 있는 함수
- msg.value로 얼마의 ether가 보내졌는지 확인 가능
출금
- transfer 함수 사용해서 이더를 특정 주소로 전달 가능
- this.balance 는 저장되어있는 전체 잔액 반환
예시)
- msg.sender.transfer : msg.sender에게 보냄
- owner.transfer : 컨트랙트에서 이더 인출
- seller.transfer : 구매자에게 이더 전달
등등으로 활용 가능
keccak256 난수 생성
- keccak256 해시 함수로 난수 생성 가능
- 사실 간단하고 쉬운 방법이긴 하지만, 공격 당할 가능성이 큼
- 본인이 크게 건 뒤, 함수를 돌렸을 때 진다면 해당 트랜잭션을 포함하지 않는 방식으로
- 이를 위해 이더리움 외부의 난수 함수에 접근 하는 방법이 있으나, 이는 후에 알아보자..
Chapter 5
토큰
- 토큰은 그저 하나의 컨트랙트일 뿐이다.
- 다만 기본적으로 몇몇 공통 규약을 정해두었는데, 그것이 ERC20
ERC20의 필요성
- 모든 토큰이 동일한 함수 집합을 공유하면, 상호작용에 유용함
- 하나의 토큰에 상호작용하는 app을 만들면, 다른 토큰과도 상호작용 가능
- 즉, app에 접근 가능한 토큰이 다양해짐
토큰 컨트랙트 구현
- 토큰 컨트랙트 구현을 위해서는 인터페이스를 import 해야함
- 그 후 해당 컨트랙트를 상속하는 우리의 컨트랙트 만들고, 오버라이딩으로 함수 정의
다수의 컨트랙트 상속
contract SatoshiNakamoto is NickSzabo, HalFinney {
NickSzabo HalFinney 다중 상속
}
balanceOf 함수
function balanceOf(address _owner) public view returns (uint256 _balance);
- address를 받아, 해당 address가 토큰을 얼마나 갖고 있는지 반환
- public이고 view 함수 (가스 소모가 없겠네?)
ownerOf
function ownerOf(uint256 _tokenId) public view returns (address _owner);
- 토큰 ID를 받아, 소유자의 address 반환
- 이것도 public, view
토큰 전송 로직
- 토큰의 소유자가, 상대의 address와 토큰 ID로 transfer 함수 호출
function transfer(address _to, uint256 _tokenId) public;
- 토큰의 소유자가 1번의 정보로 approve 호출,
그 후 전송 상대가 takeOwnership으로 호출하면 해당 토큰을 전송
function approve(address _to, uint256 _tokenId) public;
function takeOwnership(uint256 _tokenId) public;
1,2번의 차이
- 1번과 2번은 로직은 동일함
- 하지만 1번은 보내는 사람이 직접 전송하고, 2번은 승인해두면 받는 사람이 챙겨가는 방식
컨트랙트 보안강화 - 오버플로우와 언더플로우
예를 들면, uint8 데이터타입은 00000000~11111111 까지 수 저장 가능
이때 11111111에 1을 더하면 이 수는 00000000으로 돌아감
이를 막기 위해 SafeMath 사용
SafeMath
기존 더하기(+)와 비슷하지만, assert 구문이 포함되어 있음
assert는 require와 비슷하지만,
require는 함수 실행 실패하면, 남은 가스를 사용자에게 돌려주지만 assert는 돌려주지 않음