chore: introduce SNT V2 (#1)
This introduces an SNT V2 token implementation. It inherits from `MiniMeToken` and also comes with an `SNTTestnetController` that can be used on test networks for allowing minting of tokens by anyone. This makes the token controller more general and introduces an `open` property to enable/disable the faucet. Also adds a `destroyTokens()` function for completeness' sake.
This commit is contained in:
parent
3f2175ac56
commit
23de68feb5
|
@ -1 +1,10 @@
|
|||
FooTest:test_Example() (gas: 8662)
|
||||
TestDestroyTokens:testDeployment() (gas: 47764)
|
||||
TestDestroyTokens:test_DestroyTokenFaucetIsOpen() (gas: 133862)
|
||||
TestDestroyTokens:test_DestroyTokensAsOwner() (gas: 131266)
|
||||
TestDestroyTokens:test_RevertWhen_FaucetIsClosed() (gas: 16257)
|
||||
TestDestroyTokens:test_RevertWhen_NotEnoughBalance() (gas: 29029)
|
||||
TestGenerateTokens:testDeployment() (gas: 47719)
|
||||
TestGenerateTokens:test_GenerateTokensAsOwner() (gas: 119330)
|
||||
TestGenerateTokens:test_GenerateTokensOpenFaucet() (gas: 122001)
|
||||
TestGenerateTokens:test_RevertWhen_FaucetIsClosed() (gas: 16311)
|
||||
TestSNTV2:testDeployment() (gas: 47764)
|
|
@ -2,3 +2,9 @@
|
|||
branch = "v1"
|
||||
path = lib/forge-std
|
||||
url = https://github.com/foundry-rs/forge-std
|
||||
[submodule "lib/minime"]
|
||||
path = lib/minime
|
||||
url = https://github.com/vacp2p/minime
|
||||
[submodule "lib/openzeppelin-contracts"]
|
||||
path = lib/openzeppelin-contracts
|
||||
url = https://github.com/OpenZeppelin/openzeppelin-contracts
|
||||
|
|
103
README.md
103
README.md
|
@ -1,4 +1,4 @@
|
|||
# Foundry Template [![Github Actions][gha-badge]][gha] [![Foundry][foundry-badge]][foundry] [![License: MIT][license-badge]][license]
|
||||
# Status Network Token V2 [![Github Actions][gha-badge]][gha] [![Foundry][foundry-badge]][foundry] [![License: MIT][license-badge]][license]
|
||||
|
||||
[gha]: https://github.com/status-im/status-network-token-v2/actions
|
||||
[gha-badge]: https://github.com/status-im/status-network-token-v2/actions/workflows/ci.yml/badge.svg
|
||||
|
@ -7,93 +7,9 @@
|
|||
[license]: https://opensource.org/licenses/MIT
|
||||
[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg
|
||||
|
||||
A Foundry-based template for developing Solidity smart contracts, with sensible defaults.
|
||||
|
||||
This is a fork of [PaulRBerg's template](https://github.com/PaulRBerg/foundry-template) and adjusted to Vac's smart
|
||||
contracts unit's needs. See [Upstream differences](#upstream-differences) to learn more about how this template differs
|
||||
from Paul's.
|
||||
|
||||
## What's Inside
|
||||
|
||||
- [Forge](https://github.com/foundry-rs/foundry/blob/master/forge): compile, test, fuzz, format, and deploy smart
|
||||
contracts
|
||||
- [Forge Std](https://github.com/foundry-rs/forge-std): collection of helpful contracts and cheatcodes for testing
|
||||
- [Solhint Community](https://github.com/solhint-community/solhint-community): linter for Solidity code
|
||||
|
||||
## Getting Started
|
||||
|
||||
Click the [`Use this template`](https://github.com/vacp2p/foundry-template/generate) button at the top of the page to
|
||||
create a new repository with this repo as the initial state.
|
||||
|
||||
Or, if you prefer to install the template manually:
|
||||
|
||||
```sh
|
||||
$ mkdir my-project
|
||||
$ cd my-project
|
||||
$ forge init --template vacp2p/foundry-template
|
||||
$ pnpm install # install Solhint, Prettier, and other Node.js deps
|
||||
```
|
||||
|
||||
If this is your first time with Foundry, check out the
|
||||
[installation](https://github.com/foundry-rs/foundry#installation) instructions.
|
||||
|
||||
## Features
|
||||
|
||||
This template builds upon the frameworks and libraries mentioned above, so for details about their specific features,
|
||||
please consult their respective documentation.
|
||||
|
||||
For example, if you're interested in exploring Foundry in more detail, you should look at the
|
||||
[Foundry Book](https://book.getfoundry.sh/). In particular, you may be interested in reading the
|
||||
[Writing Tests](https://book.getfoundry.sh/forge/writing-tests.html) tutorial.
|
||||
|
||||
### Upstream differences
|
||||
|
||||
As mentioned above, this template is a fork with adjustments specific to the needs of Vac's smart contract service unit.
|
||||
These differences are:
|
||||
|
||||
- **Removal of [PRBTest](https://github.com/PaulRBerg/prb-test)** - In an attempt to keep dependence on third-party code
|
||||
low, we've decided to remove this library as a standard dependency of every project within Vac. If we do see a need
|
||||
for it, we might bring it back in the future.
|
||||
- **PROPERTIES.md** - For invariant testing and formal verification, we've introduced a `PROPERTIES.md` to document all
|
||||
protocol properties that must hold true.
|
||||
|
||||
### Sensible Defaults
|
||||
|
||||
This template comes with a set of sensible default configurations for you to use. These defaults can be found in the
|
||||
following files:
|
||||
|
||||
```text
|
||||
├── .editorconfig
|
||||
├── .gitignore
|
||||
├── .prettierignore
|
||||
├── .prettierrc.yml
|
||||
├── .solhint.json
|
||||
├── foundry.toml
|
||||
├── remappings.txt
|
||||
└── slither.config.json
|
||||
```
|
||||
|
||||
### VSCode Integration
|
||||
|
||||
This template is IDE agnostic, but for the best user experience, you may want to use it in VSCode alongside Nomic
|
||||
Foundation's [Solidity extension](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity).
|
||||
|
||||
For guidance on how to integrate a Foundry project in VSCode, please refer to this
|
||||
[guide](https://book.getfoundry.sh/config/vscode).
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
This template comes with GitHub Actions pre-configured. Your contracts will be linted and tested on every push and pull
|
||||
request made to the `main` branch.
|
||||
|
||||
You can edit the CI script in [.github/workflows/ci.yml](./.github/workflows/ci.yml).
|
||||
|
||||
## Writing Tests
|
||||
|
||||
If you would like to view the logs in the terminal output you can add the `-vvv` flag and use
|
||||
[console.log](https://book.getfoundry.sh/faq?highlight=console.log#how-do-i-use-consolelog).
|
||||
|
||||
This template comes with an example test contract [Foo.t.sol](./test/Foo.t.sol)
|
||||
This is the second iteration of [Status Network Token](https://github.com/status-im/status-network-token). The original
|
||||
version of the token uses a lot of legacy code. This repository implements a more modern version based on our
|
||||
[MiniMeToken](https://github.com/vacp2p/minime) fork.
|
||||
|
||||
## Usage
|
||||
|
||||
|
@ -188,14 +104,3 @@ $ forge test
|
|||
[guide](https://book.getfoundry.sh/projects/dependencies.html) in the book
|
||||
2. You don't have to create a `.env` file, but filling in the environment variables may be useful when debugging and
|
||||
testing against a fork.
|
||||
|
||||
## Related Efforts
|
||||
|
||||
- [abigger87/femplate](https://github.com/abigger87/femplate)
|
||||
- [cleanunicorn/ethereum-smartcontract-template](https://github.com/cleanunicorn/ethereum-smartcontract-template)
|
||||
- [foundry-rs/forge-template](https://github.com/foundry-rs/forge-template)
|
||||
- [FrankieIsLost/forge-template](https://github.com/FrankieIsLost/forge-template)
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under MIT.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 6d9d4f54876c2095f5aa79210869c8e17e30f55e
|
|
@ -0,0 +1 @@
|
|||
Subproject commit fd81a96f01cc42ef1c9a5399364968d0e07e9e90
|
|
@ -1 +1,3 @@
|
|||
forge-std/=lib/forge-std/src/
|
||||
@vacp2p/minime/contracts/=lib/minime/contracts/
|
||||
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity >=0.8.19 <=0.9.0;
|
||||
|
||||
import { Foo } from "../src/Foo.sol";
|
||||
import { BaseScript } from "./Base.s.sol";
|
||||
import { DeploymentConfig } from "./DeploymentConfig.s.sol";
|
||||
|
||||
import { SNTV2 } from "../src/SNTV2.sol";
|
||||
import { SNTTokenController } from "../src/SNTTokenController.sol";
|
||||
|
||||
contract Deploy is BaseScript {
|
||||
function run() public returns (Foo foo, DeploymentConfig deploymentConfig) {
|
||||
deploymentConfig = new DeploymentConfig(broadcaster);
|
||||
foo = new Foo();
|
||||
function run() public returns (SNTV2, SNTTokenController, DeploymentConfig) {
|
||||
DeploymentConfig deploymentConfig = new DeploymentConfig(broadcaster);
|
||||
(, string memory tokenName, string memory tokenSymbol, uint8 decimalUnits) =
|
||||
deploymentConfig.activeNetworkConfig();
|
||||
|
||||
vm.startBroadcast(broadcaster);
|
||||
SNTV2 sntV2 = new SNTV2(tokenName, decimalUnits, tokenSymbol);
|
||||
SNTTokenController controller = new SNTTokenController(payable(address(sntV2)), false);
|
||||
sntV2.changeController(payable(address(controller)));
|
||||
vm.stopBroadcast();
|
||||
|
||||
return (sntV2, controller, deploymentConfig);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ contract DeploymentConfig is Script {
|
|||
|
||||
struct NetworkConfig {
|
||||
address deployer;
|
||||
string tokenName;
|
||||
string tokenSymbol;
|
||||
uint8 decimalUnits;
|
||||
}
|
||||
|
||||
NetworkConfig public activeNetworkConfig;
|
||||
|
@ -27,7 +30,12 @@ contract DeploymentConfig is Script {
|
|||
}
|
||||
|
||||
function getOrCreateAnvilEthConfig() public view returns (NetworkConfig memory) {
|
||||
return NetworkConfig({ deployer: deployer });
|
||||
return NetworkConfig({
|
||||
deployer: deployer,
|
||||
tokenName: "Status Network Token",
|
||||
tokenSymbol: "SNT",
|
||||
decimalUnits: 18
|
||||
});
|
||||
}
|
||||
|
||||
// This function is a hack to have it excluded by `forge coverage` until
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity >=0.8.19;
|
||||
|
||||
contract Foo {
|
||||
function id(uint256 value) external pure returns (uint256) {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import { MiniMeBase } from "@vacp2p/minime/contracts/MiniMeBase.sol";
|
||||
import { TokenController } from "@vacp2p/minime/contracts/TokenController.sol";
|
||||
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";
|
||||
|
||||
/**
|
||||
* @title SNTController
|
||||
* @author r4bbit <r4bbit@status.im>
|
||||
* @dev Controller contract for SNTV2 token.
|
||||
* It's a no operation contract that can be replaced by controllers with more privileges.
|
||||
*/
|
||||
contract SNTController is TokenController, Ownable2Step {
|
||||
MiniMeBase public snt;
|
||||
|
||||
/**
|
||||
* @param _snt The address of the SNT token
|
||||
*/
|
||||
constructor(address payable _snt) {
|
||||
snt = MiniMeBase(_snt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice The owner of this contract can change the controller of the SNT token
|
||||
* Please, be sure that the owner is a trusted agent or 0x0 address.
|
||||
* @param _newController The address of the new controller
|
||||
*/
|
||||
function changeController(address payable _newController) public onlyOwner {
|
||||
snt.changeController(_newController);
|
||||
emit ControllerChanged(_newController);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev proxyPayment set to reject all Ether.
|
||||
*/
|
||||
function proxyPayment(address) public payable override returns (bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev onTransfer set to accept any transfer
|
||||
*/
|
||||
function onTransfer(address, address, uint256) public pure override returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev onApprove set to accept any approval
|
||||
*/
|
||||
function onApprove(address, address, uint256) public pure override returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Send tokens or ether from this contract to owner.
|
||||
* @param _token Token contract to recover, 0 to extract ether.
|
||||
*/
|
||||
function claimTokens(MiniMeBase _token) public onlyOwner {
|
||||
uint256 balance;
|
||||
if (address(_token) == address(0)) {
|
||||
balance = address(this).balance;
|
||||
payable(msg.sender).transfer(balance);
|
||||
return;
|
||||
} else {
|
||||
balance = _token.balanceOf(address(this));
|
||||
_token.transfer(msg.sender, balance);
|
||||
}
|
||||
emit ClaimedTokens(address(_token), msg.sender, balance);
|
||||
}
|
||||
|
||||
event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
|
||||
event ControllerChanged(address indexed _newController);
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import { MiniMeBase } from "@vacp2p/minime/contracts/MiniMeBase.sol";
|
||||
import { MiniMeToken } from "@vacp2p/minime/contracts/MiniMeToken.sol";
|
||||
import { TokenController } from "@vacp2p/minime/contracts/TokenController.sol";
|
||||
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";
|
||||
|
||||
/**
|
||||
* @title SNTTokenController
|
||||
* @author r4bbit <r4bbit@status.im>
|
||||
* @dev Testnet controller contract for SNTV2 token.
|
||||
* It's a no operation contract that allows for generating tokens.
|
||||
* This is useful for test networks.
|
||||
*/
|
||||
contract SNTTokenController is TokenController, Ownable2Step {
|
||||
error SNTTokenController_NotOpen();
|
||||
|
||||
MiniMeToken public snt;
|
||||
|
||||
bool public open;
|
||||
|
||||
/**
|
||||
* @param _snt The address of the SNT token
|
||||
*/
|
||||
constructor(address payable _snt, bool _open) {
|
||||
snt = MiniMeToken(_snt);
|
||||
open = _open;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice The owner of this contract can set the open variable
|
||||
* This is useful for test networks.
|
||||
* @param _open The new value for the open variable
|
||||
*/
|
||||
function setOpen(bool _open) public onlyOwner {
|
||||
open = _open;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice The owner of this contract can change the controller of the SNT token
|
||||
* Please, be sure that the owner is a trusted agent or 0x0 address.
|
||||
* @param _newController The address of the new controller
|
||||
*/
|
||||
function changeController(address payable _newController) public onlyOwner {
|
||||
snt.changeController(_newController);
|
||||
emit ControllerChanged(_newController);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev proxyPayment set to reject all Ether.
|
||||
*/
|
||||
function proxyPayment(address) public payable override returns (bool) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev onTransfer set to accept any transfer
|
||||
*/
|
||||
function onTransfer(address, address, uint256) public pure override returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev onApprove set to accept any approval
|
||||
*/
|
||||
function onApprove(address, address, uint256) public pure override returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Generate tokens for the given address.
|
||||
* @param _to The address that will receive the minted tokens.
|
||||
* @param _amount The amount of tokens to mint.
|
||||
*/
|
||||
function generateTokens(address _to, uint256 _amount) public {
|
||||
if (!open && msg.sender != owner()) {
|
||||
revert SNTTokenController_NotOpen();
|
||||
}
|
||||
snt.generateTokens(_to, _amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Destroy tokens for the given address.
|
||||
* @param _from The address that gets token removed.
|
||||
* @param _amount The amount of tokens to destroy.
|
||||
*/
|
||||
function destroyTokens(address _from, uint256 _amount) public {
|
||||
if (!open && msg.sender != owner()) {
|
||||
revert SNTTokenController_NotOpen();
|
||||
}
|
||||
snt.destroyTokens(_from, _amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Send tokens or ether from this contract to owner.
|
||||
* @param _token Token contract to recover, 0 to extract ether.
|
||||
*/
|
||||
function claimTokens(MiniMeBase _token) public onlyOwner {
|
||||
uint256 balance;
|
||||
if (address(_token) == address(0)) {
|
||||
balance = address(this).balance;
|
||||
payable(msg.sender).transfer(balance);
|
||||
return;
|
||||
} else {
|
||||
balance = _token.balanceOf(address(this));
|
||||
_token.transfer(msg.sender, balance);
|
||||
}
|
||||
emit ClaimedTokens(address(_token), msg.sender, balance);
|
||||
}
|
||||
|
||||
event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
|
||||
event ControllerChanged(address indexed _newController);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity >=0.8.19;
|
||||
|
||||
import { MiniMeToken } from "@vacp2p/minime/contracts/MiniMeToken.sol";
|
||||
|
||||
contract SNTV2 is MiniMeToken {
|
||||
constructor(
|
||||
string memory _tokenName,
|
||||
uint8 _decimalUnits,
|
||||
string memory _tokenSymbol
|
||||
)
|
||||
MiniMeToken(MiniMeToken(payable(address(0))), 0, _tokenName, _decimalUnits, _tokenSymbol, true)
|
||||
{ }
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity >=0.8.19 <0.9.0;
|
||||
|
||||
import { Test, console } from "forge-std/Test.sol";
|
||||
|
||||
import { Deploy } from "../script/Deploy.s.sol";
|
||||
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
|
||||
import { Foo } from "../src/Foo.sol";
|
||||
|
||||
contract FooTest is Test {
|
||||
Foo internal foo;
|
||||
DeploymentConfig internal deploymentConfig;
|
||||
|
||||
address internal deployer;
|
||||
|
||||
function setUp() public virtual {
|
||||
Deploy deployment = new Deploy();
|
||||
(foo, deploymentConfig) = deployment.run();
|
||||
}
|
||||
|
||||
function test_Example() external {
|
||||
console.log("Hello World");
|
||||
uint256 x = 42;
|
||||
assertEq(foo.id(x), x, "value mismatch");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity >=0.8.19;
|
||||
|
||||
import { Test } from "forge-std/Test.sol";
|
||||
import { Deploy } from "../script/Deploy.s.sol";
|
||||
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
|
||||
|
||||
import { NotEnoughBalance } from "@vacp2p/minime/contracts/MiniMeBase.sol";
|
||||
import { SNTV2 } from "../src/SNTV2.sol";
|
||||
import { SNTTokenController } from "../src/SNTTokenController.sol";
|
||||
|
||||
contract TestSNTV2 is Test {
|
||||
SNTV2 internal sntV2;
|
||||
SNTTokenController internal controller;
|
||||
DeploymentConfig internal deploymentConfig;
|
||||
|
||||
address internal deployer;
|
||||
|
||||
function setUp() public virtual {
|
||||
Deploy deployment = new Deploy();
|
||||
(sntV2, controller, deploymentConfig) = deployment.run();
|
||||
(address _deployer,,,) = deploymentConfig.activeNetworkConfig();
|
||||
deployer = _deployer;
|
||||
}
|
||||
|
||||
function testDeployment() public {
|
||||
(, string memory tokenName, string memory tokenSymbol, uint8 decimalUnits) =
|
||||
deploymentConfig.activeNetworkConfig();
|
||||
|
||||
assertEq(sntV2.name(), tokenName);
|
||||
assertEq(sntV2.symbol(), tokenSymbol);
|
||||
assertEq(sntV2.decimals(), decimalUnits);
|
||||
assertEq(sntV2.totalSupply(), 0);
|
||||
assertEq(sntV2.controller(), address(controller));
|
||||
|
||||
assertEq(controller.owner(), deployer);
|
||||
}
|
||||
}
|
||||
|
||||
contract TestGenerateTokens is TestSNTV2 {
|
||||
function setUp() public override {
|
||||
TestSNTV2.setUp();
|
||||
}
|
||||
|
||||
function test_RevertWhen_FaucetIsClosed() public {
|
||||
// ensure faucet is closed
|
||||
vm.prank(deployer);
|
||||
controller.setOpen(false);
|
||||
|
||||
vm.expectRevert(SNTTokenController.SNTTokenController_NotOpen.selector);
|
||||
controller.generateTokens(address(this), 100);
|
||||
}
|
||||
|
||||
function test_GenerateTokensAsOwner() public {
|
||||
vm.startPrank(deployer);
|
||||
controller.setOpen(false);
|
||||
|
||||
uint256 balanceBefore = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceBefore, 0);
|
||||
|
||||
controller.generateTokens(address(this), 100);
|
||||
uint256 balanceAfter = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceAfter, 100);
|
||||
}
|
||||
|
||||
function test_GenerateTokensOpenFaucet() public {
|
||||
// ensure faucet is open
|
||||
vm.prank(deployer);
|
||||
controller.setOpen(true);
|
||||
|
||||
uint256 balanceBefore = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceBefore, 0);
|
||||
|
||||
controller.generateTokens(address(this), 100);
|
||||
uint256 balanceAfter = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceAfter, 100);
|
||||
}
|
||||
}
|
||||
|
||||
contract TestDestroyTokens is TestSNTV2 {
|
||||
function setUp() public override {
|
||||
TestSNTV2.setUp();
|
||||
}
|
||||
|
||||
function test_RevertWhen_FaucetIsClosed() public {
|
||||
// ensure faucet is closed
|
||||
vm.prank(deployer);
|
||||
controller.setOpen(false);
|
||||
|
||||
vm.expectRevert(SNTTokenController.SNTTokenController_NotOpen.selector);
|
||||
controller.destroyTokens(address(this), 100);
|
||||
}
|
||||
|
||||
function test_RevertWhen_NotEnoughBalance() public {
|
||||
// ensure faucet is closed
|
||||
vm.prank(deployer);
|
||||
controller.setOpen(true);
|
||||
|
||||
vm.expectRevert(NotEnoughBalance.selector);
|
||||
controller.destroyTokens(address(this), 100);
|
||||
}
|
||||
|
||||
function test_DestroyTokensAsOwner() public {
|
||||
// ensure faucet is open
|
||||
vm.startPrank(deployer);
|
||||
controller.setOpen(false);
|
||||
|
||||
uint256 balanceBefore = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceBefore, 0);
|
||||
|
||||
controller.generateTokens(address(this), 100);
|
||||
uint256 balanceAfter = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceAfter, 100);
|
||||
|
||||
controller.destroyTokens(address(this), 100);
|
||||
balanceAfter = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceAfter, 0);
|
||||
}
|
||||
|
||||
function test_DestroyTokenFaucetIsOpen() public {
|
||||
// ensure faucet is open
|
||||
vm.prank(deployer);
|
||||
controller.setOpen(true);
|
||||
|
||||
uint256 balanceBefore = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceBefore, 0);
|
||||
|
||||
controller.generateTokens(address(this), 100);
|
||||
uint256 balanceAfter = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceAfter, 100);
|
||||
|
||||
controller.destroyTokens(address(this), 100);
|
||||
balanceAfter = sntV2.balanceOf(address(this));
|
||||
assertEq(balanceAfter, 0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue