MultiSigWallet 테스트 코드

김대익·2022년 11월 10일
0

전체 동작 과정

먼저 MultiSigWallet 컨트랙트의 동작과정을 설명하면 아래와 같다.

배포시 Wallet컨트랙트의 owner들의 주소와 트랜잭션 실행을 위한 최소 동의 인원을 설정한다.

실행하고 싶은 트랜잭션 내용을 submitTransaction에 담아 제출하여 owner들의 confirm을 기다린다.


실행을 동의한다면 confirmTransaction으로 위에서 생성된 트랜잭션의 index를 인수로 넣어 동의하고,
동의를 취소하고싶다면 revokeTransaction을 실행시켜 동의를 취소한다.


트랜잭션이 이더를 전송하는 경우라면 컨트랙트가 이더를 가지고 있어야하므로
receive() 메서드를 통해 이더를 전송받는다.

트랜잭션 실행 함수는 실행하려는 트랜잭션의 인덱스를 인수로 받아,
실행되면 required이상의 인원이 동의했는지 확인하고,
동의했다면 실행시킨 뒤 트랜잭션 구조체의 executed를 true로 만들어 이미 실행이 되었다는 것을 기록해둔다.


submitTransaction

전체 동작과정을 알아보았으니 테스트코드를 작성해보려고한다.
submitTransaction함수에서 체크해봐야할 내용을 나열해보면
1. transactionId를 인덱스로 하는 transaction배열에 Transaction 구조체가 저장이 되었는지
2. submitTransaction함수가 실행되고 transactionCount가 증가하였는지
3. transactionId를 인덱스로 Submit이벤트가 정말로 발생하였는지
확인해야 한다.

그래서 함수가 실행되기 전 transactionCount를 저장해둔 뒤
함수를 실행해야지만 확인이 가능한 event를 첫 번째로 검사한다.
여기서 처음 제출되는 트랜잭션이므로 index는 0이라고 예상하여 테스트한다.

이후에는 함수가 한번 실행되었으니 검사만을 진행한다
먼저 transactionCount증가 여부를 검사하기 위해 저장해둔 실행하기전 Count에 1을 더한 뒤
실행된 이후의 Count를 비교해 동일한지 확인한다.

다음으로는 트랜잭션 구조체가 실제로 생성되었는지 확인하기 위해
트랜잭션 구조체의 destination주소가 초기값인 0이 아닌지 확인한다.


confirmTransaction

이제 required이상의 confirm을 받아야 executeTrancation함수를 실행시킬 수 있으므로
confirmTransaction함수를 검사하면서 동시에 confirmTransaction을 취소시키는 revokeConfirmation함수도 검사하겠다.

confirmTransaction과 revokeConfirmation에서 체크해봐야할 사항들을 나열해보면
confirmTransaction에서는
1. confirmation배열의 값이 false에서 true로 변경되었는지
2. confirmTransaction 함수 실행시 Confirmation이벤트가 실행되는지
revokeConfirmation에서는
1. confirmation배열의 값이 true에서 false로 변경되었는지
2. revokeConfirmation 함수 실행시 Revocation이벤트가 실행되는지
확인해야한다.

submitTransaction에서와 같이
이 테스트에서는 accounts[1~3]이 owner이고 required가 2인 상황을 가정하고,
accounts[3]은 confirm한 후 revoke한 상황을 가정하여 테스트할 것이다.

먼저 event는 함수를 실행하면서 확인이 가능하므로 먼저 실행 전의 confirmation배열의 값을 저장해둔다.
그리고 expect로 account별로 함수를 실행시켜 event가 실행되었는지 검사한 뒤,
revokeConfirmation에서 사용할 before값으로써 confirmTransaction이 실행된 뒤의 accounts[3]의 confirmation배열 상태를 저장해둔다

event를 검사하면서 실행이 되었으므로 accounts[1,2]의 confirmation배열 값이 false에서 true로 변하였는지,
즉 서로 같지않은지 확인한다.


revokeConfirmation

confirmTransaction의 모든 사항에 대한 검사는 완료되었으므로
이제 revokeConfirmation을 검사하기 위해 Revocation 이벤트가 발생하였는지 검사한다.

confirm한 뒤 저장해둔 accounts[3]의 confirmation배열 상태와 revoke한 뒤의 상태 배열 값이 true에서 false로 변하여 같지않은지 검사한다.


receive()

다음으로는 트랜잭션이 이더를 보내는 상황을 테스트하므로 컨트랙트에 이더를 보내
receive() 메서드가 실행되면서 Deposit 이벤트가 제대로 동작하는지 확인한다.

앞에서와 동일하게 receive() 실행 전의 컨트랙트의 잔고를 저장해둔 뒤
이더를 전송하여 Deposit 이벤트가 실행되는지 확인한다.

이후 저장해둔 이전 잔고 + 전송한 이더의 양이 메서드 실행 후의 잔고와 동일한지 검사한다.


executeTransaction

마지막으로 executeTransaction함수를 테스트한다.
executeTransaction에서 확인해봐야할 내용들은 아래와 같다.
1. executeTransaction함수가 실행된 뒤 실행한 트랜잭션 구조체의 executed변수가 true로 바뀌었는지
2. executeTransaction함수가 실행되면서 Execution 이벤트가 실행되는지
3. 이더를 전송하는 트랜잭션의 경우 실행 후 목적지 주소의 잔고가 변했는지
를 확인해야한다.

테스트에 앞서 앞에서와 같이
event검사 전에 목적지 주소의 잔고와 executed 변수를 저장해두고
함수를 실행시켜 event발생 여부를 확인한다.

다음으로는 executed가 false에서 true로 변경되었는지 같지 않을 경우를 체크하는 notEqual로 검사하고

마지막으로 함수 실행 전 목적지 주소 잔고에 실행시 보내는 이더의 양을 더하여
실행 뒤의 목적지 주소 잔고와 동일한 지 비교하여 실제로 이더가 보내졌는지 확인한다.


테스트 실행

모든 테스트 작성이 완료되었고 npx hardhat test를 통해 생각한대로 동작하여 테스트를 통과하는지 검사해보면

위와 같이 모든 테스트를 통과하여 생각했던대로 함수들이 동작했음을 확인할 수 있었다.

0개의 댓글