-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Merge pull request #3 from reservoir-protocol/liquidt-term
Liquidt term
- Loading branch information
Showing
2 changed files
with
291 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
import {IERC1155} from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol"; | ||
|
||
import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; | ||
|
||
import {ERC1155Supply} from "openzeppelin-contracts/contracts/token/ERC1155/extensions/ERC1155Supply.sol"; | ||
|
||
contract LiquidTerm is ERC20 { | ||
uint256 public immutable tokenId; | ||
|
||
address public immutable registry; | ||
|
||
constructor( | ||
string memory name_, | ||
string memory symbol_, | ||
address registry_, | ||
uint256 tokenId_ | ||
) ERC20(name_, symbol_) { | ||
registry = registry_; | ||
tokenId = tokenId_; | ||
} | ||
|
||
function totalSupply() public view override returns (uint256) { | ||
return ERC1155Supply(registry).totalSupply(tokenId); | ||
} | ||
|
||
function balanceOf(address account) public view override returns (uint256) { | ||
return IERC1155(registry).balanceOf(account, tokenId); | ||
} | ||
|
||
function _transfer( | ||
address from, | ||
address to, | ||
uint256 amount | ||
) internal override { | ||
IERC1155(registry).safeTransferFrom(from, to, tokenId, amount, ""); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.24; | ||
|
||
import {Term} from "src/Term.sol"; | ||
import {LiquidTerm} from "src/LiquidTerm.sol"; | ||
|
||
import {Test} from "forge-std/Test.sol"; | ||
import {console} from "forge-std/console.sol"; | ||
|
||
contract LiquidTermTest is Test { | ||
Term term; | ||
|
||
LiquidTerm lTerm00; | ||
LiquidTerm lTerm01; | ||
LiquidTerm lTerm02; | ||
LiquidTerm lTerm03; | ||
|
||
address eoa1 = vm.addr(1); | ||
address eoa2 = vm.addr(2); | ||
address eoa3 = vm.addr(3); | ||
address eoa4 = vm.addr(4); | ||
|
||
function setUp() external { | ||
term = new Term(address(this), "https://reservoir.xyz"); | ||
|
||
lTerm00 = new LiquidTerm("Liquid Term", "ltrUSD-00", address(term), 0); | ||
lTerm01 = new LiquidTerm("Liquid Term", "ltrUSD-01", address(term), 1); | ||
lTerm02 = new LiquidTerm("Liquid Term", "ltrUSD-02", address(term), 2); | ||
lTerm03 = new LiquidTerm("Liquid Term", "ltrUSD-03", address(term), 3); | ||
} | ||
|
||
function testInitialState() external { | ||
assertEq(lTerm00.tokenId(), 0); | ||
assertEq(lTerm00.registry(), address(term)); | ||
|
||
assertEq(lTerm00.symbol(), "ltrUSD-00"); | ||
assertEq(lTerm00.name(), "Liquid Term"); | ||
|
||
assertEq(lTerm01.tokenId(), 1); | ||
assertEq(lTerm01.registry(), address(term)); | ||
|
||
assertEq(lTerm02.symbol(), "ltrUSD-02"); | ||
assertEq(lTerm02.name(), "Liquid Term"); | ||
|
||
assertEq(lTerm02.tokenId(), 2); | ||
assertEq(lTerm02.registry(), address(term)); | ||
|
||
assertEq(lTerm02.symbol(), "ltrUSD-02"); | ||
assertEq(lTerm02.name(), "Liquid Term"); | ||
|
||
assertEq(lTerm03.tokenId(), 3); | ||
assertEq(lTerm03.registry(), address(term)); | ||
|
||
assertEq(lTerm03.symbol(), "ltrUSD-03"); | ||
assertEq(lTerm03.name(), "Liquid Term"); | ||
} | ||
|
||
function testBalanceAndTotalSupply() external { | ||
term.grantRole(term.MINTER(), address(this)); | ||
|
||
term.mint(eoa1, 0, 1_000e18); | ||
term.mint(eoa2, 1, 1_000e18); | ||
term.mint(eoa3, 2, 1_000e18); | ||
term.mint(eoa4, 3, 1_000e18); | ||
|
||
assertEq(term.balanceOf(eoa1, 0), 1_000e18); | ||
assertEq(term.balanceOf(eoa2, 1), 1_000e18); | ||
assertEq(term.balanceOf(eoa3, 2), 1_000e18); | ||
assertEq(term.balanceOf(eoa4, 3), 1_000e18); | ||
|
||
assertEq(term.totalSupply(0), 1_000e18); | ||
assertEq(term.totalSupply(1), 1_000e18); | ||
assertEq(term.totalSupply(2), 1_000e18); | ||
assertEq(term.totalSupply(3), 1_000e18); | ||
|
||
assertEq(lTerm00.totalSupply(), 1_000e18); | ||
assertEq(lTerm01.totalSupply(), 1_000e18); | ||
assertEq(lTerm02.totalSupply(), 1_000e18); | ||
assertEq(lTerm03.totalSupply(), 1_000e18); | ||
|
||
assertEq(lTerm00.balanceOf(eoa1), 1_000e18); | ||
assertEq(lTerm00.balanceOf(eoa2), 0); | ||
assertEq(lTerm00.balanceOf(eoa3), 0); | ||
assertEq(lTerm00.balanceOf(eoa4), 0); | ||
|
||
assertEq(lTerm01.balanceOf(eoa1), 0); | ||
assertEq(lTerm01.balanceOf(eoa2), 1_000e18); | ||
assertEq(lTerm01.balanceOf(eoa3), 0); | ||
assertEq(lTerm01.balanceOf(eoa4), 0); | ||
|
||
assertEq(lTerm02.balanceOf(eoa1), 0); | ||
assertEq(lTerm02.balanceOf(eoa2), 0); | ||
assertEq(lTerm02.balanceOf(eoa3), 1_000e18); | ||
assertEq(lTerm02.balanceOf(eoa4), 0); | ||
|
||
assertEq(lTerm03.balanceOf(eoa1), 0); | ||
assertEq(lTerm03.balanceOf(eoa2), 0); | ||
assertEq(lTerm03.balanceOf(eoa3), 0); | ||
assertEq(lTerm03.balanceOf(eoa4), 1_000e18); | ||
} | ||
|
||
function testTransfer() external { | ||
address receiver = vm.addr(uint256(keccak256("receiver"))); | ||
|
||
term.grantRole(term.MINTER(), address(this)); | ||
|
||
term.mint(eoa1, 0, 1_000e18); | ||
term.mint(eoa2, 1, 1_000e18); | ||
term.mint(eoa3, 2, 1_000e18); | ||
term.mint(eoa4, 3, 1_000e18); | ||
|
||
// eoa1 | ||
|
||
assertEq(lTerm00.balanceOf(receiver), 0); | ||
assertEq(lTerm00.balanceOf(eoa1), 1_000e18); | ||
|
||
vm.prank(eoa1); | ||
term.setApprovalForAll(address(lTerm00), true); | ||
|
||
vm.prank(eoa1); | ||
lTerm00.transfer(receiver, 1e18); | ||
|
||
assertEq(lTerm00.balanceOf(receiver), 1e18); | ||
assertEq(lTerm00.balanceOf(eoa1), 999e18); | ||
|
||
// eoa2 | ||
|
||
assertEq(lTerm01.balanceOf(receiver), 0); | ||
assertEq(lTerm01.balanceOf(eoa2), 1_000e18); | ||
|
||
vm.prank(eoa2); | ||
term.setApprovalForAll(address(lTerm01), true); | ||
|
||
vm.prank(eoa2); | ||
lTerm01.transfer(receiver, 1e18); | ||
|
||
assertEq(lTerm01.balanceOf(receiver), 1e18); | ||
assertEq(lTerm01.balanceOf(eoa2), 999e18); | ||
|
||
// eoa3 | ||
|
||
assertEq(lTerm02.balanceOf(receiver), 0); | ||
assertEq(lTerm02.balanceOf(eoa3), 1_000e18); | ||
|
||
vm.prank(eoa3); | ||
term.setApprovalForAll(address(lTerm02), true); | ||
|
||
vm.prank(eoa3); | ||
lTerm02.transfer(receiver, 1e18); | ||
|
||
assertEq(lTerm02.balanceOf(receiver), 1e18); | ||
assertEq(lTerm02.balanceOf(eoa3), 999e18); | ||
|
||
// eoa4 | ||
|
||
assertEq(lTerm03.balanceOf(receiver), 0); | ||
assertEq(lTerm03.balanceOf(eoa4), 1_000e18); | ||
|
||
vm.prank(eoa4); | ||
term.setApprovalForAll(address(lTerm03), true); | ||
|
||
vm.prank(eoa4); | ||
lTerm03.transfer(receiver, 1e18); | ||
|
||
assertEq(lTerm03.balanceOf(receiver), 1e18); | ||
assertEq(lTerm03.balanceOf(eoa4), 999e18); | ||
} | ||
|
||
function testTransferFrom() external { | ||
address receiver = vm.addr(uint256(keccak256("receiver"))); | ||
|
||
term.grantRole(term.MINTER(), address(this)); | ||
|
||
term.mint(eoa1, 0, 1_000e18); | ||
term.mint(eoa2, 1, 1_000e18); | ||
term.mint(eoa3, 2, 1_000e18); | ||
term.mint(eoa4, 3, 1_000e18); | ||
|
||
// eoa1 | ||
|
||
assertEq(lTerm00.balanceOf(receiver), 0); | ||
assertEq(lTerm00.balanceOf(eoa1), 1_000e18); | ||
|
||
vm.prank(eoa1); | ||
term.setApprovalForAll(address(lTerm00), true); | ||
|
||
vm.prank(eoa1); | ||
lTerm00.approve(address(this), 1e18); | ||
|
||
lTerm00.transferFrom(eoa1, receiver, 1e18); | ||
|
||
assertEq(lTerm00.balanceOf(receiver), 1e18); | ||
assertEq(lTerm00.balanceOf(eoa1), 999e18); | ||
|
||
assertEq(lTerm00.allowance(eoa1, receiver), 0); | ||
|
||
// eoa2 | ||
|
||
assertEq(lTerm01.balanceOf(receiver), 0); | ||
assertEq(lTerm01.balanceOf(eoa2), 1_000e18); | ||
|
||
vm.prank(eoa2); | ||
term.setApprovalForAll(address(lTerm01), true); | ||
|
||
vm.prank(eoa2); | ||
lTerm01.approve(address(this), 1e18); | ||
|
||
lTerm01.transferFrom(eoa2, receiver, 1e18); | ||
|
||
assertEq(lTerm01.balanceOf(receiver), 1e18); | ||
assertEq(lTerm01.balanceOf(eoa2), 999e18); | ||
|
||
assertEq(lTerm01.allowance(eoa2, receiver), 0); | ||
|
||
// eoa3 | ||
|
||
assertEq(lTerm02.balanceOf(receiver), 0); | ||
assertEq(lTerm02.balanceOf(eoa3), 1_000e18); | ||
|
||
vm.prank(eoa3); | ||
term.setApprovalForAll(address(lTerm02), true); | ||
|
||
vm.prank(eoa3); | ||
lTerm02.approve(address(this), 1e18); | ||
|
||
lTerm02.transferFrom(eoa3, receiver, 1e18); | ||
|
||
assertEq(lTerm02.balanceOf(receiver), 1e18); | ||
assertEq(lTerm02.balanceOf(eoa3), 999e18); | ||
|
||
assertEq(lTerm02.allowance(eoa3, receiver), 0); | ||
|
||
// eoa4 | ||
|
||
assertEq(lTerm03.balanceOf(receiver), 0); | ||
assertEq(lTerm03.balanceOf(eoa4), 1_000e18); | ||
|
||
vm.prank(eoa4); | ||
term.setApprovalForAll(address(lTerm03), true); | ||
|
||
vm.prank(eoa4); | ||
lTerm03.approve(address(this), 1e18); | ||
|
||
lTerm03.transferFrom(eoa4, receiver, 1e18); | ||
|
||
assertEq(lTerm03.balanceOf(receiver), 1e18); | ||
assertEq(lTerm03.balanceOf(eoa4), 999e18); | ||
|
||
assertEq(lTerm03.allowance(eoa2, receiver), 0); | ||
} | ||
} |