체인의정석

스마트컨트렉트 테스트 코드, hardhat & ethers & Typescript에서 상황별 Big number 다루기 본문

블록체인/Ethers & web3

스마트컨트렉트 테스트 코드, hardhat & ethers & Typescript에서 상황별 Big number 다루기

체인의정석 2022. 7. 26. 14:44
728x90
반응형

bignumber의 경우 테스트 코드를 할 때 적용해주어야 한다.

특히 소수점 처리를 다루는 컨트렉트의 경우 정확한 예측치를 바탕으로 테스트를 하기 위해서는 decimal 을 적용시켜서 테스트 코드레벨에서 먼저 시나리오 테스트를 하는게 필요하다. 하지만 ethers로 하는 경우 잘 정리되어 있는 글이 별로 없어 따로 정리를 하였다.

 

먼저 decimal을 적용할 경우 ethers의 parsUnits을 사용한다.

decimal이 적용되기 전의 숫자를 number라고 정의해 놓고 이를 문자열로 바꾼 후 뒤에 붙이고 싶은 0 만큼, 여기선 일반적인 케이스인 decimal이 18인 경우이니 18만큼을 넣어준다.

      ethers.utils.parseUnits(number.toString(), 18)

이러면 Bignumber 형태의 자료형이 결과 값으로 나오게 된다.

 

이 결과 값은 테스트 코드의 값 비교에도 그대로 사용 할 수 있다.

    expect(await erc20Token.balanceOf(A.address)).to.equal(
      ethers.utils.parseUnits(amount.toString(), 18)
    );

이런식으로 하면 잔고 체크가 가능하다.

 

반면 검산이 필요한 경우도 있다. 이럴때는 bignumber 끼리 연산을 해주어야 하는데 연산이 그냥 하면 되지 않는다. bigInt 자료형으로 바꿔야 가능하다.

 

그 경우

    expect(await erc20Token.balanceOf(A.address)).to.equal(
      ethers.utils.parseUnits(amount.toString(), 18).toBigInt() -
        (
          await contractExample.checkAmount(
            ethers.utils.parseUnits(amount.toString(), 18),
            param
          )
        ).toBigInt()
    );

이런식으로 toBigInt를 bigNumber가 리턴되는 결과 값의 마지막에 붙이면 Big Int 형태로 바뀌면서 연산이 가능해 진다.

 

그리고 decimal이 붙기 전의 숫자의 경우

ethers.BigNumber.from(number).toNumber()

다음을 사용하면 일반 숫자형으로 바꿀 수 있다. 하지만 decimal을 넣을 경우 지원 범위가 초과 되게 되므로, 먼저 바꿔주고 그걸 다시 praseUnit을 사용하여 decimal로 적용시켜주고 이에 대한 연산을 할때는 toBigInt()를 적용시켜 주어야 한다.

 

마지막으로 스마트컨트렉트에서 잔고를 조회하는 등 조회 함수의 결과값으로서 큰 숫자값이 나오는 경우에는 bigNumber가 기본적인 값으로 나오게 된다. 해당 bigNumber가 나오는 경우 바로 .toBigInt()를 붙여주게 되면 bigInt가 되기 때문에 아래와 같이 검산이 가능하다.

    amount = ethers.utils.parseUnits("34239789", 18).toBigInt();
    
    const totalFee = await ExampleContract.checkTotalAmount(fee, ratio);
	
    expect(await erc20Token.balanceOf(A.address)).to.equal(
      amount - totalFee.toBigInt()
    );

  만약 amount 값에서 fee, ratio를 가지고 특정 요금의 %만큼 제외한 값이 맞는지 체크할 경우 아래와 같이 bignumber가 리턴되는 값을 가지고 와서 원래 amount 만큼에서 빠져나간 비율 만큼을 제외하고 그만큼의 잔고가 A의 주소에 있는지 위와 같이 확인할 수 있다.

 

결국 문자형태의 "숫자"와 bigNumber와 bigInt 를 자유자제로 써가면서 상황에 맞게 변환하여 사용하는 것이 중요하다.

 

예를 들어 infiniteApprove와 같은 경우 그냥 입력값이 고정되어 있으므로 

"숫자 최대값"을 한 상태로 끝내는것과 같이 사용하며 사칙연산이 들어갈 경우 bigInt 자료형을 사용하여서 bigInt형태로 바꾸어서 검산한 후 비교한다.

728x90
반응형
Comments