[SpeedRunEthereum] Challenge 1[Decentralized Staking App]
challenge 1은 스테이킹 앱을 만들어보는 것입니다.
Checkpoint 1: Environment
challenge 0처럼 템플릿 프로젝트를 받고 로컬 네트워크, 리액트, 디플로이를 해줍니다.
git clone https://github.com/scaffold-eth/scaffold-eth-challenges.git challenge-1-decentralized-staking
cd challenge-1-decentralized-staking
git checkout challenge-1-decentralized-staking
yarn install
//terminal 1
yarn chain
//terminal 2
yarn start
//terminal 3
yarn deploy
Checkpoint 2: Staking
Staker.sol 에서 지갑별로 스테이크한 금액을 저장해둘 맵핑과 최대치를 선언해줍니다.
mapping(address => uint256) public balances;
uint256 public constant threshold = 1 ether;
stake함수를 작성합니다.
function stake() public payable {
require(balances[msg.sender].add(msg.value)<= threshold);
balances[msg.sender] = balances[msg.sender].add(msg.value);
emit Stake(msg.sender, msg.value);
}
프론트에 접속해 stake 함수로 금액을 전송해 event와 금액이 정상적으로 전송되었는지 확인해봅니다.
컨트랙트 지갑의 잔고, 개인 주소에 저장되어 있는 금액, 이벤트 내역까지 확인할 수 있습니다.
Checkpoint 3: State Machine / Timing
데드라인을 생성합니다. 시간은 컨트랙트 배포 시간 + 30초로 지정합니다.
uint256 public deadline = block.timestamp + 30 seconds;
deadline이 지난 후에 실행 가능한 execute 함수를 작성합니다.
execute함수는 컨트랙트 지갑의 잔고가 임계치(1 ether) 이상이라면 exampleExternalcontract.complete{value: address(this).balance}();를 호출하고 아니라면 openForWithdraw를 true로 하여 모든 사용자가 출금할 수 있게 합니다.
bool public openForWithdraw;
function execute() public deadlineExpire {
if (address(this).balance >= threshold) {
exampleExternalContract.complete{value: address(this).balance}();
}else{
openForWithdraw = true;
}
}
function withdraw() public payable {
require(openForWithdraw);
uint256 val = balances[msg.sender];
require(val >= msg.value);
balances[msg.sender] = val.sub(msg.value);
msg.sender.call{value: msg.value}("");
}
deadline까지 시간이 얼마나 남았는지를 반환하는 timeLeft 함수를 작성합니다.
function timeLeft() public view returns (uint256) {
return (block.timestamp < deadline) ? deadline - block.timestamp : 0;
}
Checkpoint 4: Receive Function / UX
컨트랙트에 직접 이더를 전송할 경우에도 대응 가능하게 receive 폴백 함수를 작성합니다.
receive() external payable {
stake();
}
Checkpoint 5: 배포 / 프론트
challenge 0에서 한 것처럼 설정 변경 후 배포합니다.
1. hardhat.config.js 에서 localnetwork 변경
2. yarn generate로 menemonic 생성
3. yarn deploy
4. App.jsx 에서 targetNetwork 변경
5. yarn build
6. yarn surge
배포된 컨트랙트를 확인하려면
package.json의 verify에 이더스캔 api키를 적어준 후
터미널에서 다음과 같이 입력합니다.
yarn verify --network your_network