Solidity 03. Variables/Datatypes
변수를 어떻게 사용하는가?
- 멤버 변수들은 Storage 변수. 상태 변수이다.
- 파라미터들은 Memory 변수. 함수 리턴시 날라간다.
- 파라미터에 Storage를 지정하면? 참조가 된다?
integer와 string을 get/set 하는 예제
pragma solidity >=0.4.0 <0.6.0;
contract SimpleStorage {
uint storedData;
string storedNm;
function set(uint x) public {
storedData = x;
}
function setNm(string memory x) public {
storedNm = x;
}
function get() public view returns (uint) {
return storedData;
}
function getNm() public view returns (string memory ) {
return storedNm;
}
}
- 기본 자료형이 아닌 것은 저장소를 명시해 주어야 한다. string을 사용하는 부분에 memory 타입으로 명시함.
datatype
- 기본형
uint/int ; uint, int는 뒤에 256이 생략되어 있다. (u는 unsigned 의미)
uint8~uint256 ; 여기서 숫자는 비트수를 의미. 1바이트부터 32바이트까지 있다.
bool : true or false
byte : uint8과 같다고 생각하면 된다.
address : 20바이트 주소값
address payable : address타입인데 멤버함수가 있다. transfer, send.
address payable x = address(uint160(to));
enum State { Created, Locked, Inactive } ;
산술/비교/비트/논리 연산자는 C 와 같음. enum도 같다.
- 참조형
배열 : [] array
구조체: struct
0xffff ; int16(-1)
0x42 ; bytes1(0x42)
0x0003 ; uint16(0x03)
0x48656c6c6f2c20776f726c6421 ; string("Hello, world!") (without null)
address의 멤버
- balance ; 계정 주소에 있는 이더를 wei로 반환
- transfer(uint amount) ; 계정 주소(받는 사람 주소)에 있는 amount 금액을 송금. to.transfer(_amount)
- send(uint amount) returns (bool) ; 상동. 실패시 false 리턴. to_send(_amount)
- call(…) returns (bool) : 상동, 실패시 false 리턴. 가스량 조절 가능. to.call.value(_amount).gas(1000000)() . 리턴값을 확인하여 false이면 revert()로 롤백한다.
- delegatecall(…) returns (bool) : 다른 계약의 함수를 호출.
address x=0x123 ;
address myAddress = this ;
if (x.balance<10 && myAddress.balance>=10) x.transfer(10) ;
- send : low-level의 transfer임. (실패시 롤백없음). 리턴값(true/false)을 반드시 확인.
고정크기 바이트 배열
bytes1/bytes2/bytes3/… bytes32 : bytes뒤에 숫자를 붙인다. 바이트수를 의미.
byte : bytes1과 같다.
멤버
length : 고정된 길이를 반환. 읽기 전용.
bytes32는 32바이트까지만 담을 수 있다.
ex)
bytes2 b = “bac”
동적 크기 바이트 배열
bytes : 임의 길이의 원시데이터.
string : UTF-8 인코딩 문자열. 임의의 길이. 거의 무제한.(2^256 * 256 비트)
- 멤버로 length, push()가 있다.
- 작은 따옴표나 큰 따옴표 상관없다.
ex) bytes memory a = ‘aaaaaaaaaa’;
a.length ;
a.push(‘c’) ;
a.push(“C”) ;
a.push(“AB”) ; // error. byte[]라서 byte 하나만 push 가능.
문자열 리터럴
작은 따옴표, 큰 따옴표 둘 다 가능.
C랑 다르게 null terminated가 아니다. 보이는 문자 개수만큼만 메모리를 차지함.
\n, \xNN (16진수), \uNNNN (유니코드) 도 지원.
16진수 리터럴
hex"001122FF"
앞에 hex를 지정.
이중배열
uint [][5] : 주의할 점은 행과 열이 다른 언어와 반대임.
이것을 C로 보면 uint [5][] 이 된다.
- 웃긴건 접근할 때는 C처럼 행, 열 순으로 접근한다.
- 선언할 때랑 사용할 때랑 다르다니 문화충격이다.
uint[3][2] dArray ;
// row index는 0,1까지 가능. column index는 0,1,2까지 가능.
// C나 java로 치면 uint dArray[2][3] 으로 생각해야 함.
dArray[1][2] = 100 ; // last element.
dArray[2][2] = 100 ; // error.
dArray[0][3] = 100 ; // error.
function f(uint len) public pure {
uint[] memory a = new uint[](7) ;
bytes memory b = new bytes(len) ;
// a.length==7, b.length=len
a[6]=8 ;
}
function f() public pure {
g([uint(1), 2, 3]) ;
}
function g(uint[3] _data) pubilc pure {
}
[1,2,3] 은 uint8[3] memory 타입이다. array에 첫 번째 요소에 타입을 명시해 줄 수 있다.
- 고정 크기 배열을 동적크기 배열에 할당할 수 없다.!
uint8[] memory x = [uint8(1),2,3] ; // 에러
uint8[3] memory x = [uint8(1),2,3] ; // 가능.
uint[] dArray ;
dArray.push(2) ;
dArray.push(3) ;
- 삭제는 delete로 배열을 삭제한다.
- 일반 변수에 delete를 하면 초기값(0)으로 할당된다.
자료구조
struct 지원
struct Voter {
uint w ;
bool v ;
address dele ;
uint vote ;
}
Enum Types
enum State { Created, Locked, Inactive }
Type Conversion
- uint를 스트링으로 변환. 하나씩 바이트 단위로 ascii char로 변환한다.
function uintToString(uint v) constant returns (string str) {
uint maxlength = 100;
bytes memory reversed = new bytes(maxlength);
uint i = 0;
while (v != 0) {
uint remainder = v % 10;
v = v / 10;
reversed[i++] = byte(48 + remainder);
}
bytes memory s = new bytes(i + 1);
for (uint j = 0; j <= i; j++) {
s[j] = reversed[i - j];
}
str = string(s);
}
function uint2str(uint i) internal pure returns (string)
{
if (i == 0) return "0";
uint j = i;
uint length;
while (j != 0){ length++; j /= 10; }
bytes memory bstr = new bytes(length);
uint k = length - 1;
while (i != 0){ bstr[k--] = byte(48 + i % 10);
i /= 10;
}
return string(bstr);
}
- 타입 캐스팅은 타입을 함수처럼 사용하여 파라미터로 받는다.
- 32비트를 16비트로 타입 캐스팅시 하위 바이트(낮은 자리 값)만 가져온다.
- 예를 들면. uint32 a= 0x12345678 ; 이것을 uint16 b = uint16(a) ; 이렇게 하면 하위 바이트인 0x5678을 가져온다.
Mapping
contract Mappings {
struct User {
string name ;
string email ;
}
mapping(address => User) users ;
function addUser(string memory _name, string memory _email) public {
users[msg.sender].name = _name ;
users[msg.sender].email = _email ;
}
function getUser() public returns (string memory, string memory) {
return (users[msg.sender].name, users[msg.sender].email) ;
}
}
이더리움 단위
wei ; 가장 작은 단위
1000 배씩 올라간다.
kwei, mwei, gwei, micro, milli, ether
kether, mether, gether, tether
위 단위를 코드에 그대로 사용한다.
즉, 1 이더는 10**18 wei
시간 단위
second, minute, hour, day, week, year
블록 및 거래 속성
- block.blockhash(uint blockNumber) returns (bytes32) : 지정한 블록의 해시값을 리턴. (최근 256개 블록만 사용 가능)
- block.coinbase ; address 채굴자 계정 주소
- block.difficulty ; uint 현재 블록 난이도
- block.gaslimit ; uint 현재 블록의 가스 제한량
- block.number ; uint 현재 블록 번호
- block.timestamp ; uint 현재 블록의 타임스탬프
- msg.data ; bytes 호출 데이터
- msg.gas ; 남은 가스양
- msg.sender ; address 메시지를 보낸사람
- msg.sig ; bytes4 calldata의 첫 4바이트로 함수 식별자
- msg.value ; uint 메시지와 같이 보낸 wei
- now ; block.timestamp와 같다. (현재 시간을 의미하는 값은 아니다. 현재시간과 대략 비슷)
- tx.gasprice ; uint 거래의 가스가격
- tx.origin ; 거래 발신자 주소. (sender.address와 같을 수도 다를 수도 있다.)
- this ; 현재 계약
- selfdestruct(address) ; 현재 계약을 파기해 지정한 주소로 금액을 보냄
- suicide(address) ; 상동
예외 처리
- assert(bool condition) ; 조건이 실패하면 에러를 발생시킨다. (보통 내부에러)
- require(bool condition) ; 위와 같다. 입력값 체크시 사용. (보통 외부에러)
- revert() ; 에러가 발생하면 롤백을 시킨다.
기타 연산
- 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( data ) returns (bytes32) : 이더리움 sha3 (KECCAK256) 해시
- sha256
- sha3 ; keccak256과 동일
- ripecmd160(data) returns (bytes20)
- ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) return (address) : 타원곡선암호서명에서 공개키와 연결된 주소를 리턴
할당
- 복수 데이터를 할당 할 수 있다. 리턴도 복수개가 가능
- (x,y) = f() ;
- swap
- (x,y) = (y,x) ;
- 함수 파라미터를 이름대로 지정할 수 있다.
- f(3, 2) 대신 f({value:2, key:3}) 이렇게 사용. (파라미터 이름)
- new로 다른 계약을 만들 수 있다.
Author: crazyj7@gmail.com
'BlockChain' 카테고리의 다른 글
Solidity#2 HelloWorld (0) | 2019.12.06 |
---|---|
Solidity 0.4 vs 0.5 (0) | 2019.12.06 |
Windows Ethereum python module install error (0) | 2019.12.04 |
[ether02] 코인만들기 (0) | 2019.11.10 |
[ether01] solidity 맛보기 (0) | 2019.11.10 |