solidity는 이더리움에서 smartContract를 정의할때 사용하는 언어로서 javascript에다가 몇가지 기능을 추가한 언어이다.
헬로월드 수준은: http://www.chaintalk.io/archive/lecture/86
간단한 dApp예제는 : http://www.chaintalk.io/archive/lecture/501
공부하기 가장좋은 사이트는 크립토좀비.
거기서 공부한 예제를 보면 다음과 같다.
pragma solidity ^0.4.19;
contract ZombieFactory {
// 여기에 이벤트 선언 - 이벤트는 나중에 별도로
uint dnaDigits = 16;
uint dnaModulus = 10 ** dnaDigits;
//struct: 생성자 자동, myZombie.name 으로 접근.
//struct내에서는 uint(256) 보다는 uint8을 쓰는게 가스소모량을 줄인다.
struct Zombie {
string name;
uint dna;
}
Zombie[] public zombies; //변수나 함수 되에 public/private 선언이 가능하다.
//private함수 및 param의 이름은 _로 시작하는게 관례 // internal: 자식class에서도 호출가능-private은 안됨 external: 외부에서만 호출가능
function _createZombie(string _name, uint _dna) private {
zombies.push(Zombie(_name, _dna));
// 여기서 이벤트 실행
}
//view:읽기만 하는 함수외부서호출시gas불소모, pure:다른변수 전혀 안쓰는 함수, return은 여러개도 가능
function _generateRandomDna(string _str) private view returns (uint) {
uint rand = uint(keccak256(_str)); //이더리움에서 지원하는 SHA함수로 16진수 return. uint로 변환필요
return rand % dnaModulus;
}
function createRandomZombie(string _name) public {
uint randDna = _generateRandomDna(_name);
_createZombie(_name, randDna);
}
}
<Event>
//선언
event NewZombieAdded(uint zombieId, string name, uint dna);
//이벤트 실행: dApp으로 신호보내기 임.
NewZombieAdded(id, _name, _dna); //id= zombies.push(..)-1 로 가능. push는 length리턴.
이벤트 받는 예제는 : REF
<Mapping> 매핑은 말이 Mapping이지 사용법을 array와 동일하게 만들어 놨음.
msg.sender 이용(해보자) : 컨트랙트내의 함수를 외부에서 호출한 사람주소
mapping (address => uint) favoriteZombieMap;
function setMyNumber(uint _myNumber) public {
favoriteZombieMap[msg.sender] = _myNumber;
}
<Require> Require는 if 함수와 비슷하지만, 조건이 안 맞으면 에러를 낸다.
solidity에는 string비교함수가 없으므로 SHA해시로 비교한다.
require(keccak256(_name) == keccak256("Vitalik"));
<상속>
contract ZombieFeeding is ZombieFactory {
}
<storage 및 메모리>
storage: HDD 또는 heap느낌. 블록체인에 영구저장됨. contract의 멤버변수들도 여기 해당됨.
memory: RAM 또는 stack느낌.
대부분 storage/memory구분없이 사용해도 자동으로 되긴 하지만, function내에서 struct/array처리시 구분해서 사용해야할 경우가 있다.
<Interface>
contract와 포맷이 동일한데, 내부함수에 body없음.
=> 다른 contract내의 함수를 호출할때 사용한다.
contract KittyInterface {
function getKitty(uint256 _id) external view returns (uint a);
}
<OpenZeppelin의 Ownable.sol> => 이걸 상속받으면 onlyOwner modifier로 간단히 owner제약.
owner 만 실행가능함.
//1. import ownable.sol, 2. 상속 (is Ownable) 3.아래처럼 사용
function setKittyContractAddress(address _address) external onlyOwner {
kittyContract = KittyInterface(_address);
}
onlyOwner와 같은 modifier에 인자도 추가 가능.
modifier aboveLevel(uint _level, uint _zombieId) {
require(zombies[_zombieId].level > _level);
_; //실행코드가 한줄은 필요..
}
<각종 시간>
1 minutes : 60 임 (초단위까지 네요)
5 minutes: 300
seconds
, minutes
, hours
, days
, weeks
, years
같은 시간 단위 또한 포함하고 있다네. 이들은 그에 해당하는 길이 만큼의 초 단위 uint
숫자로 변환되네. 즉 1 minutes
는 60
, 1 hours
는 3600
(60초 x 60 분), 1 days
는 86400
(24시간 x 60분 x 60초) 같이 변환
function fiveMinutesHavePassed() public view returns (bool) {
return (now >= (lastUpdated + 5 minutes));
}
<Payable>
function levelUp(uint _zombieId) external payable {
require(msg.value == levelUpFee);
zombies[_zombieId].level++;
}
//인출 코드 예제.
uint itemFee = 0.001 ether;
msg.sender.transfer(msg.value - itemFee);