Added Terminus pool features

0. Capacity
1. Transferable
2. Burnable
pull/9/head
Neeraj Kashyap 2021-12-21 13:05:40 -08:00
rodzic aed0d9584c
commit 973e49526d
5 zmienionych plików z 616 dodań i 29 usunięć

Wyświetl plik

@ -75,7 +75,7 @@ contract ERC1155WithTerminusStorage is
{
require(
account != address(0),
"ERC1155: balance query for the zero address"
"ERC1155WithTerminusStorage: balance query for the zero address"
);
return LibTerminus.terminusStorage().poolBalances[id][account];
}
@ -96,7 +96,7 @@ contract ERC1155WithTerminusStorage is
{
require(
accounts.length == ids.length,
"ERC1155: accounts and ids length mismatch"
"ERC1155WithTerminusStorage: accounts and ids length mismatch"
);
uint256[] memory batchBalances = new uint256[](accounts.length);
@ -135,6 +135,18 @@ contract ERC1155WithTerminusStorage is
];
}
function isApprovedForPool(uint256 poolID, address operator)
public
view
returns (bool)
{
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
if (operator == ts.poolController[poolID]) {
return true;
}
return false;
}
/**
* @dev See {IERC1155-safeTransferFrom}.
*/
@ -146,8 +158,10 @@ contract ERC1155WithTerminusStorage is
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not owner nor approved"
from == _msgSender() ||
isApprovedForAll(from, _msgSender()) ||
isApprovedForPool(id, _msgSender()),
"ERC1155WithTerminusStorage: caller is not owner nor approved"
);
_safeTransferFrom(from, to, id, amount, data);
}
@ -164,7 +178,7 @@ contract ERC1155WithTerminusStorage is
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: transfer caller is not owner nor approved"
"ERC1155WithTerminusStorage: transfer caller is not owner nor approved"
);
_safeBatchTransferFrom(from, to, ids, amounts, data);
}
@ -188,7 +202,15 @@ contract ERC1155WithTerminusStorage is
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: transfer to the zero address");
require(
to != address(0),
"ERC1155WithTerminusStorage: transfer to the zero address"
);
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
require(
!ts.poolNotTransferable[id],
"ERC1155WithTerminusStorage: _safeTransferFrom -- pool is not transferable"
);
address operator = _msgSender();
@ -201,12 +223,10 @@ contract ERC1155WithTerminusStorage is
data
);
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
uint256 fromBalance = ts.poolBalances[id][from];
require(
fromBalance >= amount,
"ERC1155: insufficient balance for transfer"
"ERC1155WithTerminusStorage: insufficient balance for transfer"
);
unchecked {
ts.poolBalances[id][from] = fromBalance - amount;
@ -237,9 +257,12 @@ contract ERC1155WithTerminusStorage is
) internal virtual {
require(
ids.length == amounts.length,
"ERC1155: ids and amounts length mismatch"
"ERC1155WithTerminusStorage: ids and amounts length mismatch"
);
require(
to != address(0),
"ERC1155WithTerminusStorage: transfer to the zero address"
);
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
@ -254,7 +277,7 @@ contract ERC1155WithTerminusStorage is
uint256 fromBalance = ts.poolBalances[id][from];
require(
fromBalance >= amount,
"ERC1155: insufficient balance for transfer"
"ERC1155WithTerminusStorage: insufficient balance for transfer"
);
unchecked {
ts.poolBalances[id][from] = fromBalance - amount;
@ -291,7 +314,10 @@ contract ERC1155WithTerminusStorage is
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(
to != address(0),
"ERC1155WithTerminusStorage: mint to the zero address"
);
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
require(
ts.poolSupply[id] + amount <= ts.poolCapacity[id],
@ -309,6 +335,7 @@ contract ERC1155WithTerminusStorage is
data
);
ts.poolSupply[id] += amount;
ts.poolBalances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
@ -337,10 +364,13 @@ contract ERC1155WithTerminusStorage is
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(
to != address(0),
"ERC1155WithTerminusStorage: mint to the zero address"
);
require(
ids.length == amounts.length,
"ERC1155: ids and amounts length mismatch"
"ERC1155WithTerminusStorage: ids and amounts length mismatch"
);
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
@ -357,6 +387,7 @@ contract ERC1155WithTerminusStorage is
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; i++) {
ts.poolSupply[ids[i]] += amounts[i];
ts.poolBalances[ids[i]][to] += amounts[i];
}
@ -385,10 +416,23 @@ contract ERC1155WithTerminusStorage is
uint256 id,
uint256 amount
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
require(
from != address(0),
"ERC1155WithTerminusStorage: burn from the zero address"
);
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
require(
ts.poolBurnable[id],
"ERC1155WithTerminusStorage: _burn -- pool is not burnable"
);
address operator = _msgSender();
require(
operator == from || isApprovedForPool(id, operator),
"ERC1155WithTerminusStorage: _burn -- caller is neither owner nor approved"
);
_beforeTokenTransfer(
operator,
from,
@ -398,11 +442,14 @@ contract ERC1155WithTerminusStorage is
""
);
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
uint256 fromBalance = ts.poolBalances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
require(
fromBalance >= amount,
"ERC1155WithTerminusStorage: burn amount exceeds balance"
);
unchecked {
ts.poolBalances[id][from] = fromBalance - amount;
ts.poolSupply[id] -= amount;
}
emit TransferSingle(operator, from, address(0), id, amount);
@ -420,16 +467,35 @@ contract ERC1155WithTerminusStorage is
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
require(
from != address(0),
"ERC1155WithTerminusStorage: burn from the zero address"
);
require(
ids.length == amounts.length,
"ERC1155: ids and amounts length mismatch"
"ERC1155WithTerminusStorage: ids and amounts length mismatch"
);
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
bool approvedForPools = true;
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
for (uint256 i = 0; i < ids.length; i++) {
require(
ts.poolBurnable[ids[i]],
"ERC1155WithTerminusStorage: _burnBatch -- pool is not burnable"
);
if (!isApprovedForPool(ids[i], operator)) {
approvedForPools = false;
}
}
require(
from == _msgSender() || approvedForPools,
"ERC1155WithTerminusStorage: _burnBatch -- caller is neither owner nor approved"
);
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
for (uint256 i = 0; i < ids.length; i++) {
uint256 id = ids[i];
@ -438,10 +504,11 @@ contract ERC1155WithTerminusStorage is
uint256 fromBalance = ts.poolBalances[id][from];
require(
fromBalance >= amount,
"ERC1155: burn amount exceeds balance"
"ERC1155WithTerminusStorage: burn amount exceeds balance"
);
unchecked {
ts.poolBalances[id][from] = fromBalance - amount;
ts.poolSupply[id] -= amount;
}
}
@ -458,7 +525,10 @@ contract ERC1155WithTerminusStorage is
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC1155: setting approval status for self");
require(
owner != operator,
"ERC1155WithTerminusStorage: setting approval status for self"
);
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
ts.globalOperatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
@ -512,12 +582,16 @@ contract ERC1155WithTerminusStorage is
)
returns (bytes4 response) {
if (response != IERC1155Receiver.onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
revert(
"ERC1155WithTerminusStorage: ERC1155Receiver rejected tokens"
);
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
revert(
"ERC1155WithTerminusStorage: transfer to non ERC1155Receiver implementer"
);
}
}
}
@ -543,12 +617,16 @@ contract ERC1155WithTerminusStorage is
if (
response != IERC1155Receiver.onERC1155BatchReceived.selector
) {
revert("ERC1155: ERC1155Receiver rejected tokens");
revert(
"ERC1155WithTerminusStorage: ERC1155Receiver rejected tokens"
);
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
revert(
"ERC1155WithTerminusStorage: transfer to non ERC1155Receiver implementer"
);
}
}
}

Wyświetl plik

@ -31,8 +31,9 @@ library LibTerminus {
mapping(uint256 => uint256) poolCapacity;
mapping(uint256 => uint256) poolSupply;
mapping(uint256 => mapping(address => uint256)) poolBalances;
mapping(uint256 => bool) poolNotTransferable;
mapping(uint256 => bool) poolBurnable;
mapping(address => mapping(address => bool)) globalOperatorApprovals;
// TODO(zomglings): Add mappings for pool properties. E.g. poolTransferable, poolMintable, etc.
}
function terminusStorage()

Wyświetl plik

@ -12,7 +12,9 @@
* 3. Pool capacity: The total number of tokens that can be minted in that authorization pool.
* 4. Pool supply: The number of tokens that have actually been minted in that authorization pool.
* 5. Transferable: A boolean value which denotes whether or not tokens from that pool can be transfered
* between addresses.
* between addresses. (Note: Implemented by TerminusStorage.poolNotTransferable since we expect most
* pools to be transferable. This negation is better for storage + gas since false is default value
* in map to bool.)
* 6. Burnable: A boolean value which denotes whether or not tokens from that pool can be burned.
*/
@ -97,6 +99,14 @@ contract TerminusFacet is ERC1155WithTerminusStorage {
return LibTerminus.terminusStorage().poolCapacity[poolID];
}
function terminusPoolSupply(uint256 poolID)
external
view
returns (uint256)
{
return LibTerminus.terminusStorage().poolSupply[poolID];
}
function createSimplePool(uint256 _capacity) external returns (uint256) {
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
uint256 requiredPayment = ts.poolBasePrice;
@ -114,6 +124,35 @@ contract TerminusFacet is ERC1155WithTerminusStorage {
return LibTerminus.createSimplePool(_capacity);
}
function createPoolV1(
uint256 _capacity,
bool _transferable,
bool _burnable
) external returns (uint256) {
LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage();
// TODO(zomglings): Implement requiredPayment update based on pool features.
uint256 requiredPayment = ts.poolBasePrice;
IERC20 paymentTokenContract = _paymentTokenContract();
require(
paymentTokenContract.allowance(_msgSender(), address(this)) >=
requiredPayment,
"TerminusFacet: createPoolV1 -- Insufficient allowance on payment token"
);
paymentTokenContract.transferFrom(
msg.sender,
address(this),
requiredPayment
);
uint256 poolID = LibTerminus.createSimplePool(_capacity);
if (!_transferable) {
ts.poolNotTransferable[poolID] = true;
}
if (_burnable) {
ts.poolBurnable[poolID] = true;
}
return poolID;
}
function mint(
address to,
uint256 poolID,
@ -135,4 +174,12 @@ contract TerminusFacet is ERC1155WithTerminusStorage {
}
_mintBatch(to, poolIDs, amounts, data);
}
function burn(
address from,
uint256 poolID,
uint256 amount
) external {
_burn(from, poolID, amount);
}
}

Wyświetl plik

@ -98,6 +98,20 @@ class TerminusFacet:
self.assert_contract_is_instantiated()
return self.contract.balanceOfBatch.call(accounts, ids)
def burn(
self, from_: ChecksumAddress, pool_id: int, amount: int, transaction_config
) -> Any:
self.assert_contract_is_instantiated()
return self.contract.burn(from_, pool_id, amount, transaction_config)
def create_pool_v1(
self, _capacity: int, _transferable: bool, _burnable: bool, transaction_config
) -> Any:
self.assert_contract_is_instantiated()
return self.contract.createPoolV1(
_capacity, _transferable, _burnable, transaction_config
)
def create_simple_pool(self, _capacity: int, transaction_config) -> Any:
self.assert_contract_is_instantiated()
return self.contract.createSimplePool(_capacity, transaction_config)
@ -108,6 +122,10 @@ class TerminusFacet:
self.assert_contract_is_instantiated()
return self.contract.isApprovedForAll.call(account, operator)
def is_approved_for_pool(self, pool_id: int, operator: ChecksumAddress) -> Any:
self.assert_contract_is_instantiated()
return self.contract.isApprovedForPool.call(pool_id, operator)
def mint(
self,
to: ChecksumAddress,
@ -202,6 +220,10 @@ class TerminusFacet:
self.assert_contract_is_instantiated()
return self.contract.terminusPoolController.call(pool_id)
def terminus_pool_supply(self, pool_id: int) -> Any:
self.assert_contract_is_instantiated()
return self.contract.terminusPoolSupply.call(pool_id)
def total_pools(self) -> Any:
self.assert_contract_is_instantiated()
return self.contract.totalPools.call()
@ -282,6 +304,32 @@ def handle_balance_of_batch(args: argparse.Namespace) -> None:
print(result)
def handle_burn(args: argparse.Namespace) -> None:
network.connect(args.network)
contract = TerminusFacet(args.address)
transaction_config = get_transaction_config(args)
result = contract.burn(
from_=args.from_arg,
pool_id=args.pool_id,
amount=args.amount,
transaction_config=transaction_config,
)
print(result)
def handle_create_pool_v1(args: argparse.Namespace) -> None:
network.connect(args.network)
contract = TerminusFacet(args.address)
transaction_config = get_transaction_config(args)
result = contract.create_pool_v1(
_capacity=args.capacity_arg,
_transferable=args.transferable_arg,
_burnable=args.burnable_arg,
transaction_config=transaction_config,
)
print(result)
def handle_create_simple_pool(args: argparse.Namespace) -> None:
network.connect(args.network)
contract = TerminusFacet(args.address)
@ -299,6 +347,13 @@ def handle_is_approved_for_all(args: argparse.Namespace) -> None:
print(result)
def handle_is_approved_for_pool(args: argparse.Namespace) -> None:
network.connect(args.network)
contract = TerminusFacet(args.address)
result = contract.is_approved_for_pool(pool_id=args.pool_id, operator=args.operator)
print(result)
def handle_mint(args: argparse.Namespace) -> None:
network.connect(args.network)
contract = TerminusFacet(args.address)
@ -443,6 +498,13 @@ def handle_terminus_pool_controller(args: argparse.Namespace) -> None:
print(result)
def handle_terminus_pool_supply(args: argparse.Namespace) -> None:
network.connect(args.network)
contract = TerminusFacet(args.address)
result = contract.terminus_pool_supply(pool_id=args.pool_id)
print(result)
def handle_total_pools(args: argparse.Namespace) -> None:
network.connect(args.network)
contract = TerminusFacet(args.address)
@ -496,6 +558,29 @@ def generate_cli() -> argparse.ArgumentParser:
)
balance_of_batch_parser.set_defaults(func=handle_balance_of_batch)
burn_parser = subcommands.add_parser("burn")
add_default_arguments(burn_parser, True)
burn_parser.add_argument("--from-arg", required=True, help="Type: address")
burn_parser.add_argument("--pool-id", required=True, help="Type: uint256", type=int)
burn_parser.add_argument("--amount", required=True, help="Type: uint256", type=int)
burn_parser.set_defaults(func=handle_burn)
create_pool_v1_parser = subcommands.add_parser("create-pool-v1")
add_default_arguments(create_pool_v1_parser, True)
create_pool_v1_parser.add_argument(
"--capacity-arg", required=True, help="Type: uint256", type=int
)
create_pool_v1_parser.add_argument(
"--transferable-arg",
required=True,
help="Type: bool",
type=boolean_argument_type,
)
create_pool_v1_parser.add_argument(
"--burnable-arg", required=True, help="Type: bool", type=boolean_argument_type
)
create_pool_v1_parser.set_defaults(func=handle_create_pool_v1)
create_simple_pool_parser = subcommands.add_parser("create-simple-pool")
add_default_arguments(create_simple_pool_parser, True)
create_simple_pool_parser.add_argument(
@ -513,6 +598,16 @@ def generate_cli() -> argparse.ArgumentParser:
)
is_approved_for_all_parser.set_defaults(func=handle_is_approved_for_all)
is_approved_for_pool_parser = subcommands.add_parser("is-approved-for-pool")
add_default_arguments(is_approved_for_pool_parser, False)
is_approved_for_pool_parser.add_argument(
"--pool-id", required=True, help="Type: uint256", type=int
)
is_approved_for_pool_parser.add_argument(
"--operator", required=True, help="Type: address"
)
is_approved_for_pool_parser.set_defaults(func=handle_is_approved_for_pool)
mint_parser = subcommands.add_parser("mint")
add_default_arguments(mint_parser, True)
mint_parser.add_argument("--to", required=True, help="Type: address")
@ -640,6 +735,13 @@ def generate_cli() -> argparse.ArgumentParser:
)
terminus_pool_controller_parser.set_defaults(func=handle_terminus_pool_controller)
terminus_pool_supply_parser = subcommands.add_parser("terminus-pool-supply")
add_default_arguments(terminus_pool_supply_parser, False)
terminus_pool_supply_parser.add_argument(
"--pool-id", required=True, help="Type: uint256", type=int
)
terminus_pool_supply_parser.set_defaults(func=handle_terminus_pool_supply)
total_pools_parser = subcommands.add_parser("total-pools")
add_default_arguments(total_pools_parser, False)
total_pools_parser.set_defaults(func=handle_total_pools)

Wyświetl plik

@ -118,5 +118,364 @@ class TestPoolCreation(TerminusTestCase):
self.assertEqual(pool_capacity, 10)
class TestPoolOperations(TerminusTestCase):
@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
moonstream_diamond_address = cls.contracts["Diamond"]
diamond_moonstream = ERC20Facet.ERC20Facet(moonstream_diamond_address)
terminus_diamond_address = cls.terminus_contracts["Diamond"]
diamond_terminus = TerminusFacet.TerminusFacet(terminus_diamond_address)
diamond_terminus.set_payment_token(
moonstream_diamond_address, {"from": accounts[0]}
)
diamond_terminus.set_pool_base_price(1000, {"from": accounts[0]})
diamond_moonstream.mint(accounts[1], 1000000, {"from": accounts[0]})
diamond_moonstream.approve(
terminus_diamond_address, 1000000, {"from": accounts[1]}
)
cls.diamond_terminus = diamond_terminus
cls.diamond_moonstream = diamond_moonstream
def setUp(self) -> None:
self.diamond_terminus.create_simple_pool(10, {"from": accounts[1]})
def test_mint(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
balance = self.diamond_terminus.balance_of(accounts[2].address, pool_id)
self.assertEqual(balance, 1)
supply = self.diamond_terminus.terminus_pool_supply(pool_id)
self.assertEqual(supply, 1)
def test_mint_fails_if_it_exceeds_capacity(self):
pool_id = self.diamond_terminus.total_pools()
with self.assertRaises(Exception):
self.diamond_terminus.mint(
accounts[2], pool_id, 11, b"", {"from": accounts[1]}
)
balance = self.diamond_terminus.balance_of(accounts[2].address, pool_id)
self.assertEqual(balance, 0)
supply = self.diamond_terminus.terminus_pool_supply(pool_id)
self.assertEqual(supply, 0)
def test_mint_batch(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint_batch(
accounts[2].address,
pool_i_ds=[pool_id],
amounts=[1],
data=b"",
transaction_config={"from": accounts[1]},
)
balance = self.diamond_terminus.balance_of(accounts[2].address, pool_id)
self.assertEqual(balance, 1)
supply = self.diamond_terminus.terminus_pool_supply(pool_id)
self.assertEqual(supply, 1)
def test_mint_batch_fails_if_it_exceeds_capacity(self):
pool_id = self.diamond_terminus.total_pools()
with self.assertRaises(Exception):
self.diamond_terminus.mint_batch(
accounts[2].address,
pool_i_ds=[pool_id],
amounts=[11],
data=b"",
transaction_config={"from": accounts[1]},
)
balance = self.diamond_terminus.balance_of(accounts[2].address, pool_id)
self.assertEqual(balance, 0)
supply = self.diamond_terminus.terminus_pool_supply(pool_id)
self.assertEqual(supply, 0)
def test_transfer(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
initial_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
self.diamond_terminus.safe_transfer_from(
accounts[2].address,
accounts[3].address,
pool_id,
1,
b"",
{"from": accounts[2]},
)
final_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
final_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
self.assertEqual(final_sender_balance, initial_sender_balance - 1)
self.assertEqual(final_receiver_balance, initial_receiver_balance + 1)
def test_transfer_as_pool_controller(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
initial_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
self.diamond_terminus.safe_transfer_from(
accounts[2].address,
accounts[3].address,
pool_id,
1,
b"",
{"from": accounts[1]},
)
final_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
final_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
self.assertEqual(final_sender_balance, initial_sender_balance - 1)
self.assertEqual(final_receiver_balance, initial_receiver_balance + 1)
def test_transfer_as_unauthorized_recipient(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
initial_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
with self.assertRaises(Exception):
self.diamond_terminus.safe_transfer_from(
accounts[2].address,
accounts[3].address,
pool_id,
1,
b"",
{"from": accounts[3]},
)
final_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
final_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
self.assertEqual(final_sender_balance, initial_sender_balance)
self.assertEqual(final_receiver_balance, initial_receiver_balance)
def test_transfer_as_unauthorized_unrelated_party(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
initial_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
with self.assertRaises(Exception):
self.diamond_terminus.safe_transfer_from(
accounts[2].address,
accounts[3].address,
pool_id,
1,
b"",
{"from": accounts[4]},
)
final_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
final_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
self.assertEqual(final_sender_balance, initial_sender_balance)
self.assertEqual(final_receiver_balance, initial_receiver_balance)
def test_burn_fails_as_token_owner(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
initial_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
with self.assertRaises(Exception):
self.diamond_terminus.burn(
accounts[2].address, pool_id, 1, {"from": accounts[2]}
)
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
final_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.assertEqual(final_pool_supply, initial_pool_supply)
self.assertEqual(final_owner_balance, initial_owner_balance)
def test_burn_fails_as_pool_controller(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
initial_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
with self.assertRaises(Exception):
self.diamond_terminus.burn(
accounts[2].address, pool_id, 1, {"from": accounts[1]}
)
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
final_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.assertEqual(final_pool_supply, initial_pool_supply)
self.assertEqual(final_owner_balance, initial_owner_balance)
def test_burn_fails_as_third_party(self):
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
initial_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
with self.assertRaises(Exception):
self.diamond_terminus.burn(
accounts[2].address, pool_id, 1, {"from": accounts[3]}
)
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
final_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.assertEqual(final_pool_supply, initial_pool_supply)
self.assertEqual(final_owner_balance, initial_owner_balance)
class TestCreatePoolV1(TestPoolOperations):
def setUp(self):
self.diamond_terminus.create_pool_v1(10, True, False, {"from": accounts[1]})
def test_nontransferable_pool(self):
self.diamond_terminus.create_pool_v1(10, False, False, {"from": accounts[1]})
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
initial_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
with self.assertRaises(Exception):
self.diamond_terminus.safe_transfer_from(
accounts[2].address,
accounts[3].address,
pool_id,
1,
b"",
{"from": accounts[2]},
)
final_sender_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
final_receiver_balance = self.diamond_terminus.balance_of(
accounts[3].address, pool_id
)
self.assertEqual(final_sender_balance, initial_sender_balance)
self.assertEqual(final_receiver_balance, initial_receiver_balance)
def test_burnable_pool_burn_as_token_owner(self):
self.diamond_terminus.create_pool_v1(10, True, True, {"from": accounts[1]})
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
initial_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.diamond_terminus.burn(
accounts[2].address, pool_id, 1, {"from": accounts[2]}
)
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
final_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.assertEqual(final_pool_supply, initial_pool_supply - 1)
self.assertEqual(final_owner_balance, initial_owner_balance - 1)
def test_burnable_pool_burn_as_pool_controller(self):
self.diamond_terminus.create_pool_v1(10, True, True, {"from": accounts[1]})
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
initial_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.diamond_terminus.burn(
accounts[2].address, pool_id, 1, {"from": accounts[1]}
)
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
final_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.assertEqual(final_pool_supply, initial_pool_supply - 1)
self.assertEqual(final_owner_balance, initial_owner_balance - 1)
def test_burnable_pool_burn_as_unauthorized_third_party(self):
self.diamond_terminus.create_pool_v1(10, True, True, {"from": accounts[1]})
pool_id = self.diamond_terminus.total_pools()
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
initial_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
with self.assertRaises(Exception):
self.diamond_terminus.burn(
accounts[2].address, pool_id, 1, {"from": accounts[3]}
)
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
final_owner_balance = self.diamond_terminus.balance_of(
accounts[2].address, pool_id
)
self.assertEqual(final_pool_supply, initial_pool_supply)
self.assertEqual(final_owner_balance, initial_owner_balance)
if __name__ == "__main__":
unittest.main()