payable (23/05/30)

nazzzo·2023년 5월 30일
0

payable


솔리디티의 payable은 두 종류로 나뉩니다

// address payable
payable(address);
address payable public owner;


// function payable
function sellItem() external payable {}

  • address payable은 주소의 타입을 지정하는 것을 뜻합니다
    해당 주소에는 이더를 송금할 수 있는 기능(transfer()send() 함수)이 내장됩니다
  • function payable은 함수의 속성을 지정합니다
    그리고 이렇게 payable을 선언한 함수에서만 이더를 보낼 수 있습니다
    즉, 컨트랙트에서 payable로 선언된 함수는 외부에서 호출될 때 이더를 전송하는 기능을 수행할 수 있게 됩니다

간단한 마켓 기능을 구현해보면서 두 payable 속성을 이해해봅시다

[appleShop.sol]

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract AppleShop {
    // myApple[key] = value, 기본값 0이 할당됩니다
    mapping(address=> uint256) myApple;

    function buy() public payable {
        myApple[msg.sender] += 1;
    }
    // 내가 가진 사과갯수 표시 (call)
    function get() public view returns(uint256) {
        return myApple[msg.sender];
    }
    // 전체 환불. 갯수를 지정하고 싶다면 매개변수를 받아야 합니다
    function sell() public payable {
        uint256 refund = myApple[msg.sender] * 10 ** 18;
        myApple[msg.sender] = 0;

        // payable() ~ 인자는 어드레스(string), 리턴값은 어카운트(object)로 이해하기
        // transfer ~ CA가 가진 이더를 사용자 어카운트에 전달하는 payable 내장 메서드
        payable(msg.sender).transfer(refund);
    }
}

[AppleShop.jsx]

import AppleShopContract from "../contracts/AppleShop.json";
import { useState, useEffect } from "react";

const AppleShop = ({ web3, account }) => {
    const [deployed, setDeployed] = useState(null);
    const [apple, setApple] = useState(0);

    const buy = async () => {
        await deployed.methods.buy().send({
            from : account,
            value : web3.utils.toWei('1', 'ether') // 이더는 CA에 전달됩니다
        })
    }

    const sell = async () => {
        await deployed.methods.sell().send({
            from : account,
        })
    }

    useEffect(() => {
        if (!deployed) return;
        deployed.methods.get().call().then(setApple);
    }, [deployed]);

    useEffect(() => {
        if (!web3) return;
        const instance = new web3.eth.Contract(
            AppleShopContract.abi,
            AppleShopContract.networks[1685407833552].address // window.ethereum에서 chainId로 가져올 수도 있습니다
        );
        setDeployed(instance);
    }, []);

    return (
        <>
            <h2>사과 가격: 1 ETH</h2>
            <h2>현재 계정 : {account}</h2>
            <div>
                내가 가진 사과 갯수 : {apple}
                <br />
                <button onClick={buy}>Buy</button>
            </div>
            <div>
                총 사과 판매 가격 1 ETH
                <br />
                <button onClick={sell}>Sell</button>
            </div>
        </>
    );
};

buy() 실행 후 CA의 밸런스

sell() 실행 후 CA의 밸런스


0개의 댓글