3. 솔리디티 스마트 계약 이론


3.1. Contract 의 구조

클래스와 비슷, 자바스킄립트와 비슷

타입을 구분할 수 있고

컨트랙트끼리 상속할 수 있다 객체지향처럼

pragma solidity ^0.4.23;
//solidity 컴파일러 버전

//키워드 이름 
contract MyContract {
    uint count; //상태변수
    //컨ㅌ랙 저장소에 영구히 저장된다. 


    constructor() public {
        //생성자, 키워드 + public
    }

    //구조 자바스크립트 ++ 자바 느낌 
    function numOfStudents(address _teacher) public view returns(uint){
            //함수이름     ( 매개변수       )   함수타입        리턴타입
    }
}

3.2. 접근제어자

함수와 상태변수에 쓸 수있는 4가지 가시성이 존재한다

가시성(Visibility)설명
external1. 외부 컨트랙만 호출 가능/
 2. 상태변수는 external 사용 불가
internal1. 컨트랙 내부 호출 가능
 2. 상속받은 컨트랙트도 호출 가능
 3. 상태변수는 디폴트로 internal 선언
public1. 컨트랙 내부 호출 가능
 2. 상속받은 컨트랙트도 호출 가능
 3. 외부 컨트랙트도 호출 가능
private1. 컨트랙 내부만 호출 가능

external

pragma solidity ^0.4.23;

contract MyContract{
    //ERROR
    uint external count;
    //external 붙일 수 없다. 
    constructor() public {

    }

    function numOfStudents(address _teacher) public view returns(uint) {
        //ERROR
        test();
        //external 이 붙은 함수를 같은 컨트랙트에서 부를 수 없음
    }

    function test() external{

    }
}

contract YourContract {
    MyContract myContract;
    //myContranct 를 선언한뒤 

    function callTest() public {
        myContract.test();
        //외부 컨트랙트에서 호출 가능
    }
}

internal

pragma solidity ^0.4.23;

contract MyContract{
    uint count;
    //default 는 internal

    constructor() public {

    }

    function numOfStudents(address _teacher) public view returns(uint) {
        test();
    }

    function test() external{

    }
}

contract YourContract is MyContract{
    //YourContract 가 MyContract를 상속받음
    //~~. 의 접근제어자 없이 바로 사용가능 
    function callTest() public {
        test();
    }
}

public

pragma solidity ^0.4.23;

contract MyContract{
    uint public count;
    //PUBLIC은 자동적으로 변수의 getter함수를 만들어준다. 

    constructor() public {

    }

    function numOfStudents(address _teacher) public view returns(uint) {
        test();
    }

    function test() public{

    }
}

contract YourContract is MyContract{
    //YourContract 가 MyContract를 상속받음
    //~~. 의 접근제어자 없이 바로 사용가능 
    function callTest() public {// DEFAULT : PUBLIC
        test();
    }
}

contract HisContract {
    MyContract myContract;

    function callTest() public {
        myContract.test();
    }
}

private

pragma solidity ^0.4.23;

contract MyContract{
    uint public count;
    //PUBLIC은 자동적으로 변수의 getter함수를 만들어준다. 

    constructor() public {

    }

    function numOfStudents(address _teacher) public view returns(uint) {
        test();
        //같은 컨트랙트 내에서만 부름 
    }

    function test() private{

    }
}

contract YourContract is MyContract{
    function callTest() public {// DEFAULT : PUBLIC
        //ERROR
        test();
    }
}

contract HisContract {
    MyContract myContract;

    function callTest() public {
        //ERROR
        myContract.test();
    }
}

3.3. 함수 타입 제어자

종류설명
view1. 데이터 read-only
 2. 가스 비용 없음
pure1. 데이터 읽지 않음
 2. 인자값만 활용해서 반환 값 정함
 3. 가스 비용 없음
constant0.4.17 버전 이전에는 view/pure 대신 쓰임
payable1.함수가 eth를 받을 수 있게 함
 2. 가스 비용 있음

view

uint nuOfStudents;

function getNumOfStudents() public view returns (uint) {
    return numOfStudents;
    //view 가 붙으면 수정/삭제는 못한다. 
}

pure

블록체인에 저장된 데이터를 불러오는 것으로 쓸 수 없다.

즉, 인자값만 활용해서 리턴한다.

function multiply(uint x, uint y) public pure returns(uint) {
    return x* y;
}

constant

view  pure   권장됩니다. 

payable

function buy() public pyable {
    require(1000 = msg.value);//송신자가 보넨 웨이
    transferEther(msg.sender);
}

3.4. 값 타입

Boolean 형

bool x = false 이렇게 사용

정수형

int == int256

uint==yint256

둘 다 8 ~256bits

int32 x -27462;

uint256 x = 24557867;

uint256 쓰면 여기에 담을 수 있는 숫자의 사이즈는 2^256 인것!

(default 256)

주소형

타입 : address

값 : 20byte 값 이더리움 계정 주소

추가 설명 : 두 개의 멤버 소유 balance, transfer

0x제외하면 40개 (이더리움 주소 길이)

Ex :

address x = 0x123;

function send public {
    if(x.balance <10){
        x.transfer(10);
    }
}

고정된 크기의 byte 배열

  • 타입 : bytes
  • 값 : 1~32 byte (사이즈를 지정해서 사용)
  • byte ==bytes1
  • EX)
  • bytes32 x = “hello world!”; (문자열 저장가능 사실 hex로 젖ㅇ)

동적인 크기의 byte 배열

bytes/string

  • 값 : 무한
  • 추가설명 : 값타입이 아니다!

열거형

enum

  • 값 : [value, value2]
  • 추가설명 : 값을 정수형으로 리턴
  • ex
enum Direction{ Right, Left}
Direction direction;

function getDirection() public returns (uint) {
    return uint(direction);
}
function setDirection(uint newDirection) public {
    direction = Direction(newDirection);
}

3.5. 참조 타입 : 데이터 위치

종류설명
storage1. 변수를 블록체인에 영구히 저장(ex: 하드디스크)
 2. 디폴트로 상태변수는 storage
memory1. 임시 저장 변수 (ex : RAM)
 2. 디폴트로 매개변수와 리턴 값은 memory
contract MyContract {
    uint[] ages;// 컴파일러가 자동으로 storage 라고 인식한다. 상태변수디폴트
	
    //매개변수로 넘겼을때는 저장위치를 memory를 쓴다. 
    //함수가 종료되면 값들이 휘발된다. 
    //매개변수로 받은 newAges 값이 들어간다. 
    function learnDataLocation(uint[] newAges) public returns (uint a) {
        ages = newAges;	// 복사 ages 배열 안에 newAges 로 받은 거랑 
        				//이 경우 memory 에서 storage(블록체인에 저장)
        uint16 myAge = 44;	//uint 나 boolean 같은 경우 저장 위치가 디폴트로 메모리!!
        					//함수가 끝나면 날라갑니다. 
        uint[] studentAges = ages;	//배열이 함수 안에 선언되었을때 디폴트로 storage !!!!!
        //값 타입은 memory,  배열은 로컬변수로 쓰일 때 storage
        //studentAges는 ages를 가리키는 포인터가 된다. 

        studentAges[0] = myAge;	// studentAges 배열의 첫번쨰 인덱스를 44로 바꿈 
        						
        a = studentAges[0];

        return a; //a는 메모리이기 때문에 종료되면서 사라진다. 
    }
}

3.6. 참조 타입 : 배열

종류설명ex
정적 배열사이즈가 고정uint[s] fixedArray
동적 배열사이즈가 무한대uint[] dynamicArray
contact MyContract {
    uint[] myArray;
    function learnArrays() public {
        uint256[] memory a = new uint256[](5);
        bytes32[] memory b = new bytes32[](10);
        
        a[0] = 1; //  a 배열 첫 번째 인덱스 숫자 1 입력
        a[1] = 2; //  a 배열 두 번째 인덱스 숫자 2 입력
        
        uint8[3] memory c= [1,2,3];
        // 함수 안에서 리터럴통해 배열 초기화 할 때 저장위치 memory
        
        //ERROR
        uint8[3] d = [1,2,3];
        //리터럴 통해 초기화 하는데 저장위치 memory 안써줘서 에러 
        
        myArray.push(5);
        uint myArrayLength = myArray.length;
    }
}

3.7. 참조 타입 : 구조체

struct : 필요한 자료형들을 가지고 새롭게 정의하는 사용자 정의 타입

 contract MyContract {
     struct studentName{
         string studentName;
         string gender;
         uint age;
     }

     Student[] students;

     funciton addStudent(string _ name, string _gender, uint _age) public {
         students.push(Student(_name, _gender, _age));
         // student 상태변수 배열에 새로운 Student 입력   
         
         Student storage updateStudent = students[0];
         // storage 에 저장하는 새로운 Student 선언
         // 상태변수 students 배열의 첫 번째 인덱스 값을 대입
         // "storage" 로 선언했기 때문에 상태변수를 가르키는 포인터 역할

         updateStudent.age = 55;
         //updataStudent age 필드를 55로 변경
         // 결과적으로는 상태변수 students 배열의 첫 번째 이ㅣㄴ덱스의 age 필드를 55 로 변경한다. 

         Student memory updateStudent2 = students[0];
         // memory 에 저장하는 새로운 Student 선언
         // 상태변수 students 배열의 첫 번째 인덱스 값을 대입
         // memory 로 선언됐기 때문에 복사한다. 

         updateStudent2.age = 20;
         //updateStudent2의 age 필드를 20으로 변경
         // 이 경우는 복사된 updateStudent2의 age 의 값이 변경된다. 

         students[0] =updateStudent2;
         //memory 배열으 ㅣ값을 상태변수에 직접적으로 대입해주면 
         // students 값 영구히 변경 

     }
 }

3.8. 참조 타입 : 매핑

mapping(_KeyType => _ValueType)

  • Key & Value 를 쌍으로 저장하는 자바의 Map과 비슷
  • KeyType : 동적 배열, 열거체, 구조체, 매핑타입 제외 다른 타입들 다 가능
  • ValueType : 매핑 포함 다른 타입 다 가능
contract MyContract {
    mapping(address =>uint256) balance;
    //매핑키워드로 주소형을 양수형으로 변수이름은 balance
    //어떤 이더리움 계정의 양수값이 블록체인 안에 존재한다. 
    function learnMapping() public {
        balance[msg.sender] = 100;
        balance[msg.sender] += 100;
        // balance 상태변수
        // msg.sender : 현제 이 함수를 불러오는 계정 주소
        // 
        
        uint256 currentBalance = balance[msg.sender];
    }
}
contract MyContract {
    struct Student {
        string studentName;
        string gender;
        uint age;
    }

    mapping(uinnt256 => Student) studetInfo ;

    function setStuddentInfo(uint _studenntId,string _name, string _gender, uint _age) public {
        Student storage student = studentInfo[_studenId]];
        // 키 값으로 매개변수로 받은 _studentId(예 : 1234) 입력
        // 1234 키 값만의 특정 Student 구조체 정보를 불러온다. 

        student.studentName = _name;
        student.gender = _gender;
        studnet.age = _age;
        // 각각 필드에 매개변수로 받은 자료형을 대입 
    }

    function getStudentInfo(uint256 _studentId) view public returns (string, string, uint) {
        //설명 매개변수로 받은 studnetId 를 키값으로 활용하여 1234에 매핑된 value 값인 Student 를 불러온다. 
        return (studentInfo[_studentId].studentName, studnetInfo[_studentId].gender, studentInfo[_studnetId].age);
    }
}





© 2018. by yoonhoi Jeon

Powered by zzsza