Remix_04

atesi·2022년 10월 16일
0

blockchain

목록 보기
6/12

Arrays & Structs

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

 import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract FundMe {

    uint256 public minimumUsd = 50 * 1e18;

    address[] public funders;
    mapping(ddress => uint256) public addressToAmountFunded;

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

계약에 돈을 보낸 사람을 추적하기 위해 funders 배열을 만들어준다. 그리고 얼마를 보냈는지 확인을 위해 mapping을 통해 값에 msg.value를 추가한다.

Libraries

Solidity-Libraries

contracts/
	SimpleStorage.sol
    StorageFactory.sol
    ExtraStorage.sol
    FundMe.sol
    PriceConverter.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

library PriceConverter {

     function getPrice() internal view returns(uint256){
        // ABI 
        // Address 0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
        AggregatorV3Interface priceFeed = AggregatorV3Interface(0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e);
        (,int256 price,,,) = priceFeed.latestRoundData();
        // ETH in terms of USD
        // 1300.00000000
        return uint256(price * 1e10); // 1**10 == 10000000000
    }

    function getVersion() internal view returns (uint256) {
        AggregatorV3Interface priceFeed = AggregatorV3Interface(0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e)
        return priceFeed.version();
    }

    function getConversionRate(uint256 ethAmount) internal view returns (uint256) {
        uint256 ethPrice = getPrice();
        // 1300_00000000000000000 = ETH / USD price
        // 1_0000000000000000000 ETH

        uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1e18;
        return ethAmountInUsd;
    }

}

contract대신에 library를 입력해준다. 변수를 가질 수 없고 라이브러리의 모든 기능은 internal이 된다.

FundMe.sol에서 getPrice, getVersiongetConversionRate 함수를 잘라내서 PriceConverter.sol에 붙여넣는다. AggregatorV3Interface 역시 사용하지 않으므로 import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";도 잘라내어 붙여넣는다. 마지막으로 가져온 함수의 상태변수를 internal로 바꾸어준다.

// 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(ddress => uint256) public addressToAmountFunded;

    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;
    }

}

Solidity에서 'using X for Y'의 의미는 라이브러리의 함수 X를 타입 Y로 사용한다는 것이다.
예를 들어 Using SafeMath for uint256 라고 하면,
add, sub, mul, div같은 SafeMath 의 함수의 bound는 uint256타입인 것이다.(1)^{(1)}

이것이 작동하는 방식은 라이브러리를 만든 후 스마트계약에서 사용할 때 일반적으로 변수가 전달될 것으로 예상하는 함수는 msg.value를 첫 번째 변수로 간주한다. 따라서 msg.value는 라이브러리 함수의 첫 번째 매개 변수로 간주된다.

function getConversionRate (uint256 ethAmount, uint256 somethingElse) internal view returns (uint256) 

msg.value.getConversionRate(123);

두 번째 변수를 함수에 전달하려는 경우 일반 함수 호출처럼 전달된다. 123은 두번째 파라미터이다.

SafeMath, Overflow Checking,"unchcked" Keyword

//SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

contract SafeMathTester{
    uint8 public bigNumber = 255; // unchecked

    function add() public{
        bigNumber= bigNumber + 1;
    }
}

uint8이 가질 수 있는 가장 큰 숫자 255에 1을 추가하면 오버플로우가 발생 0을 반환

//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract SafeMathTester{
    uint8 public bigNumber = 255;

    function add() public{
        unchecked{bigNumber= bigNumber + 1;
    }
}

0.8.0 이후에는 에러를 발생하지만 uncheked를 통해 이전 버전과 동일하게 수행한다. 계약이 더 효율적이라고 한다.

Basic loop

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

배열을 반복하고 보낸금액을 0으로 설정한다.

FundMe.sol
	...
    
	function withdraw() public{	
    	for (uint256 funderIndex= 0; funderIndex < 	funders.length; funderIndex++){
    		address funder= funders[funderIndex];
    		addressToAmountFunded[funder]= 0;
    	}
        
        funders= new address[](0);
	}
}

배열을 초기화 해준다.




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

참고
https://is-aile-i.tistory.com/m/20 (1)^{(1)}

profile
Action!

0개의 댓글