Skip to content

Commit

Permalink
test: add payments and withdrawal tests
Browse files Browse the repository at this point in the history
  • Loading branch information
0xChin committed Dec 6, 2024
1 parent 4a2eff9 commit a02c505
Show file tree
Hide file tree
Showing 4 changed files with 485 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"test:arbitrum-sepolia": "TESTING=true FORKED_NETWORK=arbitrum-sepolia FORK_BLOCK=98684306 forge test -vvv ",
"test:base": "TESTING=true FORKED_NETWORK=base FORK_BLOCK=20648648 forge test -vvv ",
"test:bnb": "TESTING=true FORKED_NETWORK=bnb FORK_BLOCK=44138162 forge test -vvv ",
"test:integration": "TESTING=true FORKED_NETWORK=mainnet FORK_BLOCK=18920905 forge test -vvv --match-contract Integration -vvv",
"test:optimism": "TESTING=true FORKED_NETWORK=optimism FORK_BLOCK=121238511 forge test -vvv ",
"test:optimism-sepolia": "TESTING=true FORKED_NETWORK=optimism-sepolia FORK_BLOCK=20113040 forge test -vvv ",
"test:polygon": "TESTING=true FORKED_NETWORK=polygon FORK_BLOCK=62103393 forge test -vvv ",
Expand Down
236 changes: 236 additions & 0 deletions test/unit/Payment.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

// Base test contract
import {UnitBase} from "./helpers/Base.t.sol";

// Grateful contract and related interfaces
import {Grateful, IGrateful} from "contracts/Grateful.sol";
import {ERC20Mock} from "test/mocks/ERC20Mock.sol";

contract UnitPayment is UnitBase {
function test_paySuccessWithoutYield() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.mint(user, amount);
vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
vm.expectEmit(true, true, true, true);
emit IGrateful.PaymentProcessed(user, merchant, address(token), amount, false, paymentId);
grateful.pay(merchant, address(token), amount, paymentId, false);

uint256 feeAmount = (amount * grateful.fee()) / 1e18;
uint256 expectedMerchantAmount = amount - feeAmount;

assertEq(token.balanceOf(owner), feeAmount);
assertEq(token.balanceOf(merchant), expectedMerchantAmount);
}

function test_paySuccessWithYield() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.mint(user, amount);
vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
vm.expectEmit(true, true, true, true);
emit IGrateful.PaymentProcessed(user, merchant, address(token), amount, true, paymentId);
grateful.pay(merchant, address(token), amount, paymentId, true);

uint256 feeAmount = (amount * grateful.fee()) / 1e18;
uint256 amountAfterFee = amount - feeAmount;

assertEq(token.balanceOf(owner), feeAmount);
assertEq(token.balanceOf(merchant), 0);

uint256 merchantShares = grateful.shares(merchant, address(token));
uint256 merchantDeposit = grateful.userDeposits(merchant, address(token));

assertGt(merchantShares, 0);
assertEq(merchantDeposit, amountAfterFee);
}

function test_revertIfPayWithNonWhitelistedToken() public {
ERC20Mock nonWhitelistedToken = new ERC20Mock();

uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
nonWhitelistedToken.mint(user, amount);
vm.prank(user);
nonWhitelistedToken.approve(address(grateful), amount);

vm.prank(user);
vm.expectRevert(IGrateful.Grateful_TokenNotWhitelisted.selector);
grateful.pay(merchant, address(nonWhitelistedToken), amount, paymentId, false);
}

function test_revertIfPayWithZeroAmount() public {
uint256 amount = 0;
uint256 paymentId = 1;

vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
vm.expectRevert(IGrateful.Grateful_InvalidAmount.selector);
grateful.pay(merchant, address(token), amount, paymentId, false);
}

function test_revertIfPayWithInvalidMerchant() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
vm.expectRevert(IGrateful.Grateful_InvalidAddress.selector);
grateful.pay(address(0), address(token), amount, paymentId, false);
}

function test_revertIfPayWithInsufficientAllowance() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.mint(user, amount);

vm.prank(user);
vm.expectRevert();
grateful.pay(merchant, address(token), amount, paymentId, false);
}

function test_revertIfPayWithInsufficientBalance() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
vm.expectRevert();
grateful.pay(merchant, address(token), amount, paymentId, false);
}

function test_revertIfPayWithInvalidTokenAddress() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
vm.expectRevert(IGrateful.Grateful_TokenNotWhitelisted.selector);
grateful.pay(merchant, address(0), amount, paymentId, false);
}

function test_payWithoutVaultYieldFundsTrue() public {
vm.prank(owner);
grateful.removeVault(address(token));

uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.mint(user, amount);
vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
vm.expectEmit(true, true, true, true);
emit IGrateful.PaymentProcessed(user, merchant, address(token), amount, true, paymentId);
grateful.pay(merchant, address(token), amount, paymentId, true);

uint256 feeAmount = (amount * grateful.fee()) / 1e18;
uint256 amountAfterFee = amount - feeAmount;

assertEq(token.balanceOf(owner), feeAmount);
assertEq(token.balanceOf(merchant), amountAfterFee);

uint256 merchantShares = grateful.shares(merchant, address(token));
uint256 merchantDeposit = grateful.userDeposits(merchant, address(token));

assertEq(merchantShares, 0);
assertEq(merchantDeposit, 0);
}

function test_revertIfPayWithZeroAddressToken() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
vm.expectRevert(IGrateful.Grateful_TokenNotWhitelisted.selector);
grateful.pay(merchant, address(0), amount, paymentId, false);
}

function test_revertIfPayToZeroAddressMerchant() public {
uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.mint(user, amount);
vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
vm.expectRevert(IGrateful.Grateful_InvalidAddress.selector);
grateful.pay(address(0), address(token), amount, paymentId, false);
}

function test_payWithCustomFee() public {
uint256 customFee = 0.02 ether; // 2%
vm.prank(owner);
grateful.setCustomFee(customFee, merchant);

uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.mint(user, amount);
vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
grateful.pay(merchant, address(token), amount, paymentId, false);

uint256 feeAmount = (amount * customFee) / 1e18;
uint256 expectedMerchantAmount = amount - feeAmount;

assertEq(token.balanceOf(owner), feeAmount);
assertEq(token.balanceOf(merchant), expectedMerchantAmount);
}

function test_payWithVaultNotSetAndYieldFundsTrue() public {
vm.prank(owner);
grateful.removeVault(address(token));

uint256 amount = 1000 ether;
uint256 paymentId = 1;

vm.prank(user);
token.mint(user, amount);
vm.prank(user);
token.approve(address(grateful), amount);

vm.prank(user);
grateful.pay(merchant, address(token), amount, paymentId, true);

uint256 feeAmount = (amount * grateful.fee()) / 1e18;
uint256 amountAfterFee = amount - feeAmount;

assertEq(token.balanceOf(owner), feeAmount);
assertEq(token.balanceOf(merchant), amountAfterFee);

uint256 merchantShares = grateful.shares(merchant, address(token));
uint256 merchantDeposit = grateful.userDeposits(merchant, address(token));

assertEq(merchantShares, 0);
assertEq(merchantDeposit, 0);
}
}
Loading

0 comments on commit a02c505

Please sign in to comment.