# 4. Write Smart Contract

1. Background
2. Define the variable
3. Define functions
4. Let's do something more\
   4.1. Add a variable \ 4.2. Update functions

## 1) 배경지식 <a href="#id-1-background" id="id-1-background"></a>

"Count"라는 매우 간단한 컨트랙트를 만들 거에요.

a. `count`라는 스토리지 변수가 하나만 있습니다.\
b. 사용자는 `count` 변수를 1씩 늘리거나 줄일 수 있습니다. 따라서 `count` 변수를 1만큼 증가시키는 `plus` 함수와 `count` 변수를 1만큼 감소시키는 `minus` 함수, 총 2개의 함수가 있습니다. 참 쉽죠?

## 2) 변수 정의 <a href="#id-2-define-the-variable" id="id-2-define-the-variable"></a>

변수를 설정하기 전에 솔리디티 버전을 지정해야 합니다. 0.5.6 stable 버전을 사용할게요.

```
 solidity 0.5.6; // 솔리디티 버전을 지정합니다.
```

그런 다음 컨트랙트의 이름을 "Count"로 지정합니다.

```
pragma solidity 0.5.6;

contract Count { // 컨트랙트의 이름을 "Count"로 합니다.

}
```

`count` 변수를 `uint`(unsigned integer) 자료형으로 선언하고 0으로 초기화하세요.

```
pragma solidity 0.5.6;

contract Count {
  uint public count = 0; // Declare count variable as uint type and initialize its value to 0.
}
```

## 3) 함수 정의 <a href="#id-3-define-functions" id="id-3-define-functions"></a>

`plus`와 `minus` 두 개의 함수가 필요해요. 각 함수의 역할은 다음과 같습니다:\
`plus` - `count` 변수를 1만큼 증가. (count = count + 1)\
`minus` - `count` 변수를 1만큼 감소. (count = count - 1)

```
pragma solidity 0.5.6;

contract Count {
  uint public count = 0;

  function plus() public { // 'plus'라는 이름의 public 함수를 작성합니다.
    count = count + 1; // 'plus' 함수는 count 변수를 1씩 증가시킵니다.
  }

  function minus() public { // 'minus'라는 이름의 public 함수를 작성합니다.
    count = count - 1; // 'minus' 함수는 count 변수를 1씩 감소시킵니다.
  }
}
```

*NOTE*\
컨트랙트 외부에서 함수를 호출하려면 `public`으로 선언해야 합니다.

```
function plus() public { … }
```

## 4) Let's do something more <a href="#id-4-let-s-do-something-more" id="id-4-let-s-do-something-more"></a>

기능 하나만 더 추가해볼까요? 마지막 참가자의 지갑 주소를 기억하는 기능은 어때요?

### 4-1) 변수 추가 <a href="#id-4-1-add-a-variable" id="id-4-1-add-a-variable"></a>

`lastParticipant` 변수를 `address` 자료형으로 선언해주세요:\
`address public lastParticipant;`

```
pragma solidity 0.5.6;

contract Count {
  uint public count = 0;
  address public lastParticipant;

  function plus() public { // 'plus'라는 이름의 public 함수를 작성합니다.
    count = count + 1; // 'plus' 함수는 count 변수를 1씩 증가시킵니다.
  }

  function minus() public { // Make a public function called 'plus'
    count = count - 1; // 'minus' function decreases count variable by 1.
  }
}
```

### 4-2) 업데이트 함수 <a href="#id-4-2-update-functions" id="id-4-2-update-functions"></a>

마지막 참가자의 주소를 추적하기 위해 `lastParticipant`에 다음과 같이 주소를 저장합니다.

```
pragma solidity 0.5.6;

contract Count {
  uint public count = 0;
  address public lastParticipant;

  function plus() public {
    count = count + 1;
    lastParticipant = msg.sender; // msg.sender의 값을 lastParticipant에 저장합니다.
  }

  function minus() public {
    count = count - 1;
    lastParticipant = msg.sender; // msg.sender의 값을 lastParticipant에 저장합니다.
  }
}
```

*참고*\
1\) `public` 변수 또는 함수를 `public`으로 선언했다면 블록체인 외부에서 접근할 수 있습니다. 즉 프론트엔드 어플리케이션에서 해당 변수 또는 함수에 접근할 수 있습니다. 나중에 [Count 컴포넌트](https://archive-ko.docs.klaytn.foundation/content/dapp/tutorials/count-dapp/5.-frontend-code-overview/5-3.-count-component) 장에서 어떻게 프론트엔드 애플리케이션으로부터 컨트랙트의 public 메서드 및 변수와 상호작용할 수 있는지 볼게요.

2\) `msg.sender`\
`msg.sender`는 현재 트랜잭션을 시작한 주소입니다.\
`msg.sender` 변수를 통해 트랜잭션 발신자의 주소를 얻을 수 있습니다.

```
lastParticipant = msg.sender;
```

이 줄은 `lastParticipant` 변수가 `msg.sender`의 주소 값을 갖도록 합니다.
