Skip to content

Commit

Permalink
Local Render, Tests, and Four-digit Ids (#83)
Browse files Browse the repository at this point in the history
* add tests

* update github workflow

* fix max digits
  • Loading branch information
mshrieve authored Aug 3, 2022
1 parent f4bc50b commit c797f9b
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 33 deletions.
13 changes: 6 additions & 7 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
name: Tests
on: [push, pull_request]
on: [push]

name: test

jobs:
check:
name: Bibos
name: Bibos Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Install dependencies
run: forge install
- name: Run tests
run: forge test -vvv
2 changes: 1 addition & 1 deletion lib/solmate
13 changes: 6 additions & 7 deletions src/Bibos.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ contract Bibos is ERC721, Owned {

error InsufficentValue();
error MintedOut();
error ZeroMintAmount();
error TooManyBibos();
error InvalidTokenId();
error AmountNotAvailable();

/*//////////////////////////////////////////////////////////////
MODIFIERS
Expand All @@ -56,8 +55,8 @@ contract Bibos is ERC721, Owned {
_;
}

modifier OnlyPositiveMintAmount(uint256 _amount) {
if (_amount == 0) revert ZeroMintAmount();
modifier OnlyIfAvailableSupply(uint256 _amount) {
if (_amount + totalSupply > maxSupply) revert AmountNotAvailable();
_;
}

Expand Down Expand Up @@ -90,8 +89,8 @@ contract Bibos is ERC721, Owned {
public
payable
OnlyIfNotMintedOut
OnlyIfAvailableSupply(_amount)
OnlyIfYouPayEnough(_amount)
OnlyPositiveMintAmount(_amount)
{
for (; _amount > 0; ) {
_mint(msg.sender);
Expand All @@ -113,11 +112,11 @@ contract Bibos is ERC721, Owned {

function _mint(address _to) internal {
uint256 tokenId = totalSupply++;
seeds[tokenId] = _computeSeed(tokenId);
seeds[tokenId] = _seed(tokenId);
ERC721._mint(_to, tokenId);
}

function _computeSeed(uint256 _tokenId) internal view returns (bytes32) {
function _seed(uint256 _tokenId) internal view returns (bytes32) {
return keccak256(abi.encodePacked(msg.sender, block.timestamp, _tokenId));
}
}
6 changes: 1 addition & 5 deletions src/libraries/Body.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ library Body {
for (uint8 i = 0; i < 7; i++) {
uint256 bodySeed = uint256(keccak256(abi.encodePacked(_seed, "body", i)));
string memory bodyFill = Palette.bodyFill(_seed, i, _tokenId);
string memory bodyFill2 = Palette.bodyFill(
_seed,
i + 7,
_tokenId
);
string memory bodyFill2 = Palette.bodyFill(_seed, i + 7, _tokenId);

string memory radius = radii[i];

Expand Down
2 changes: 1 addition & 1 deletion src/libraries/Render.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ library Render {
}

function _name(uint256 _tokenId) internal pure returns (string memory) {
return string.concat("Bibo #", Util.uint256ToString(_tokenId));
return string.concat("Bibo ", Util.uint256ToString(_tokenId, 4));
}
}
20 changes: 20 additions & 0 deletions src/libraries/Util.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {Test, console2} from "forge-std/Test.sol";
/// @title the bibos utility library
/// @notice utility functions
library Util {
error NumberHasTooManyDigits();

/// @notice wraps a string in quotes and adds a space after
function quote(string memory value) internal pure returns (string memory) {
return string.concat('"', value, '" ');
Expand All @@ -19,6 +21,24 @@ library Util {
return string.concat('"', _key, '":', _value);
}

/// @notice converts a tokenId to string and pads to _digits digits
/// @dev tokenId must be less than 10**_digits
/// @param _tokenId, uint256, the tokenId
/// @param _digits, uint8, the number of digits to pad to
/// @return result the resulting string
function uint256ToString(uint256 _tokenId, uint8 _digits) internal pure returns (string memory result) {
uint256 max = 10**_digits;
if (_tokenId >= max) revert NumberHasTooManyDigits();
// add leading zeroes
result = uint256ToString(_tokenId + max);
assembly {
// cut off one character
result := add(result, 1)
// store new length = _digits
mstore(result, _digits)
}
}

/// @notice converts a uint256 to ascii representation, without leading zeroes
/// @param _value, uint256, the value to convert
/// @return result the resulting string
Expand Down
15 changes: 8 additions & 7 deletions src/scripts/local_render.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,31 @@ import {time} from "src/util/time.sol";

contract local_render is Test {
function run() external returns (string memory tokenURI) {
// vm.startPrank(0xa0Ee7A142d267C1f36714E4a8F75612F20a79720);

Bibos bibos = new Bibos();
uint256 price = bibos.price();
uint256 totalSupply = bibos.maxSupply();

// get current time to use as random seed
uint256 unixTime = time.getUnixTime();
// set block.timestamp
vm.warp(unixTime);

// compute a random tokenId
uint256 tokenId = unixTime % 1111;
uint256 tokenId = uint256(keccak256(abi.encode(unixTime))) % totalSupply;

// set the total supply
// (in storage slot 7)
vm.store(address(bibos), bytes32(uint256(7)), bytes32(tokenId));

// mint
vm.deal(address(this), .1 ether);
bibos.mint{value: .1 ether}();
vm.deal(address(this), price);
bibos.mint{value: price}();
tokenURI = bibos.tokenURI(tokenId);
}

function run(uint256 _amount) external returns (string[] memory tokenURIs) {
Bibos bibos = new Bibos();
uint256 price = bibos.price();

// get current time to use as random seed
uint256 unixTime = time.getUnixTime();
Expand All @@ -41,11 +42,11 @@ contract local_render is Test {

tokenURIs = new string[](_amount);

vm.deal(address(this), _amount * .1 ether);
vm.deal(address(this), _amount * price);
uint256 i;
for (; i < _amount; ++i) {
// mint
bibos.mint{value: .1 ether}();
bibos.mint{value: price}();
tokenURIs[i] = bibos.tokenURI(i);
}
}
Expand Down
78 changes: 73 additions & 5 deletions src/test/Bibos.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,89 @@ import {Bibos} from "../Bibos.sol";

contract BibosTest is Test {
Bibos bibos;
uint256 price;
uint256 maxSupply;

address payable alice = payable(address(1));
address payable brian = payable(address(2));
address payable carly = payable(address(3));

error InsufficentValue();
error MintedOut();
error ZeroMintAmount();
error InvalidTokenId();
error AmountNotAvailable();

function setUp() public {
vm.prank(alice);
bibos = new Bibos();
price = bibos.price();
maxSupply = bibos.maxSupply();
}

function testMint() public {
bibos.mint{value: bibos.price()}();
bibos.mint{value: price}();
assertEq(bibos.totalSupply(), 1);
assertEq(address(bibos).balance, price);
}

function testMintMultiple(uint8 _amount) public {
vm.assume(_amount > 0);
vm.assume(_amount <= 10);
bibos.mint{value: _amount * bibos.price()}(_amount);
function testMintWrongPrice(uint16 _value) public {
vm.assume(_value < 2**12);
vm.assume(_value != price);
vm.expectRevert(InsufficentValue.selector);
bibos.mint{value: _value}();
}

function testMintMultiple(uint16 _amount) public {
vm.assume(_amount <= maxSupply);
bibos.mint{value: _amount * price}(_amount);
assertEq(bibos.totalSupply(), _amount);
assertEq(address(bibos).balance, uint256(_amount) * price);
}

function testMintMultipleWrongPrice(uint16 _amount, uint16 _value) public {
vm.assume(_value < 2**12);
vm.assume(_amount > 0);
vm.assume(_amount <= maxSupply);
vm.assume(_value != uint256(_amount) * price);
vm.expectRevert(InsufficentValue.selector);
bibos.mint{value: _value}(_amount);
}

function testMintOverSupply(uint16 _amount) public {
vm.assume(_amount > maxSupply);
vm.expectRevert(AmountNotAvailable.selector);
bibos.mint{value: _amount * price}(_amount);
}

function testMintWhenMintedOut() public {
bibos.mint{value: maxSupply * price}(maxSupply);

vm.expectRevert(MintedOut.selector);
bibos.mint{value: price}();
}

function testMintMultipleWhenMintedOut(uint16 _amount) public {
vm.assume(_amount > maxSupply);
bibos.mint{value: maxSupply * price}(maxSupply);

vm.expectRevert(MintedOut.selector);
bibos.mint{value: _amount * price}(_amount);
}

function testWithdraw(uint16 _amount) public {
vm.assume(_amount <= maxSupply);
bibos.mint{value: _amount * price}(_amount);

vm.prank(brian);
vm.expectRevert("UNAUTHORIZED");
bibos.withdraw(carly);

vm.prank(alice);
bibos.withdraw(carly);

assertEq(address(bibos).balance, 0);
assertEq(carly.balance, _amount * price);
}

function testGetTokenURI() public {
Expand Down

0 comments on commit c797f9b

Please sign in to comment.