사과를 구매하고, 환불할 수 있는 아주아주 간단한 dApp을 구현해보겠다.
목차
- 디렉토리 구조
- truffle 백
- 프론트
- 메타마스크 연결
- 물건 사고, 환불해보기
디렉토리 구조
Truffle 배포하기
터미널 열고
npx ganache-cli
다른 터미널에
mkdir truffle
cd truffle
truffle init
truffle/contracts/AppleShop.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
contract AppleShop{
mapping (address => uint) myApple; //address를 넣어주면 uint(정수)값이 튀어나온다.
function buyApple() public payable{
// 사과 구매
//send, trnafer, call을 이용하여, 이더를 보낼때 Payable이라는 키워드가 필요함.
myApple[msg.sender] += 1;
// msg.send : 현재 함수를 호출한사람, 혹은 컨트랙트의 주소
}
function sellApple(uint _applePrice) public payable {
//모든 사과 환불
uint256 refund = myApple[msg.sender] * _applePrice; //가진 apple수 * apple가격
myApple[msg.sender] = 0; // 가진 사과 개수를 0으로 바꿔줌.
payable(msg.sender).transfer(refund);
}
function getApple() view public returns (uint){
return myApple[msg.sender];
// 내가 가진 사과 수 출력
}
}
이더를 보내는 3가지 방법
이더를 보내는 3가지 방법은 send, transfer, call 이 있다.
이 세가지는 각각의 특징이 있다.
1.send : 2300 gas를 소비, 성공여부를 true 또는 false로 리턴한다
2.transfer : 2300 gas를 소비, 실패시 에러를 발생
3.call : 가변적인 gas 소비 (gas값 지정 가능), 성공여부를 true 또는 false로 리턴
재진입(reentrancy) 공격 위험성 있음, 2019년 12월 이후 call 사용을 추천.
truffle/migrations/2_deploy.AppleShop.js
const AppleShop = artifacts.require('AppleShop');
module.exports = function (deployer) {
deployer.deploy(AppleShop);
};
truffle/truffle-config.js
devlopment 주석해제하기.
truffle 디렉토리 안에서
truffle migration
하면 배포가 끝난다. (프론트와 메인넷 통신을 통해 백에서 작성한 메서드를 사용할 수 있다.)
그러면, build디렉토리 안에 contracts가 생기는데,
리액트를 다운 받고 src안에 그 폴더를 복사해서 넣어준다.(편의를 위해)
프론트
create-react-app appleshop
npm install web3
appleshop/src/App.js
import React from "react";
import useWeb3 from "./Hook/useWeb3";
import AppleShop from "./components/AppleShop";
const App = () => {
const [web3, account] = useWeb3();
if (!account) return <>메타 마스크 연결하세요.</>;
return (
<div>
<h2>사과앱</h2>
<AppleShop web3={web3} account={account}></AppleShop>
</div>
);
};
export default App;
appleshop/src/components/AppleShop.jsx
import React, { useEffect, useState } from "react";
import AppleShopContract from "../contracts/AppleShop.json";
import Web3 from "web3/dist/web3.min";
const AppleShop = ({ web3, account }) => {
const [apple, setApple] = useState();
const [deployed, setDeployed] = useState();
const buy = async () => {
//send 작업
await deployed.methods.buyApple().send({
from: account,
to: "0xf525a9837Bb65dCE2572059206Cc9b7F77e6CBf9",
value: web3.utils.toWei("1", "ether"),
});
}; //사기
const sell = async () => {
const eth = web3.utils.toWei("1", "ether");
await deployed.methods.sellApple(eth).send({
from: account,
to: "0xf525a9837Bb65dCE2572059206Cc9b7F77e6CBf9",
});
}; //환불
useEffect(() => {
(async () => {
if (!web3) return;
const instance = await new web3.eth.Contract(
AppleShopContract.abi,
"0xf525a9837Bb65dCE2572059206Cc9b7F77e6CBf9"
);
const currentApple = await instance.methods.getApple().call();
setApple(currentApple);
setDeployed(instance);
})();
}, []);
return (
<div>
<div>사과 가격 : 1ETH</div>
<div>내가 가진 사과 : {apple}</div>
<button onClick={buy}>구매하기</button>
<div>사과 판매 가격</div>
<button onClick={sell}>환불</button>
</div>
);
};
export default AppleShop;
send안에 들어가는 to값은 CA이고 truffle migration을 하면 터미널에 ca값이 뜨는데, 그 값을 붙여넣어주면된다.
appleshop/src/Hook/useWeb3.jsx
메타마스크와 연결이 됐는지 확인 해준다.
import React, { useEffect, useState } from "react";
import Web3 from "web3/dist/web3.min";
const useWeb3 = () => {
const [account, setAccount] = useState(null);
const [web3, setWeb3] = useState(null);
useEffect(() => {
(async () => {
if (!window.ethereum) return;
const [address] = await window.ethereum.request({
method: "eth_requestAccounts",
});
setAccount(address);
const web3 = new Web3(window.ethereum);
setWeb3(web3);
})();
}, []);
return [web3, account];
};
export default useWeb3;
메타마스크 연결하기
가나쉬에서 만들어진 test계정 중 첫번째 private key를 메타마스크에 등록하고,
리액트를 npm run start하면, 연결하라는 알림이 자동으로 뜬다.
그때 계정을 선택하고 연결하면 됨.
결과
구매하기를 눌러보자.
확인을 누르면 사과 1개를 살 수 있다.(무려 1이더!)
확인을 누르자.
새로 고침해주면? 가진 사과의 수가 변했다.
이제 환불해보자.
확인 누르면?
환불이 아주 잘된 것을 확인할 수 있다.
'블록체인 > 스마트 컨트랙트' 카테고리의 다른 글
[Remix IDE] Opensea 마켓에 NFT 토큰 생성해서 올려보기 (0) | 2022.07.25 |
---|---|
[스마트 컨트랙트, open-zeppelin] 토큰 <-> 이더리움 스왑 구현해보기 (0) | 2022.07.22 |
[스마트 컨트랙트] 투표 dApp 만들어 보기 (0) | 2022.07.18 |
[truffle, 스마트 컨트랙트] 토큰 생성해보기 (0) | 2022.07.15 |
[ truffle, 스마트 컨트랙트 ] 솔리디티 event 사용해서 dApp 간단하게 구현해보기 (0) | 2022.07.14 |