Remix_05

atesi·2022년 10월 16일
0

blockchain

목록 보기
7/12

Sending ETH from Contract

docs.solidity

transfer

payable(msg.sender).transfer(address(this).balance)
msg.senderaddress의 type이다. 앞에 payable을 추가하는 것은 이전에 int와 uint로 했던 것처럼 형변환하는 것이다. this는 전체계약인 FundMe.sol을 의미한다. 코스트가 2300gas로 제한되고 더 많은 코스트가 필요하면 에러를 반환한다.

send

bool sendSuccess= payable(msg.sender).send(address(this).balance);
require(sendSuccess, "Couldn't send the funds");

마찬가지로 2300gas로 제한되지만 오류 대신 bool을 반환. 자체적으로 반환하지 않기 때문에 위와같이 작성.

call

(bool callSuccess, bytes memory dataReturned)= payable(msg.sender).call{value: address(this).balance}("");

.balance 뒤의 괄호는 비어 있다. 일반적으로 계약에서 함수를 호출할 때 함수 정보나 호출하려는 함수에 대한 정보를 넣는다. 실제로 함수를 호출하고 싶지 않으므로 이 함수를 비워둔다. 비워 둔다는 것을 알리기 위해 ("")을 이용한다.

call.{value: address(this).balance}은 Remix에 지불하려는 금액을 입력하는 Value부분이 있다. 이와 같이 작동하기 위해 this계약의 주소에 금액을 입력.

2개의 변수를 반환한다. 반환되는 첫 번째 변수는 bool callSuccess이고 두 번째 변수는 dataReturned 바이트이다. 그러나 call메서드로 어떤 함수도 호출하지 않기 때문에 이 두 번째 변수는 필요하지 않다.

(bool callSuccess,)= payable(msg.sender).call{value: address(this).balance}("");
require(callSuccess, "Call failed");

Basic solidity constructor

계약을 배포한 사람만 자금을 인출할 수 있도록 하기 위해 constructor를 사용한다.

constructor(){
    owner= msg.sender;
}

owner 주소 변수를 만들고 constructormsg.sender를 설정한다.

modifier onlyOwner{
require(msg.sender == owner, "You are not the owner!");
_;
}
function withdraw() public onlyOwner {
	...
}

사용할 함수의 상태변수 뒤에 modifier를 입력해준다.

_;은 조건후에 modifier가 첨부된 함수의 나머지 코드를 실행하겠다는 의미.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import "./PriceConverter.sol";

contract FundMe{
    using PriceConverter for uint256;

    uint256 public minimumUsd = 50 * 1e18;
    address[] public funders;
    mapping(address => uint256) public addressToAmountFunded;

    address public owner;

    constructor(){
        owner = msg.sender;
    }

    function fund() public payable{
        require(msg.value.getConversionRate() >= minimumUsd, "Didn't send enough!"); // 1e18 == 1 * 10 ** 18
        funders.push(msg.sender);
        addressToAmountFunded[msg.sender] = msg.value;
    }

    function withdraw() public onlyOwner {

        for(uint256 funderIndex = 0; funderIndex < funders.length; funderIndex++){
            address funder = funders[funderIndex];
            addressToAmountFunded[funder] = 0;
        }

        funders = new address[](0);
        (bool callSuccess,)= payable(msg.sender).call{value: address(this).balance}("");
        require(callSuccess, "Call failed");
    }

    modifier onlyOwner {
        require(msg.sender == owner, "Sender is not owner!");
        _;
    }
}

완성된 코드

Testnet Demo


컴파일 후 ENVIRONMENT를 injected Provider - Metamask로 바꿔주고 CONTRACT가 FundMe로 맞춰진것을 확인 후 deploy를 눌러주자. 메타마스크에서 확인을 눌러준다.

eth-converter
50USD를 1ETH/USD인 1300으로 나눠준다. 0.0384...이 나오는데 계산하기 쉽게 0.04를 하겠다.
변환기에서 Wei값을 가져와서
Value에 입력후 fund를 해주면 성공적으로 전송된것을 확인할 수 있다.
시도 할때마다 Transaction이 쌓인다.

인출 확인을 위해 계정2로 바꾸어주고

인출을 누르면 성공적으로 오류 메세지를 반환한다. send Transaction을 눌러도 가스를 소비하고 실패할 것이다. 주소를 다시 바꿔주고 인출을 하면 성공이다.




이 시리즈는 freeCodeCamp.org의 강의를 들으면서 공부한 내용을 정리하기 위해 작성했습니다.

profile
Action!

0개의 댓글