diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 762a296..130a421 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,11 +29,6 @@ jobs: run: | forge --version - - name: Run Forge fmt - run: | - forge fmt --check - id: fmt - - name: Run Forge build run: | forge build --sizes diff --git a/src/MerkleAirdrop.sol b/src/MerkleAirdrop.sol index d09c049..a9ad1e6 100644 --- a/src/MerkleAirdrop.sol +++ b/src/MerkleAirdrop.sol @@ -9,6 +9,8 @@ import "./@openzeppelin/utils/Address.sol"; error MerkleAirdrop__AlreadyClaimed(); error MerkleAirdrop__InvalidProof(); +error MerkleAirdrop__SameRoot(); +error MerkleAirdrop__ZeroAddress(); contract MerkleAirdrop is Ownable2Step { bytes32 public merkleRoot; @@ -24,6 +26,8 @@ contract MerkleAirdrop is Ownable2Step { } function setMerkleRoot(bytes32 _merkleRoot) external onlyOwner { + require (_merkleRoot != merkleRoot, MerkleAirdrop__SameRoot()); + merkleRoot = _merkleRoot; emit MerkleAirdrop__MerkleRootSet(_merkleRoot); } @@ -47,6 +51,8 @@ contract MerkleAirdrop is Ownable2Step { } function recoverEther(address payable _recipient) external onlyOwner { + require (_recipient != address(0), MerkleAirdrop__ZeroAddress()); + emit MerkleAirdrop__EtherRecovered(_recipient, address(this).balance); Address.sendValue(_recipient, address(this).balance); } diff --git a/test/TestMerkleAirdrop.sol b/test/TestMerkleAirdrop.sol index 11bc345..988c305 100644 --- a/test/TestMerkleAirdrop.sol +++ b/test/TestMerkleAirdrop.sol @@ -91,6 +91,47 @@ contract TestMerkleAirdrop is Test { assertEq(balanceAfter - balanceBefore, claims[i].amount); } } + + function test_SetMerkleRoot() external { + vm.startPrank(deployer); + merkleAirdrop.transferOwnership(owner); + vm.stopPrank(); + + vm.startPrank(owner); + merkleAirdrop.acceptOwnership(); + + vm.expectRevert(MerkleAirdrop__SameRoot.selector); + merkleAirdrop.setMerkleRoot(root); + + merkleAirdrop.setMerkleRoot(bytes32(uint256(42))); + vm.stopPrank(); + } + + function test_RecoverEther() external { + vm.startPrank(deployer); + merkleAirdrop.transferOwnership(owner); + vm.stopPrank(); + + vm.startPrank(owner); + merkleAirdrop.acceptOwnership(); + + uint256 balanceBefore = address(merkleAirdrop).balance; + Address.sendValue(payable(address(merkleAirdrop)), TOTAL_ETHER); + uint256 balanceAfter = address(merkleAirdrop).balance; + assertEq(balanceAfter - balanceBefore, TOTAL_ETHER); + + vm.expectRevert(MerkleAirdrop__ZeroAddress.selector); + merkleAirdrop.recoverEther(payable(address(0))); + + uint256 balance42Before = address(42).balance; + merkleAirdrop.recoverEther(payable(address(42))); + uint256 balance42After = address(42).balance; + + assertEq(address(merkleAirdrop).balance, 0); + assertEq(balance42After - balance42Before, TOTAL_ETHER); + + vm.stopPrank(); + } } struct Claim {