[솔리디티] 기초 문법 - 2

근상·2025년 1월 7일

솔리디티 기초

목록 보기
3/7

전 포스트에서

기본적인 값 자료형에 다뤄봤다.

이번시간도 자료형이지만
참조 자료형에 대해 알아보자.


Struct & Constructor()

가장 먼저 Struct 변수, 구조체에 대해
그리고 constructor()까지 알아보자.

// 기본적인 Struct 구조는 이와 같다.
// 가장먼저 선언을 하고 그 안에 value형 변수들을 넣는다.

contract Ex{

	struct Product {
    	string name;
        uint256 price;
    }
    
    // 이렇게 구조체를 선언했으면 이 구조체 해당 변수는 일반 변수 선언 형태로 선언한다.
    Product public mainPd;
    
    // 하지만 네트워크에 배포할 때 초기값 설정을 위한 constructor()도 있다.
    // 이는 초기 배포시에만 동작하고 그 뒤에는 사용되지 않는다.
    //처음에 세팅하고 바뀔 수 없는 값들을 세팅할 때 사용한다.
    
    uint256 public pd1Price;
    
    constructor(uint _mainPdPrice) {
    	mainPdPrice =  _mainPdPrice);
    }
    
    // 구조체 필드 선언
    
    // 방법1 
    function initProduct() public {
    	Product memory firstPd;
        firstPd = Product("pd1", 10);
    }
    
    //방법2
    function setMainPd(string _name, uint256 price) public {
    	mainPd.name = _name;
        mainPd.price = _price;
    }
    
    function getMainPdPridce() public view returns(uint256) {
    	return mainPd.price
    }
    
   
}

enum

그 다음은 enum이다.

사용 경우는 컨트랙트의 진행 상태같은 것을 볼 때 사용한다.
유저나 개발자가 명확히 이해하도록 한다.

//(생략)

contract Ex{

	//여기에는 변수가 아니라 실제로 들어갈 데이터를 넣는다.
    // 경매로 예를 든다.
	enum Status {
    	Not sale,
        Auction,
        Sales,
        Bid,
        Sold
    }
    
    //경매 상태 변수를 선언한다.
    Status public auctionStatus;
    
    // enum의 Auction필드를 통해 경매 시작을 알아낸다.
    function auctionStart() public{
    	auctionStatus = Status.Auction;
    }
    
    // 팔렸는지 보고싶다면
    function sold() public {
    	auctionStatus = Status.Sold;
    }
    
    // 이렇게 직관적으로 확인하고 싶을 때 enum이라는 자료형을 사용한다.
    // 코드의 가독성 향상을 위해 사용된다.
}

List

프로그래밍 중 또 가장 중요한 요소인 배열이다.
솔리디티에서 어떻게 사용되는지 알아보자

contract Ex{
	
    uint[] public uintList = [1, 2, 3, 4] //이런식으로 사용한다.
    uint[4] public uint4List = [1, 2, 3, 4] // 개수를 미리 정함.
    
    // 리스트 응용 메서드
    // 하지만 이 경우에는 리스트가 동적할당 돼야하고
    // 메서드를 함수 안에서 사용할 수 있다.
    
    // 1. 배열끝에 요소 추가할 경우
    function addToArray() public {
         uintList.push(5); // [1, 2 ,3 ,4, 5]
    }
    
    // 2. 요소 제거하는 경우
    function popToArray() public view returns(uint) {
    	uint num = uintList.pop();
        return num;
        
        // pop()은 요소를 제거하며, 그 값을 리턴한다.
        // 결과 [1, 2, 3, 4]
    }
    
    // 3. 요소 조회
    // 조회만 할 뿐 리스트 자체에 영향을 주지 않는다.
    
    int public secondData = intList[1]; // 2
    
    // 4. delete 이용
    // [1, 2, 3, 4]의 리스트에서 2라는 값을 지우고 싶다면
    
    function removeElement(uint index) public {
        delete intList[index];  // 인덱스의 값을 0으로 초기화, 완전 소거 X
    }
    
    
    // Struct형태도 동일함.
    
    Struct Product {
    	string name;
        uint256 price;
    }
    
    Product public mainPd;
    Product[] public pdList;
    pdList.push(mainPd);
    // 이런식으로 구조체 배열 선언과, push()함수 이용이 가능하다.
}

Mapping

mapping 키워드 자주 쓴다.
key-value 형태이며
주로 잔액 조회에 자주 이용된다.
이때 키는 사용자 주소고 밸류는 잔액이 될 수 있다.

contract Ex{
	mapping(address => uint256) public balance;
    
    // 그래서 key값이 중복 발생이 일어나지 않음.
    
    // mapping 형태 변수 선언은 다음과 같이 한다.
    // 주소는 임의로 이더스캔에서 하나 갖고옴.
    
    balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"] = 1000;
   
    // 잔액을 조회한다면
    uint256 myBalance = balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"]; // 잔액: 1000
   
    
    // 동일한 키에 대응하는 다른 값을 입력하면 업데이트되는 형식이다.
    balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"] = 10;
    myBalance = balance["0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5"]; // 잔액 : 10
    
    // 다른 주소를 넣게되면
    balance["0x73f7b1184B5cD361cC0f7654998953E2a251dd58"] = 50; // 새로운 이 주소에 대한 잔액이 추가된다.
    
    // 결국 중복이 발생하지 않는다.
    // 같은 키면 업데이트가 되는 방식이기 때문이다.
}

변수 중복

변수가 중복될 때 어떻게 동작하는지 보자.
컨트랙트 배포와 함수 호출은 따로 권한다.

contract Ex {
	uint private data = 10; // 상태 변수로 Storage에 저장된다.
    
    // 상태 변수를 처리하기 때문에 view를 사용해 값을 리턴한다.
    function fn1() public view returns(uint){
    	return data; //10
    }
    
    // 지역 변수를 사용하기 때문에 pure를 사용해 값을 리턴한다.
    function fn2() public pure returns(uint){
    	uint8 data = 5;
        return data; // 5
    }

	// 변수가 중복될 때 지역 변수의 값으로 리턴된다.

}

주소 형태

주소에도 형태가 있다.

contract Ex{
	
    address public failUser = 0xfca28ad8fca6033e37303f94fe0120c61f62fe41f0c7ad8c4f3fe4e0472cb1d0;
    address public user = 0x73f7b1184B5cD361cC0f7654998953E2a251dd58;
    
    // 소문자로만 된 주소와, 대소문자가 섞인 주소가 있다.
    // 이대로 remix에서 컴파일을 진행하면
    // 오류가 뜬다.
    // 어카운트 checkSum이 failUser는 진행되지 않아서 솔리디티에서 사용할 수 없다.
    // 그래서 항상 솔리디티에서 주소를 사용할 때 checkSum을 거친 데이터만 사용할 수 있다.
   
}

Payable

말 그대로 돈과 관련있는 키워드다.

contract Ex{
	
    // 이더를 주고 받는 CA, EOA는 컨트랙트 상에 payable을 명시해야 한다.
    // 함수 또한 마찬간지다.
    
    address public user = 0x73f7b1184B5cD361cC0f7654998953E2a251dd58;
    
    address payable public payable_user = payable(user);
    
    // 간단한 이더 전송 함수다. payable에 집중하자.
    function sendETH() public payable{
    	// user.transfer(10**18); 이것은 오류댜 왜냐하면 user선언시 payable넣지 않음
        payable.user.transfer(10**18); // 잘 전송된다.
    }
    
    // address 타입 특징으로 바로 잔액을 구할 수 있다.
    function getBalanceETH() public view returns(uint256){
    	return user.balance;
    }
}

This

이 키워드는 해당 컨트랙트를 가릴킬 수 있다.

contract Ex{

	uint public data = 5;
	
    // 이 해당 컨트랙트의 잔액을 구하고 싶다면
    
    function getBalance() public view returns(uint256) {
    	return address(this).balance;
    }
    
    function externalFunc() external {
    	data = 15;
    }
    
    function internalFunc() internal {
    	// 이 함수 내부에서 externalFunc()를 호출하면 에러가 발생한다.
        // externalFunc(); => Error!!!!
        // 그렇다면 this를 이용한다.
        
        this.externalFunc()
    }
}

또 이렇게 다양한 형태의 자료형을 살펴봤다.


시리즈

  1. 값 자료형
  2. 현재
  3. 블록 & 트랜잭션
  4. Modifier & Error Handling
  5. 컨트랙트 상속
  6. 컨트랙트 호출

0개의 댓글