Skip to content

Commit

Permalink
deployERC20For cov
Browse files Browse the repository at this point in the history
  • Loading branch information
simplemachine92 authored Apr 2, 2024
1 parent 63e6b80 commit 02c2847
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
12 changes: 12 additions & 0 deletions test/trees/JBTokens/deployERC20For.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
TestDeployERC20For_Local
├── when bytes length EQ zero
│ └── it will revert EMPTY_NAME
├── when symbol length EQ zero
│ └── it will revert EMPTY_SYMBOL
├── when project already has a configured token
│ └── it will revert PROJECT_ALREADY_HAS_TOKEN
└── when happy path
├── given a salt is provided
│ └── it will create and initialize a deterministic clone based on the msgsender and salt
└── given a salt is not provided
└── it will clone and initialize a indeterministically generated clone
3 changes: 2 additions & 1 deletion test/units/static/JBTokens/JBTokensSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ Tests relative to this contract will be dependent on mock calls/emits and stdSto
contract JBTokensSetup is JBTest {
// Mocks
IJBDirectory public directory = IJBDirectory(makeAddr("directory"));
IJBToken public jbToken = IJBToken(makeAddr("juicayy"));
IJBToken public jbToken;

// Target Contract
IJBTokens public _tokens;

function tokensSetup() public virtual {
// Instantiate the contract being tested
jbToken = new JBERC20();
_tokens = new JBTokens(directory, jbToken);
}
}
89 changes: 89 additions & 0 deletions test/units/static/JBTokens/TestDeployERC20ForUnits.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import /* {*} from */ "../../../helpers/TestBaseWorkflow.sol";
import {JBTokensSetup} from "./JBTokensSetup.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";

contract TestDeployERC20ForUnits_Local is JBTokensSetup {
uint256 _projectId = 1;
string _name = "Juice";
string _symbol = "JBX";
IJBToken _token = IJBToken(makeAddr("JBX"));

function setUp() public {
super.tokensSetup();
}

modifier whenCallerIsController() {
// mock call to JBDirectory controllerOf
mockExpect(
address(directory), abi.encodeCall(IJBDirectory.controllerOf, (_projectId)), abi.encode(address(this))
);

_;
}

function test_WhenNameLengthEQZero() external whenCallerIsController {
// it will revert EMPTY_NAME

vm.expectRevert(abi.encodeWithSignature("EMPTY_NAME()"));
_tokens.deployERC20For({projectId: _projectId, name: "", symbol: _symbol, salt: bytes32(0)});
}

function test_WhenSymbolLengthEQZero() external whenCallerIsController {
// it will revert EMPTY_SYMBOL

vm.expectRevert(abi.encodeWithSignature("EMPTY_SYMBOL()"));
_tokens.deployERC20For({projectId: _projectId, name: _name, symbol: "", salt: bytes32(0)});
}

function test_WhenProjectAlreadyHasAConfiguredToken() external whenCallerIsController {
// it will revert PROJECT_ALREADY_HAS_TOKEN

// Find the storage slot to set credit balance
bytes32 tokenOfSlot = keccak256(abi.encode(_projectId, uint256(0)));

// Set storage
vm.store(address(_tokens), tokenOfSlot, bytes32(uint256(uint160(address(_token)))));

// Ensure it's set
IJBToken _storedToken = _tokens.tokenOf(_projectId);
assertEq(address(_storedToken), address(_token));

vm.expectRevert(abi.encodeWithSignature("PROJECT_ALREADY_HAS_TOKEN()"));
_tokens.deployERC20For({projectId: _projectId, name: _name, symbol: _symbol, salt: bytes32(0)});
}

modifier whenHappyPath() {
_;
}

function test_GivenASaltIsProvided() external whenHappyPath whenCallerIsController {
// it will create and initialize a deterministic clone based on the msgsender and salt

bytes32 salt = bytes32(uint256(1));
bytes32 hashedSalt = keccak256(abi.encode(address(this), salt));
address deployer = address(_tokens);
address token = address(jbToken);

address predicted = Clones.predictDeterministicAddress(token, hashedSalt, deployer);

vm.expectEmit();
emit IJBTokens.DeployERC20(_projectId, IJBToken(predicted), _name, _symbol, salt, address(this));

IJBToken deployedToken =
_tokens.deployERC20For({projectId: _projectId, name: _name, symbol: _symbol, salt: salt});

assertEq(predicted, address(deployedToken));
}

function test_GivenASaltIsNotProvided() external whenHappyPath whenCallerIsController {
// it will clone and initialize a indeterministically generated clone

IJBToken deployedToken =
_tokens.deployERC20For({projectId: _projectId, name: _name, symbol: _symbol, salt: bytes32(0)});

if (address(deployedToken) == address(0)) revert();
}
}

0 comments on commit 02c2847

Please sign in to comment.