한빛미디어에서 소스코드를 발췌했음
//SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.4.11;
contract CrowdFunding {
// 투자자 구조체
struct Investor {
address addr; // 투자자의 어드레스
uint amount; // 투자액
}
address payable public owner; // 컨트랙트 소유자
uint public numInvestors; // 투자자 수
uint public deadline; // 마감일 (UnixTime)
string public status; // 모금활동 스테이터스
bool public ended; // 모금 종료여부
uint public goalAmount; // 목표액
uint public totalAmount; // 총 투자액
mapping (uint => Investor) public investors; // 투자자 관리를 위한 매핑
modifier onlyOwner () {
require(msg.sender == owner);
_;
}
/// 생성자
constructor (uint _duration, uint _goalAmount) {
owner = payable(msg.sender);
// 마감일 설정 (Unixtime)
deadline = block.timestamp + _duration;
goalAmount = _goalAmount;
status = "Funding";
ended = false;
numInvestors = 0;
totalAmount = 0;
}
/// 투자 시에 호출되는 함수
function fund() public payable {
// 모금이 끝났다면 처리 중단
require(!ended);
Investor storage inv = investors[numInvestors++];
inv.addr = msg.sender;
inv.amount = msg.value;
totalAmount += inv.amount;
}
/// 목표액 달성 여부 확인
/// 그리고 모금 성공/실패 여부에 따라 송금
function checkGoalReached () public onlyOwner {
// 모금이 끝났다면 처리 중단
require(!ended);
// 마감이 지나지 않았다면 처리 중단
require(block.timestamp >= deadline);
if(totalAmount >= goalAmount) { // 모금 성공인 경우
status = "Campaign Succeeded";
ended = true;
// 컨트랙트 소유자에게 컨트랙트에 있는 모든 이더를 송금
if(!owner.send(address(this).balance)) {
revert();
}
} else { // 모금 실패인 경우
uint i = 0;
status = "Campaign Failed";
ended = true;
// 각 투자자에게 투자금을 돌려줌
while(i <= numInvestors) {
if(!payable(investors[i].addr).send(investors[i].amount)) {
revert();
}
i++;
}
}
}
/// 컨트랙트를 소멸시키기 위한 함수
function kill() public onlyOwner {
selfdestruct(owner);
}
// 현재 얼마가 있는지 알기 위한 함수
function getBalance() view public returns(uint) {
return address(this).balance;
}
}
위 코드를 실행하고 싶을 경우 Remix IDE를 사용하면 된다.
블록체인에서 주소의 의미는 계좌와도 같다.
Bob 에게 1 eth를 송금하기 위해서는 Bob의 EOA(Externally Owned Account)를 알아야한다.
msg.sender
로 계약을 시도한 사용자의 address를 가져올 수 있다.payable
키워드를 붙이면 출금이 가능하게 된다. 최근 솔리디티에서는 payable
을 꼭 쓰지 않아도 되지만 안쓰는 경우 송금할 때는 type converting이 필요하다. (ex. owner.send() 함수)다른 언어의 생성자와 동일하다. 이전 코드에서는 function 클래스명
으로 생성자를 정의했지만 최근에는 constructor (param1, param2 ...) {...}
로 정의한다.
function kill() public onlyOwner {
selfdestruct(owner);
}
이 함수는 스마트 컨트랙트를 시작한 (이후에 변경된 경우 변경된 사람이 소유권을 가짐) owner 이외에는 실행 할 수 없다.
필드에 선언한 변수들 이외의 매개변수, 함수 내의 지역변수 등은 메모리 관리를 위해 storage
, memory
키워드를 붙여줘야 한다.
주로 파라미터에는 memory
키워드를 사용하고 지역 변수의 경우 storage
를 사용한다.
더 자세한 내용
다른 언어들의 map과 유사하지만 솔리디티에서는 key
의 타입을 A로 value
의 타입을 B로 지정하는 것이다