mirror of
https://github.com/lux-amm/v4-core.git
synced 2026-10-30 20:54:53 +00:00
405 lines
12 KiB
Solidity
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);
|
|
}
|
|
}
|