[Web3] Solidity 문법 기초 2

Gunter·2024년 7월 25일
0

Web3

목록 보기
3/5

instance

인스턴스 : 주로 하나의 컨트랙트에서 다른 컨트랙트로 접근할 때 쓰임.

e.g) A와 B 컨트랙트가 있다고 가정하였을 때, B에서 A 함수나 변수로 접근하여 사용하고 싶다면 A 인스턴스를 만들어 B 컨트랙트 안에서 사용하면 됨

정의

컨트랙트 이름 인스터스의 이름 = new 컨트랙트 이름();

contract B{    
    A instance = new A();    
  }
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;

contract A{
    
    uint256 public a = 5;
    
    function change(uint256 _value) public {
        a = _value;
    } 


}

contract B{
    
    A instance = new A();
    
    function get_A() public view returns(uint256) {
        return instance.a();
    }
    function change_A(uint256 _value) public  {
        instance.change(_value);
    }    

}

B 컨트랙트에서 A 컨트랙트에 접근하여 변수 a와 change 변수 사용해보기.
A를 B 컨트랙트에서 인스턴스 화 하기.
접근할 때는 .을 붙여서 이동 e.g) instance.change(_value)
변수를 접글할 때는 ()을 붙여줘야 리턴이 됨

+) instance 는 A 스마트 컨트랙의 분신과 같은 존재.
즉 A를 따로 배포하고, 인스턴스 A를 스마트컨트랙트 B를 통해서 배포한다고 가정하였을때,
이 두개의 컨트랙트는 완전히 다르다.

그렇기 때문에, instance를 만들어서 변수 a의 값을 변경한다해도, 스마트컨트랙 A 자체만 따로 배포한곳에는 값에 영향을 주지가 않.

 


constructer (생성자)

constructer : 스마트 컨트랙트가 생성 또는 배포, 그리고 인스턴스화 될 때 초기값을 설정해주는 용도로 사용됨.

// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;

contract A{
    
    string public name;
    uint256 public age;
    
    constructor(string memory _name, uint256 _age){
        name = _name;
        age = _age;
    }
        
    function change(string memory _name, uint256 _age) public  {
         name = _name;
         age = _age;
    }
}

contract B{
    
  A instance = new A("Alice", 52);
  
  function change(string memory _name, uint256 _age) public  {
        instance.change(_name,_age);
    }
  
  function get() public view returns(string memory, uint256) {
        return (instance.name(), instance.age());
    }

}

A 컨트랙트에 constructor가 있음.
생성자를 통해서 파라미터를 받아, name과 age에 값을 넣어주고 있음.

컨트랙트 B에 "Alice", 52가 있는데 이것은 A를 인스턴스화 하기 위해서(생성하기 위해서) 필요한 초기 값.
get 함수 -> 여러개의 리턴을 하기에, returns 괄호 부분에 리턴하고자 하는 타입을 써줌
chagnge 함수 -> 컨트랙트 A의 change를 통해서, 생성자에서 설정한 age, name을 변경함을 알 수 있음.

 


상속

정의

상속 받을 컨트랙트 is 상속 주는 스마트 컨트랙트 {
       //....
}
// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;

contract Father{
    string public familyName = "Kim";
    string public givenName = "Jung";
    uint256 public money = 100; 
    
    constructor(string memory _givenName) public {
        givenName = _givenName;
    }
    
    
    function getFamilyName() view public  returns(string memory){
        return familyName;
    } 
    
    function getGivenName() view public  returns(string memory){
        return givenName;
    } 
    
    function getMoney() view public returns(uint256){
        return money;
    }
    

}

contract Son is Father("James"){
    
}

Son이 Father의 것을 상속받는데, 컴파일 후 배포를 하면 Father의 스마트 컨트랙트 변수와 함수들을 모두 받아서 사용이 가능하다.

Father에 constructor를 넣어 givenName으로,

상속 받을 컨트랙 is 상속 주는 스마트 컨트랙 (파라미터 쓰기) {
//....
}

이런식으로 파라미터를 넣어 줌으로써, 이름을 변경할 수 있다.

 

Overriding

overriding : 상속받은 함수를 다르게 변경 ( 상속받은 함수를 덮어 씌우기 )

 

// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;

contract Father{
    
    string public familyName = "Kim";
    string public givenName = "Jung";
    uint256 public money = 100; 
    
    constructor(string memory _givenName) public {
        givenName = _givenName;
    }
    
    
    function getFamilyName() view public  returns(string memory){
        return familyName;
    } 
    
    function getGivenName() view public  returns(string memory){
        return givenName;
    } 
    
    function getMoney() view  public virtual returns(uint256){
        return money;
    }
    
    
}

contract Son is Father("James"){
    
    
    uint256 public earning = 0;
    function work() public {
        earning += 100;
    }
    
     function getMoney() view  public override returns(uint256){
        return money+earning;
    }

}

getMoney 부분을 오버라이딩 하는데,

function getMoney() view  public virtual returns(uint256){
        return money;
    }

아버지 컨트랙트에 virtual을 명시해줘서, 자식 컨트랙트에서 오버라이팅을 할 것임을 알려줘야 함.

work 함수를 돌리면 earning 100씩 증가하고, getMoney를 누르면 아버지에게 받은 돈 money와 아들이 번 돈 earning이 합쳐져 아들의 재산을 보여줌.

 

+) 두 개 이상 상속 할 때

// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;


contract Father{
    uint256 public fatherMoney = 100;
    function getFatherName() public pure returns(string memory){
        return "KimJung";
    }
    
    function getMoney() public view virtual returns(uint256){
        return fatherMoney;
    }
    
}

contract Mother{
    uint256 public motherMoney = 500;
    function getMotherName() public  pure returns(string memory){
        return "Leesol";
    }
    function getMoney() public view virtual returns(uint256){
        return motherMoney;
    }
}


contract Son is Father, Mother {

    function getMoney() public view override(Father,Mother) returns(uint256){
        return fatherMoney+motherMoney;
    }
}

 


event

event : 블록체인 네트워크의 블록에 특정값을 기록하는 것

로그를 사용하여, 블록에 각인시키는 것은 일반적으로 string이나 다른 값들을 스마트 컨트랙트에 저장하는 것보다 효율적이다.

정의

event info(string name, uint256 money);
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0 <0.9.0;

contract lec13 {
   
    event info(string name, uint256 money);
    
    function sendMoney() public {
        emit info("Chae", 1000);
    }
}

logs 부분에 info 이벤트가 잘 나왔음을 확인 가능.
블록 안에 저장이 되었기에 언제든지 들고 와서 쓸 수 있음

 

indexed

indexed를 써줌으로써 블록들안에 출력된 이벤트들을 필터하여 저희가 원하는 이벤트만을 가지고 올 수 있다.

// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;

contract lec14  {
    event numberTracker(uint256 num, string str);
    event numberTracker2(uint256 indexed num, string str);

    uint256 num =0;
    function PushEvent(string memory _str) public {
        emit numberTracker(num,_str);
        emit numberTracker2(num,_str);
        num ++;
    }
}

필터를 하려고 하는 파라미터값에 indexed만 써주면 된다.

 


상속 - Super

// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;

contract Father {
    event FatherName(string name);
    function who() public virtual{
        emit FatherName("Spider");
    }
}

contract Mother {
    event MotherName(string name);
    function who() public virtual{
        emit MotherName("Gwen");
    }
}

contract Son is Father{
    event sonName(string name);
    function who() public override{
        super.who();
        emit sonName("me")
    }
}

son 컨트랙트는 father 컨트랙트의 who를 상속받아 오버라이딩 하는것을 볼 수 있다.
son 컨트랙트는, 아버지의 FatherName 이벤트를 그대로 유지하고, 자신의 sonName 이벤트를 추가했다.

만약, Son 컨트랙트 부분의 오버라이딩한 함수 who 안에 단순히 FatherName 이벤트 한 줄만 쓰는게 아니고, 여러줄의 코드를 써야할 때, 매우 번거로워진다.
이 때 super를 쓰면, 그대로 Father 컨트랙트의 이벤트를 들고 올 수 있다.

 

+) 상속의 순서

// SPDX-License-Identifier:GPL-30
pragma solidity >= 0.7.0 < 0.9.0;
contract Father {
    event FatherName(string name);
    function who() public virtual{
        emit FatherName("spider");
    }
}
contract Mother {
    event MotherName(string name);
    function who() public virtual{
        emit MotherName("gwen");
    }
}
contract Son is Father, Mother{    
    function who() public override(Father,Mother){
        super.who();
    }
}

Son 이라는 스마트컨트랙은 Father 와 Mother를 상속받앗다.
who 함수에 오버라이딩을 하여서, super.who() 를 해줌.

그러면 여기서 Father 와 Mother 누구의 것이 상속이 될까요?

정답은 Mother의 것이 상속되어서 gwen 이 반환됩니다.

왜 Father 이 아니라 Mother 인걸까요?

정답은 Son is Father , Mother 이기 때문. 즉 Mother 두번째 (최신) 으로 상속 받았기에 그렇다.

0개의 댓글