Solidity ^0.8.0 - Underflow, Overflow 그리고 unchecked{…} 키워드

프동프동·2023년 9월 19일
0

솔리디티(Solidity)

목록 보기
16/20
post-thumbnail
post-custom-banner

https://docs.soliditylang.org/en/v0.8.21/080-breaking-changes.html

Solidity 0.8.0의 변경점에 대해 번역을 진행하고 Hardhat, Ethers.js, Typescript를 통해 이해하기 쉽도록 작성하였습니다.

Slient Changes of the Sematics - 1

컴파일러가 사용자에게 알리지 않고 기존 코드의 동작이 변경되는 변경사항이 나열되어 있습니다.
시리즈로 작성하겠습니다.

Underflow, Overflow 그리고 unchecked{…} 키워드

  • Solidity 0.8.0에서 산술 연산은 Underflow, Overflow에서 revert 됩니다. 하지만 **unchecked{…}**를 사용하면 이전 wapping 동작을 사용할 수 있습니다. Overflow 검사는 매우 일반적이므로 가스 비용이 약간 증가하더라도 코드의 가독성을 높이기 위해 기본값으로 설정했습니다.
    • Arithmetic.sol
      // SPDX-License-Identifier: MIT
      pragma solidity ^0.8.0;
      
      contract Arithmetic {
          function add(uint256 a, uint256 b) public pure returns (uint256) {
              return a + b;
          }
      
          function subtract(uint256 a, uint256 b) public pure returns (uint256) {
              return a - b;
          }
      
          function uncheckedAdd(uint256 a, uint256 b) public pure returns (uint256) {
              unchecked {
                  return a + b;
              }
          }
      
          function uncheckedSubtract(
              uint256 a,
              uint256 b
          ) public pure returns (uint256) {
              unchecked {
                  return a - b;
              }
          }
      }
    • Arithmetic.ts
      • Solidty 0.8.0 버전에서는 overflow, underflow 발생 시 revert됩니다.

        describe('add', () => {
          it('overflow로 인해 revert된다.', async () => {
            const { Arithmetic } = await loadFixture(DeployContract);
        
            await expect(Arithmetic.add(ethers.MaxUint256, ethers.MaxUint256)).to.be
              .reverted;
          });
        });
        describe('sub', () => {
          it('underflow로 인해 revert된다.', async () => {
            const { Arithmetic } = await loadFixture(DeployContract);
        
            await expect(Arithmetic.subtract(0, 1)).to.be.reverted;
          });
        });
      • 하지만 unchecked 키워드를 사용하면 이전 버전 처럼 동작하도록 할 수 있습니다.

        describe('uncheckedAdd', () => {
            it('uncheckedAdd', async () => {
              // Wrapping behavior
              const { Arithmetic } = await loadFixture(DeployContract);
              const result = await Arithmetic.uncheckedAdd(ethers.MaxUint256, 2);
              expect(result).to.equal(1);
            });
          });
          describe('uncheckedSubtract', () => {
            it('uncheckedSubtract', async () => {
              // Wrapping behavior
              const { Arithmetic } = await loadFixture(DeployContract);
              const result = await Arithmetic.uncheckedSubtract(0, 1);
        
              expect(result).to.equal(ethers.MaxUint256);
            });
          });
      • unchecked 키워드를 사용한 함수의 경우 이전처럼 underflow, overflow 발생 시 결과를 그대로 보여줍니다.

profile
좋은 개발자가 되고싶은
post-custom-banner

0개의 댓글