2020.코딩일지

[solidity] payable/balance와 msg.sender (feat.솔리디티깨부수기) 본문

Block Chain

[solidity] payable/balance와 msg.sender (feat.솔리디티깨부수기)

개발하는라푼젤 2022. 12. 5. 13:38
728x90

payable을 붙이면 빨간색 버튼이 된다

payable

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract lec26 {
    /*
    payable은 이더/토큰과 주고받을때(상호작용시) 필요한 키워드라고 생각하쟈!
    즉, send, transfer, call을 이용하여 이더를 보낼때 Payable이라는 키워드가 필요하다.
    이 payable은 주로 "함수, 주소, 생성자"에 붙여서 사용된다.

    msg.value는 송금 보낸 코인의 값

    이더를 보내는 3가지
        1. send : 2300 gas를 소비, (에러대신에) 성공여부를 true또는 false로 리턴한다.
        2. transfer : 2300 gas를 소비, 실패시 에러를 발생 
        3. call : 가변적인 gas소비 (gas값 지정 가능), 성공여부를 true 또는 false로 리턴
                재진입(re-entrancy) 공격 위험성 있음(엇위험해 무한반복), 2019.12월 이후 call 사용을 추천
        0.4.13 버전이후에는 안전한 방법인 ⭐️transfer 권장 했으나 
        Istanbul하드포크이후 가스가격이 올라서 ⭐️call 사용 권장. 
    */
    event howMuch(uint256 _value) ;

//gas 32436
    function sendNow(address payable _to) public payable { //⭐️_to자리에 스컨도 이더를받을수있다;ㅋㅋ
        bool sent = _to.send(msg.value); //(msg.value에는 이더금액이들어있다) return true or false
        require(sent, "Failed to send either");
        emit howMuch(msg.value);
    }

//gas 32436
    function transferNow(address payable _to) public payable{
        _to.transfer(msg.value); //transfer자체가 에러를 리턴하기때문에 위와같이 require를 안써도된다.
        emit howMuch(msg.value);
    }

    function callNow(address payable _to) public payable {
        // (0.6.12로테스트함)~0.7
        // (bool, sent, ) = _to.call.gas(1000).value(msg.value)("");
        // require(sent, "failed to send either");

        // 0.7~  //gas 32695
        // (bool sent, ) = _to.call{value: msg.value, gas:1000}("");//가스지정했다가 처리가안될수도있으니; 지정안하는게나을수도
        // require(sent, "Failed to send Ether");

        emit howMuch(msg.value);
    }
}

 

payable에 생성자적용

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
//34강) modifier로 변경
//payable을 생성자에 넣을 때. 특정 주소에게만 권한 주기
//(payable은 주로 함수, 주소, 생성자에 붙여서 사용된다)
contract MobileBanking {
    address owner;
    constructor() payable { //컨트랙자체가 입금받을수있다;ㅋㅋ 
        owner = msg.sender;
    }

    event SendInfo(address _msgSender, uint256 _currentValue);
    event MyCurrentValue(address _msgSender, uint256 _value);
    event CurrentValueOfSomeone(address _msgSender, address _to, uint256 _value);

    function sendEther(address payable _to) public payable {
        require(msg.sender == owner, "Only Owner!"); //추가함 오더여야만이 가능하다.
        require(msg.sender.balance >= msg.value, "Your balance is not enough");
        _to.transfer(msg.value);
        emit SendInfo(msg.sender, (msg.sender).balance); //event로 전송하고 남은 잔액이 나옴
    }

    function checkValueNow() public {
        emit MyCurrentValue(msg.sender, msg.sender.balance);
    }

    function checkUserMoney(address _to) public{
        emit CurrentValueOfSomeone(msg.sender, _to, _to.balance);
        //보내는사람주소, 받는사람주소, 받는사람의 잔액이 출력됨
    }
}

 

 


 

balance와 msg.sender

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

/*
주소.balance
주소.balance는 해당 특정 주소의 현재 갖고 있는 이더의 잔액을 나타낸다(msg.value는 송금액)
주소.balance와 같은 형태로 사용한다.

msg.sender  
msg.sender는 스컨을 사용하는 주체라고 볼 수 있다.
msg.sender는 앞으로 call vs delegate call에서 주요 내용이다.
*/

contract MobileBanking {
    event SendInfo(address _msgSender, uint256 _currentValue);
    event MyCurrentValue(address _msgSender, uint256 _value);
    event CurrentValueOfSomeone(address _msgSender, address _to, uint256 _value);

    function sendEther(address payable _to) public payable {
        require(msg.sender.balance >= msg.value, "Your balance is not enough");
        _to.transfer(msg.value);
        emit SendInfo(msg.sender, (msg.sender).balance); //event로 전송하고 남은 잔액이 나옴
    }

    function checkValueNow() public {
        emit MyCurrentValue(msg.sender, msg.sender.balance);
    }

    function checkUserMoney(address _to) public{
        emit CurrentValueOfSomeone(msg.sender, _to, _to.balance);
        //보내는사람주소, 받는사람주소, 받는사람의 잔액이 출력됨
    }
}
Comments