Files
v4-core/test/ERC6909Claims.t.sol

405 lines
12 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import {Test} from "forge-std/Test.sol";
import {Currency} from "../src/types/Currency.sol";
import {MockERC6909Claims} from "../src/test/MockERC6909Claims.sol";
contract ERC6909ClaimsTest is Test {
MockERC6909Claims token;
function setUp() public {
token = new MockERC6909Claims();
}
function test_burnFrom_withApproval(address sender, uint256 id, uint256 mintAmount, uint256 transferAmount)
public
{
token.mint(sender, id, mintAmount);
vm.prank(sender);
token.approve(address(this), id, mintAmount);
if (transferAmount > mintAmount) {
vm.expectRevert();
}
token.burnFrom(sender, id, transferAmount);
if (transferAmount <= mintAmount) {
if (mintAmount == type(uint256).max) {
assertEq(token.allowance(sender, address(this), id), type(uint256).max);
} else {
if (sender != address(this)) {
assertEq(token.allowance(sender, address(this), id), mintAmount - transferAmount);
} else {
assertEq(token.allowance(sender, address(this), id), mintAmount);
}
}
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
}
}
function test_burnFrom_revertsWithNoApproval() public {
token.mint(address(this), 1337, 100);
vm.prank(address(0xBEEF));
vm.expectRevert();
token.burnFrom(address(this), 1337, 100);
}
/// ---- Tests copied from solmate ---- ///
function testMint() public {
token.mint(address(0xBEEF), 1337, 100);
vm.snapshotGasLastCall("ERC6909Claims mint");
assertEq(token.balanceOf(address(0xBEEF), 1337), 100);
}
function testBurn() public {
token.mint(address(0xBEEF), 1337, 100);
vm.prank(address(0xBEEF));
token.burn(1337, 70);
vm.snapshotGasLastCall("ERC6909Claims burn");
assertEq(token.balanceOf(address(0xBEEF), 1337), 30);
}
function testSetOperator() public {
token.setOperator(address(0xBEEF), true);
assertTrue(token.isOperator(address(this), address(0xBEEF)));
}
function testApprove() public {
token.approve(address(0xBEEF), 1337, 100);
vm.snapshotGasLastCall("ERC6909Claims approve");
assertEq(token.allowance(address(this), address(0xBEEF), 1337), 100);
}
function testTransfer() public {
address sender = address(0xABCD);
token.mint(sender, 1337, 100);
vm.prank(sender);
token.transfer(address(0xBEEF), 1337, 70);
vm.snapshotGasLastCall("ERC6909Claims transfer");
assertEq(token.balanceOf(sender, 1337), 30);
assertEq(token.balanceOf(address(0xBEEF), 1337), 70);
}
function testTransferFromWithApproval() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
token.mint(sender, 1337, 100);
vm.prank(sender);
token.approve(address(this), 1337, 100);
token.transferFrom(sender, receiver, 1337, 70);
vm.snapshotGasLastCall("ERC6909Claims transferFrom with approval");
assertEq(token.allowance(sender, address(this), 1337), 30);
assertEq(token.balanceOf(sender, 1337), 30);
assertEq(token.balanceOf(receiver, 1337), 70);
}
function testTransferFromWithInfiniteApproval() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
token.mint(sender, 1337, 100);
vm.prank(sender);
token.approve(address(this), 1337, type(uint256).max);
token.transferFrom(sender, receiver, 1337, 70);
vm.snapshotGasLastCall("ERC6909Claims transferFrom with infinite approval");
assertEq(token.allowance(sender, address(this), 1337), type(uint256).max);
assertEq(token.balanceOf(sender, 1337), 30);
assertEq(token.balanceOf(receiver, 1337), 70);
}
function testTransferFromAsOperator() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
token.mint(sender, 1337, 100);
vm.prank(sender);
token.setOperator(address(this), true);
token.transferFrom(sender, receiver, 1337, 70);
vm.snapshotGasLastCall("ERC6909Claims transferFrom as operator");
assertEq(token.balanceOf(sender, 1337), 30);
assertEq(token.balanceOf(receiver, 1337), 70);
}
function test_revertMintBalanceOverflow() public {
token.mint(address(0xDEAD), 1337, type(uint256).max);
vm.expectRevert();
token.mint(address(0xDEAD), 1337, 1);
}
function test_revertTransferBalanceUnderflow() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
vm.expectRevert();
vm.prank(sender);
token.transferFrom(sender, receiver, 1337, 1);
}
function test_revertTransferBalanceOverflow() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
token.mint(sender, 1337, type(uint256).max);
vm.prank(sender);
token.transferFrom(sender, receiver, 1337, type(uint256).max);
token.mint(sender, 1337, 1);
vm.expectRevert();
vm.prank(sender);
token.transferFrom(sender, receiver, 1337, 1);
}
function test_revertTransferFromBalanceUnderflow() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
vm.expectRevert();
vm.prank(sender);
token.transferFrom(sender, receiver, 1337, 1);
}
function test_revertTransferFromBalanceOverflow() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
token.mint(sender, 1337, type(uint256).max);
vm.prank(sender);
token.transferFrom(sender, receiver, 1337, type(uint256).max);
token.mint(sender, 1337, 1);
vm.expectRevert();
vm.prank(sender);
token.transferFrom(sender, receiver, 1337, 1);
}
function test_revertTransferFromNotAuthorized() public {
address sender = address(0xABCD);
address receiver = address(0xBEEF);
token.mint(sender, 1337, 100);
vm.expectRevert();
token.transferFrom(sender, receiver, 1337, 100);
}
function testMint(address receiver, uint256 id, uint256 amount) public {
token.mint(receiver, id, amount);
assertEq(token.balanceOf(receiver, id), amount);
}
function testBurn(address sender, uint256 id, uint256 amount) public {
token.mint(sender, id, amount);
vm.prank(sender);
token.burn(id, amount);
assertEq(token.balanceOf(sender, id), 0);
}
function testSetOperator(address operator, bool approved) public {
token.setOperator(operator, approved);
assertEq(token.isOperator(address(this), operator), approved);
}
function testApprove(address spender, uint256 id, uint256 amount) public {
token.approve(spender, id, amount);
assertEq(token.allowance(address(this), spender, id), amount);
}
function testTransfer(address sender, address receiver, uint256 id, uint256 mintAmount, uint256 transferAmount)
public
{
transferAmount = bound(transferAmount, 0, mintAmount);
token.mint(sender, id, mintAmount);
vm.prank(sender);
token.transfer(receiver, id, transferAmount);
if (sender == receiver) {
assertEq(token.balanceOf(sender, id), mintAmount);
} else {
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
assertEq(token.balanceOf(receiver, id), transferAmount);
}
}
function testTransferFromWithApproval(
address sender,
address receiver,
uint256 id,
uint256 mintAmount,
uint256 transferAmount
) public {
transferAmount = bound(transferAmount, 0, mintAmount);
token.mint(sender, id, mintAmount);
vm.prank(sender);
token.approve(address(this), id, mintAmount);
token.transferFrom(sender, receiver, id, transferAmount);
if (mintAmount == type(uint256).max) {
assertEq(token.allowance(sender, address(this), id), type(uint256).max);
} else {
if (sender != address(this)) {
assertEq(token.allowance(sender, address(this), id), mintAmount - transferAmount);
} else {
assertEq(token.allowance(sender, address(this), id), mintAmount);
}
}
if (sender == receiver) {
assertEq(token.balanceOf(sender, id), mintAmount);
} else {
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
assertEq(token.balanceOf(receiver, id), transferAmount);
}
}
function testTransferFromWithInfiniteApproval(
address sender,
address receiver,
uint256 id,
uint256 mintAmount,
uint256 transferAmount
) public {
transferAmount = bound(transferAmount, 0, mintAmount);
token.mint(sender, id, mintAmount);
vm.prank(sender);
token.approve(address(this), id, type(uint256).max);
token.transferFrom(sender, receiver, id, transferAmount);
assertEq(token.allowance(sender, address(this), id), type(uint256).max);
if (sender == receiver) {
assertEq(token.balanceOf(sender, id), mintAmount);
} else {
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
assertEq(token.balanceOf(receiver, id), transferAmount);
}
}
function testTransferFromAsOperator(
address sender,
address receiver,
uint256 id,
uint256 mintAmount,
uint256 transferAmount
) public {
transferAmount = bound(transferAmount, 0, mintAmount);
token.mint(sender, id, mintAmount);
vm.prank(sender);
token.setOperator(address(this), true);
token.transferFrom(sender, receiver, id, transferAmount);
if (sender == receiver) {
assertEq(token.balanceOf(sender, id), mintAmount);
} else {
assertEq(token.balanceOf(sender, id), mintAmount - transferAmount);
assertEq(token.balanceOf(receiver, id), transferAmount);
}
}
function test_revertTransferBalanceUnderflow(address sender, address receiver, uint256 id, uint256 amount) public {
amount = bound(amount, 1, type(uint256).max);
vm.expectRevert();
vm.prank(sender);
token.transfer(receiver, id, amount);
}
function test_revertTransferBalanceOverflow(address sender, address receiver, uint256 id, uint256 amount) public {
if (sender == receiver) return;
amount = bound(amount, 1, type(uint256).max);
uint256 overflowAmount = type(uint256).max - amount + 1;
token.mint(sender, id, amount);
vm.prank(sender);
token.transfer(receiver, id, amount);
token.mint(sender, id, overflowAmount);
vm.expectRevert();
vm.prank(sender);
token.transfer(receiver, id, overflowAmount);
}
function test_revertTransferFromBalanceUnderflow(address sender, address receiver, uint256 id, uint256 amount)
public
{
amount = bound(amount, 1, type(uint256).max);
vm.expectRevert();
vm.prank(sender);
token.transferFrom(sender, receiver, id, amount);
}
function test_revertTransferFromBalanceOverflow(address sender, address receiver, uint256 id, uint256 amount)
public
{
if (sender == receiver) return;
amount = bound(amount, 1, type(uint256).max);
uint256 overflowAmount = type(uint256).max - amount + 1;
token.mint(sender, id, amount);
vm.prank(sender);
token.transferFrom(sender, receiver, id, amount);
token.mint(sender, id, overflowAmount);
vm.expectRevert();
vm.prank(sender);
token.transferFrom(sender, receiver, id, overflowAmount);
}
function test_revertTransferFromNotAuthorized(address sender, address receiver, uint256 id, uint256 amount)
public
{
amount = bound(amount, 1, type(uint256).max);
token.mint(sender, id, amount);
vm.assume(sender != address(this));
vm.expectRevert();
token.transferFrom(sender, receiver, id, amount);
}
}