Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BTT Testing for DropERC20 #532

Merged
merged 24 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/test/drop/drop-erc20/_beforeClaim/_beforeClaim.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import { DropERC20 } from "contracts/prebuilts/drop/DropERC20.sol";
import { TWProxy } from "contracts/infra/TWProxy.sol";

// Test imports
import "../../../utils/BaseTest.sol";

contract HarnessDropERC20BeforeClaim is DropERC20 {
bytes private emptyBytes = bytes("");

function harness_beforeClaim(uint256 quantity, AllowlistProof calldata _proof) public view {
_beforeClaim(address(0), quantity, address(0), 0, _proof, emptyBytes);
}
}

contract DropERC20Test_beforeClaim is BaseTest {
address public dropImp;
HarnessDropERC20BeforeClaim public proxy;

uint256 private mintQty;

function setUp() public override {
super.setUp();

bytes memory initializeData = abi.encodeCall(
DropERC20.initialize,
(deployer, NAME, SYMBOL, CONTRACT_URI, forwarders(), saleRecipient, platformFeeRecipient, platformFeeBps)
);

dropImp = address(new HarnessDropERC20BeforeClaim());
proxy = HarnessDropERC20BeforeClaim(address(new TWProxy(dropImp, initializeData)));
}

modifier setMaxTotalSupply() {
vm.prank(deployer);
proxy.setMaxTotalSupply(100);
_;
}

modifier qtyExceedMaxTotalSupply() {
mintQty = 101;
_;
}

function test_revert_MaxSupplyExceeded() public setMaxTotalSupply qtyExceedMaxTotalSupply {
DropERC20.AllowlistProof memory proof;
vm.expectRevert("exceed max total supply.");
proxy.harness_beforeClaim(mintQty, proof);
}
}
10 changes: 10 additions & 0 deletions src/test/drop/drop-erc20/_beforeClaim/_beforeClaim.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function _beforeClaim(
address,
uint256 _quantity,
address,
uint256,
AllowlistProof calldata,
bytes memory
)
└── when maxTotalSupply does not equal to 0 and totalSupply() + _quantity is greater than _maxTotalSupply
└── it should revert ✅
93 changes: 93 additions & 0 deletions src/test/drop/drop-erc20/_canSetFunctions/_canSetFunctions.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import { DropERC20 } from "contracts/prebuilts/drop/DropERC20.sol";
import { TWProxy } from "contracts/infra/TWProxy.sol";

// Test imports
import "../../../utils/BaseTest.sol";

contract HarnessDropERC20CanSet is DropERC20 {
function canSetPlatformFeeInfo() external view returns (bool) {
return _canSetPlatformFeeInfo();
}

function canSetPrimarySaleRecipient() external view returns (bool) {
return _canSetPrimarySaleRecipient();
}

function canSetContractURI() external view returns (bool) {
return _canSetContractURI();
}

function canSetClaimConditions() external view returns (bool) {
return _canSetClaimConditions();
}
}

contract DropERC20Test_canSet is BaseTest {
address public dropImp;

HarnessDropERC20CanSet public proxy;

function setUp() public override {
super.setUp();

bytes memory initializeData = abi.encodeCall(
DropERC20.initialize,
(deployer, NAME, SYMBOL, CONTRACT_URI, forwarders(), saleRecipient, platformFeeRecipient, platformFeeBps)
);

dropImp = address(new HarnessDropERC20CanSet());
proxy = HarnessDropERC20CanSet(address(new TWProxy(dropImp, initializeData)));
}

modifier callerHasDefaultAdminRole() {
vm.startPrank(deployer);
_;
}

modifier callerDoesNotHaveDefaultAdminRole() {
_;
}

function test_canSetPlatformFee_returnTrue() public callerHasDefaultAdminRole {
bool status = proxy.canSetPlatformFeeInfo();
assertEq(status, true);
}

function test_canSetPlatformFee_returnFalse() public callerDoesNotHaveDefaultAdminRole {
bool status = proxy.canSetPlatformFeeInfo();
assertEq(status, false);
}

function test_canSetPrimarySaleRecipient_returnTrue() public callerHasDefaultAdminRole {
bool status = proxy.canSetPrimarySaleRecipient();
assertEq(status, true);
}

function test_canSetPrimarySaleRecipient_returnFalse() public callerDoesNotHaveDefaultAdminRole {
bool status = proxy.canSetPrimarySaleRecipient();
assertEq(status, false);
}

function test_canSetContractURI_returnTrue() public callerHasDefaultAdminRole {
bool status = proxy.canSetContractURI();
assertEq(status, true);
}

function test_canSetContractURI_returnFalse() public callerDoesNotHaveDefaultAdminRole {
bool status = proxy.canSetContractURI();
assertEq(status, false);
}

function test_canSetClaimConditions_returnTrue() public callerHasDefaultAdminRole {
bool status = proxy.canSetClaimConditions();
assertEq(status, true);
}

function test_canSetClaimConditions_returnFalse() public callerDoesNotHaveDefaultAdminRole {
bool status = proxy.canSetClaimConditions();
assertEq(status, false);
}
}
23 changes: 23 additions & 0 deletions src/test/drop/drop-erc20/_canSetFunctions/_canSetFunctions.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
function _canSetPlatformFeeInfo()
├── when caller has DEFAULT_ADMIN_ROLE
│ └── it should return true ✅
└── when caller does not have DEFAULT_ADMIN_ROLE
└── it should return false ✅

function _canSetPrimarySaleRecipient()
├── when caller has DEFAULT_ADMIN_ROLE
│ └── it should return true ✅
└── when caller does not have DEFAULT_ADMIN_ROLE
└── it should return false ✅

function _canSetContractURI()
├── when caller has DEFAULT_ADMIN_ROLE
│ └── it should return true ✅
└── when caller does not have DEFAULT_ADMIN_ROLE
└── it should return false ✅

function _canSetClaimConditions()
├── when caller has DEFAULT_ADMIN_ROLE
│ └── it should return true ✅
└── when caller does not have DEFAULT_ADMIN_ROLE
└── it should return false ✅
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import { DropERC20 } from "contracts/prebuilts/drop/DropERC20.sol";
import { TWProxy } from "contracts/infra/TWProxy.sol";

// Test imports
import "../../../utils/BaseTest.sol";

contract HarnessDropERC20CollectPriceOnClaim is DropERC20 {
function harness_collectPrice(
address _primarySaleRecipient,
uint256 _quantityToClaim,
address _currency,
uint256 _pricePerToken
) public payable {
_collectPriceOnClaim(_primarySaleRecipient, _quantityToClaim, _currency, _pricePerToken);
}
}

contract DropERC20Test_collectPrice is BaseTest {
address public dropImp;
HarnessDropERC20CollectPriceOnClaim public proxy;

address private currency;
address private primarySaleRecipient;
uint256 private msgValue;
uint256 private pricePerToken;

function setUp() public override {
super.setUp();

bytes memory initializeData = abi.encodeCall(
DropERC20.initialize,
(deployer, NAME, SYMBOL, CONTRACT_URI, forwarders(), saleRecipient, platformFeeRecipient, platformFeeBps)
);

dropImp = address(new HarnessDropERC20CollectPriceOnClaim());
proxy = HarnessDropERC20CollectPriceOnClaim(address(new TWProxy(dropImp, initializeData)));
}

modifier pricePerTokenZero() {
_;
}

modifier pricePerTokenNotZero() {
pricePerToken = 1 ether;
_;
}

modifier msgValueZero() {
_;
}

modifier msgValueNotZero() {
msgValue = 1 ether;
_;
}

modifier valuePriceMismatch() {
msgValue = 1 ether;
pricePerToken = 2 ether;
_;
}

modifier primarySaleRecipientZeroAddress() {
primarySaleRecipient = address(0);
_;
}

modifier primarySaleRecipientNotZeroAddress() {
primarySaleRecipient = address(0x0999);
_;
}

modifier currencyNativeToken() {
currency = NATIVE_TOKEN;
_;
}

modifier currencyNotNativeToken() {
currency = address(erc20);
_;
}

function test_revert_pricePerTokenZeroMsgValueNotZero() public pricePerTokenZero msgValueNotZero {
vm.expectRevert("!Value");
proxy.harness_collectPrice{ value: msgValue }(primarySaleRecipient, 1 ether, currency, pricePerToken);
}

function test_revert_nativeCurrencyTotalPriceZero() public pricePerTokenNotZero msgValueZero currencyNativeToken {
vm.expectRevert("quantity too low");
proxy.harness_collectPrice{ value: msgValue }(primarySaleRecipient, 0, currency, pricePerToken);
}

function test_revert_nativeCurrencyValuePriceMismatch() public currencyNativeToken valuePriceMismatch {
vm.expectRevert("Invalid msg value");
proxy.harness_collectPrice{ value: msgValue }(primarySaleRecipient, 1 ether, currency, pricePerToken);
}

function test_revert_erc20ValuePriceMismatch() public currencyNotNativeToken valuePriceMismatch {
vm.expectRevert("Invalid msg value");
proxy.harness_collectPrice{ value: msgValue }(primarySaleRecipient, 1 ether, currency, pricePerToken);
}

function test_state_nativeCurrency()
public
currencyNativeToken
pricePerTokenNotZero
msgValueNotZero
primarySaleRecipientNotZeroAddress
{
(address platformFeeRecipient, uint16 platformFeeBps) = proxy.getPlatformFeeInfo();
uint256 beforeBalancePrimarySaleRecipient = address(primarySaleRecipient).balance;
uint256 beforeBalancePlatformFeeRecipient = address(platformFeeRecipient).balance;

proxy.harness_collectPrice{ value: msgValue }(primarySaleRecipient, 1 ether, currency, pricePerToken);

uint256 afterBalancePrimarySaleRecipient = address(primarySaleRecipient).balance;
uint256 afterBalancePlatformFeeRecipient = address(platformFeeRecipient).balance;

uint256 platformFeeVal = (msgValue * platformFeeBps) / MAX_BPS;
uint256 primarySaleRecipientVal = msgValue - platformFeeVal;

assertEq(beforeBalancePrimarySaleRecipient + primarySaleRecipientVal, afterBalancePrimarySaleRecipient);
assertEq(beforeBalancePlatformFeeRecipient + platformFeeVal, afterBalancePlatformFeeRecipient);
}

function test_revert_erc20_msgValueNotZero()
public
currencyNotNativeToken
msgValueNotZero
primarySaleRecipientNotZeroAddress
{
vm.expectRevert("!Value");
proxy.harness_collectPrice{ value: msgValue }(primarySaleRecipient, msgValue, currency, pricePerToken);
}

function test_state_erc20() public currencyNotNativeToken pricePerTokenNotZero primarySaleRecipientNotZeroAddress {
(address platformFeeRecipient, uint16 platformFeeBps) = proxy.getPlatformFeeInfo();

erc20.mint(address(this), pricePerToken);
ERC20(erc20).approve(address(proxy), pricePerToken);
uint256 beforeBalancePrimarySaleRecipient = erc20.balanceOf(primarySaleRecipient);
uint256 beforeBalancePlatformFeeRecipient = erc20.balanceOf(platformFeeRecipient);

proxy.harness_collectPrice(primarySaleRecipient, pricePerToken, currency, pricePerToken);

uint256 afterBalancePrimarySaleRecipient = erc20.balanceOf(primarySaleRecipient);
uint256 afterBalancePlatformFeeRecipient = erc20.balanceOf(platformFeeRecipient);

uint256 platformFeeVal = (pricePerToken * platformFeeBps) / MAX_BPS;
uint256 primarySaleRecipientVal = 1 ether - platformFeeVal;

assertEq(beforeBalancePrimarySaleRecipient + primarySaleRecipientVal, afterBalancePrimarySaleRecipient);
assertEq(beforeBalancePlatformFeeRecipient + platformFeeVal, afterBalancePlatformFeeRecipient);
}

function test_state_erc20StoredPrimarySaleRecipient()
public
currencyNotNativeToken
pricePerTokenNotZero
primarySaleRecipientZeroAddress
{
(address platformFeeRecipient, uint16 platformFeeBps) = proxy.getPlatformFeeInfo();
address storedPrimarySaleRecipient = proxy.primarySaleRecipient();

erc20.mint(address(this), pricePerToken);
ERC20(erc20).approve(address(proxy), pricePerToken);
uint256 beforeBalancePrimarySaleRecipient = erc20.balanceOf(storedPrimarySaleRecipient);
uint256 beforeBalancePlatformFeeRecipient = erc20.balanceOf(platformFeeRecipient);

proxy.harness_collectPrice(primarySaleRecipient, pricePerToken, currency, pricePerToken);

uint256 afterBalancePrimarySaleRecipient = erc20.balanceOf(storedPrimarySaleRecipient);
uint256 afterBalancePlatformFeeRecipient = erc20.balanceOf(platformFeeRecipient);

uint256 platformFeeVal = (pricePerToken * platformFeeBps) / MAX_BPS;
uint256 primarySaleRecipientVal = 1 ether - platformFeeVal;

assertEq(beforeBalancePrimarySaleRecipient + primarySaleRecipientVal, afterBalancePrimarySaleRecipient);
assertEq(beforeBalancePlatformFeeRecipient + platformFeeVal, afterBalancePlatformFeeRecipient);
}

function test_state_nativeCurrencyStoredPrimarySaleRecipient()
public
currencyNativeToken
pricePerTokenNotZero
primarySaleRecipientZeroAddress
msgValueNotZero
{
(address platformFeeRecipient, uint16 platformFeeBps) = proxy.getPlatformFeeInfo();
address storedPrimarySaleRecipient = proxy.primarySaleRecipient();

uint256 beforeBalancePrimarySaleRecipient = address(storedPrimarySaleRecipient).balance;
uint256 beforeBalancePlatformFeeRecipient = address(platformFeeRecipient).balance;

proxy.harness_collectPrice{ value: msgValue }(primarySaleRecipient, 1 ether, currency, pricePerToken);

uint256 afterBalancePrimarySaleRecipient = address(storedPrimarySaleRecipient).balance;
uint256 afterBalancePlatformFeeRecipient = address(platformFeeRecipient).balance;

uint256 platformFeeVal = (msgValue * platformFeeBps) / MAX_BPS;
uint256 primarySaleRecipientVal = msgValue - platformFeeVal;

assertEq(beforeBalancePrimarySaleRecipient + primarySaleRecipientVal, afterBalancePrimarySaleRecipient);
assertEq(beforeBalancePlatformFeeRecipient + platformFeeVal, afterBalancePlatformFeeRecipient);
}
}
Loading