728x90
오늘은 Solidity를 사용하여 토큰 판매를 위한 기본적인 스마트 컨트랙트를 작성하는 방법에 대해 배웠습니다. 이 컨트랙트는 사용자가 이더리움을 지불하고 토큰을 구매할 수 있도록 하고, 소유자는 자신이 받은 수익을 출금할 수 있는 기능을 포함합니다. 또한, 환율을 설정하고 추가 토큰을 발행하는 기능도 구현되어 있습니다.
pragma solidity >=0.4.22 <0.6.0; // Solidity 버전 설정 (0.4.22 이상, 0.6.0 미만)
contract SellToken {
/* 계좌별 잔액을 저장하는 매핑 (address -> 잔액) */
mapping (address => uint256) public balanceOf;
address payable public owner; // 스마트 컨트랙트 소유자 주소
uint public rate; // 토큰 환율 (1 ETH 당 몇 개의 토큰을 받을 수 있는지)
uint public totalSupply; // 총 토큰 공급량
uint public income; // ETH로 받은 수익
/* 초기 공급량을 설정하는 생성자 */
constructor (uint256 initialSupply) public {
owner = msg.sender; // 컨트랙트를 배포한 주소를 소유자로 설정
balanceOf[owner] = initialSupply; // 소유자에게 초기 공급량을 할당
rate = 1; // 기본 환율 설정 (1 ETH = 1 토큰)
totalSupply = initialSupply; // 총 공급량 설정
income = 0; // 초기 수익을 0으로 설정
}
/* 토큰을 전송하는 함수 */
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] > _value); // 송금자가 충분한 잔액을 가지고 있는지 확인
require(balanceOf[_to] + _value > balanceOf[_to]); // 오버플로우 방지
balanceOf[msg.sender] -= _value; // 송금자의 잔액 감소
balanceOf[_to] += _value; // 수신자의 잔액 증가
return true; // 전송 성공
}
/* 내부적으로 토큰을 판매하는 함수 (외부에서 직접 호출 불가) */
function sell(address _from, address _to, uint _value) private {
require(balanceOf[_from] > _value); // 판매자가 충분한 토큰을 보유하고 있는지 확인
require(balanceOf[_to] + _value > balanceOf[_to]); // 오버플로우 방지
balanceOf[_from] -= _value; // 판매자의 토큰 감소
balanceOf[_to] += _value; // 구매자의 토큰 증가
}
/* 사용자가 이더리움을 지불하고 토큰을 구매하는 함수 */
function buy () public payable {
uint pay = msg.value * rate / (10**18); // 지불한 이더리움을 토큰으로 환산
sell(owner, msg.sender, pay); // 소유자로부터 구매자에게 토큰 전송
income = income + pay; // 총 수익 증가
}
/* 컨트랙트의 수익을 소유자의 계좌로 출금하는 함수 */
function withdrawal() public isOwner {
uint out = income * (10**18); // 수익을 이더리움 단위로 변환
owner.transfer(out); // 소유자에게 출금
income = 0; // 수익 초기화
}
/* 토큰 환율을 변경하는 함수 (소유자만 호출 가능) */
function setRate(uint _rate) public isOwner {
rate = _rate;
}
/* 추가 발행: 소유자가 새로운 토큰을 발행하는 함수 */
function additionalIssue(uint _amount) public isOwner {
balanceOf[owner] += _amount; // 소유자의 잔액 증가
totalSupply += _amount; // 총 공급량 증가
}
/* 소유자만 실행할 수 있도록 제한하는 수정자 */
modifier isOwner() {
require(msg.sender == owner); // 호출자가 소유자인지 확인
_; // 조건이 충족되면 함수 실행
}
}
스마트 컨트랙트 개요
이번에 작성한 스마트 컨트랙트는 SellToken
이라는 이름을 가지고 있습니다. 이 컨트랙트는 다음과 같은 기능을 제공합니다:
- 사용자는 이더리움을 지불하고 토큰을 구매할 수 있습니다.
- 소유자는 토큰의 환율을 설정하고, 수익을 출금하며, 추가로 토큰을 발행할 수 있습니다.
- 사용자는 다른 주소로 토큰을 전송할 수 있습니다.
코드 분석
1. 변수와 상태 정의
mapping (address => uint256) public balanceOf;
address payable public owner;
uint public rate;
uint public totalSupply;
uint public income;
balanceOf
: 각 주소가 보유한 토큰의 잔액을 저장하는 매핑입니다.owner
: 스마트 컨트랙트의 소유자 주소입니다. 이 주소는 여러 기능(환율 설정, 수익 출금 등)을 관리합니다.rate
: 토큰과 이더리움 간의 환율을 정의합니다. 예를 들어, 1 ETH당 몇 개의 토큰을 받을 수 있는지 설정합니다.totalSupply
: 현재 발행된 총 토큰 수입니다.income
: 소유자가 받은 이더리움 수익을 추적하는 변수입니다.
2. 생성자 함수
constructor (uint256 initialSupply) public {
owner = msg.sender;
balanceOf[owner] = initialSupply;
rate = 1;
totalSupply = initialSupply;
income = 0;
}
- 생성자는 스마트 컨트랙트가 배포될 때 한 번만 실행됩니다. 여기서는 소유자에게 초기 토큰 수(
initialSupply
)를 할당하고, 환율을 기본값인 1로 설정합니다. msg.sender
는 이 스마트 컨트랙트를 배포한 주소로, 이 주소가owner
로 설정됩니다.
3. transfer
함수 (토큰 전송)
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] > _value);
require(balanceOf[_to] + _value > balanceOf[_to]);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
return true;
}
- 사용자가 다른 주소로 토큰을 전송할 수 있도록 하는 함수입니다.
- 전송하려는 주소(
_to
)와 전송하려는 금액(_value
)을 확인하고, 유효한 경우 잔액을 업데이트합니다. require
를 사용하여 예외 상황을 처리하고, 전송이 성공적으로 완료되면true
를 반환합니다.
4. sell
함수 (토큰 판매)
function sell(address _from, address _to, uint _value) private {
require(balanceOf[_from] > _value);
require(balanceOf[_to] + _value > balanceOf[_to]);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
}
- 이 함수는 토큰을 판매하는 기능을 처리하는 내부 함수입니다. 외부에서 호출할 수 없습니다.
- 판매자는 충분한 잔액을 가지고 있어야 하며, 구매자는 해당 금액을 받을 수 있는 충분한 잔액을 가질 수 있어야 합니다.
5. buy
함수 (토큰 구매)
function buy () public payable {
uint pay = msg.value * rate / (10**18);
sell(owner, msg.sender, pay);
income = income + pay;
}
- 사용자가 이더리움을 보내면서 토큰을 구매하는 함수입니다.
msg.value
는 전송된 이더리움의 양입니다. 이를 환율(rate
)에 따라 토큰 수로 변환하고, 이를 소유자로부터 구매자에게 전송합니다.- 구매한 토큰 수는
income
변수에 추가되어 추후 출금할 수 있게 됩니다.
6. withdrawal
함수 (수익 출금)
function withdrawal() public isOwner {
uint out = income * (10**18);
owner.transfer(out);
income = 0;
}
isOwner
라는 수정자가 추가된 이 함수는 소유자만 호출할 수 있습니다.- 수익(
income
)을 이더리움으로 환산하여 소유자에게 전송하고, 이후income
을 0으로 리셋합니다.
7. setRate
함수 (환율 설정)
function setRate(uint _rate) public isOwner {
rate = _rate;
}
setRate
함수는 환율을 설정하는 함수입니다. 이 함수는 소유자만 호출할 수 있습니다.- 환율을 설정하여 사용자가 보낼 이더리움에 대해 어떤 비율로 토큰을 받을지를 정합니다.
8. additionalIssue
함수 (토큰 추가 발행)
function additionalIssue(uint _amount) public isOwner {
balanceOf[owner] += _amount;
totalSupply += _amount;
}
- 소유자는 필요에 따라 토큰을 추가로 발행할 수 있습니다.
- 새로운 토큰이 소유자에게 할당되며, 총 공급량도 증가합니다.
9. isOwner
수정자
modifier isOwner() {
require(msg.sender == owner);
_;
}
isOwner
는 소유자만 특정 기능을 호출할 수 있도록 제한하는 수정자입니다.- 함수 앞에
isOwner
를 추가하면 해당 함수는 소유자만 호출할 수 있게 됩니다.
결론
이번에 작성한 SellToken
스마트 컨트랙트는 기본적인 토큰 판매 기능을 제공하는 컨트랙트입니다. 사용자는 이더리움을 지불하고 토큰을 구매할 수 있으며, 소유자는 환율을 설정하고, 수익을 출금하며, 추가 토큰을 발행할 수 있습니다.
이 코드를 통해 Solidity와 스마트 컨트랙트의 핵심 개념을 익히고, 간단한 토큰 판매 시스템을 구축하는 방법을 배웠습니다.
728x90
'Decentralization' 카테고리의 다른 글
블록체인 기반 투표 시스템 구현 (2) | 2025.03.17 |
---|---|
Win & Ubuntu CLI에서 Truffle 설정 및 스마트 계약 배포 가이드 (1) | 2025.03.17 |
Solidity 스마트 컨트랙트: SimpleAuction 경매 시스템 (1) | 2025.03.15 |
Solidity로 복권 스마트 컨트랙트 구현하기 (2) | 2025.03.15 |
Solidity로 간단한 인사말 스마트 계약 만들기 (2) | 2025.03.15 |