Skip to content

Commit

Permalink
🔥 Simplify mocks
Browse files Browse the repository at this point in the history
  • Loading branch information
lajarre committed Feb 7, 2023
1 parent 86afd11 commit e82a3a3
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 136 deletions.
97 changes: 19 additions & 78 deletions test/MoltenCampaign.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@ import "forge-std/Test.sol";
import {MoltenCampaign, MoltenCampaignMarket} from "../src/MoltenCampaign.sol";
import {MToken} from "../src/MToken.sol";
import {ERC20VotesMintable} from "./helpers/ERC20VotesMintable.sol";
import {ERC20VotesMintableMock, ERC20VotesMintableFailedMock} from "./helpers/ERC20VotesMintable.sol";
import {MTokenMock, MTokenFailingMock} from "./helpers/MTokenMock.sol";
import {ERC20VotesMintableMock} from "./helpers/ERC20VotesMintable.sol";
import {MTokenMock} from "./helpers/MTokenMock.sol";

abstract contract TestBase is Test {
uint256 public threshold;
uint128 public duration;
uint128 public cooldownDuration;
address public representative = address(0x123);
MoltenCampaign public mc;
}

abstract contract TestBaseDefault is TestBase {
ERC20VotesMintableMock public daoToken;
MTokenMock public mToken;

Expand All @@ -40,82 +38,25 @@ abstract contract TestBaseDefault is TestBase {
mc = new MoltenCampaign(representative, address(mcm), address(mToken));
mToken.transferOwnership(address(mc));
}
}

abstract contract TestBaseFailingTransfer is TestBase {
ERC20VotesMintableFailedMock public daoToken;
MTokenMock public mToken;

function setUp() public virtual {
daoToken = new ERC20VotesMintableFailedMock(
"DAO governance token",
"GT"
);
threshold = 1;
duration = 1;
cooldownDuration = 1;
MoltenCampaignMarket mcm = new MoltenCampaignMarket(
address(daoToken),
threshold,
duration,
cooldownDuration
);
vm.prank(representative);
mToken = new MTokenMock(
string.concat("Molten ", daoToken.name()),
string.concat("m", daoToken.symbol()), // [XXX] Add campaigner (delegate) name
address(this)
);
mc = new MoltenCampaign(representative, address(mcm), address(mToken));
mToken.transferOwnership(address(mc));
}

function setFail() public virtual {
function setFailTransfer() public virtual {
daoToken.setFail();
}

function unsetFail() public virtual {
function unsetFailTransfer() public virtual {
daoToken.unsetFail();
}
}

abstract contract TestBaseFailingMint is TestBase {
ERC20VotesMintableMock public daoToken;
MTokenFailingMock public mToken;

function setUp() public virtual {
daoToken = new ERC20VotesMintableMock("DAO governance token", "GT");
threshold = 1;
duration = 1;
cooldownDuration = 1;
MoltenCampaignMarket mcm = new MoltenCampaignMarket(
address(daoToken),
threshold,
duration,
cooldownDuration
);
vm.prank(representative);
mToken = new MTokenFailingMock(
string.concat("Molten ", daoToken.name()),
string.concat("m", daoToken.symbol()), // [XXX] Add campaigner (delegate) name
address(this)
);
mc = new MoltenCampaign(representative, address(mcm), address(mToken));
mToken.transferOwnership(address(mc));

setFail();
}

function setFail() public virtual {
function setFailMint() public virtual {
mToken.setFail();
}

function unsetFail() public virtual {
function unsetFailMint() public virtual {
mToken.unsetFail();
}
}

contract StakeTest is TestBaseDefault {
contract StakeTest is TestBase {
address public staker;
address public staker2;

Expand Down Expand Up @@ -172,13 +113,13 @@ contract StakeTest is TestBaseDefault {
}
}

contract CantTransferStakeTest is TestBaseFailingTransfer {
contract CantTransferStakeTest is TestBase {
address public staker = address(0x331);

function setUp() public override {
super.setUp();

setFail();
setFailTransfer();
}

function testWrongStakeReverts() public {
Expand All @@ -188,13 +129,13 @@ contract CantTransferStakeTest is TestBaseFailingTransfer {
}
}

contract CantMintStakeTest is TestBaseFailingMint {
address public staker;
contract CantMintStakeTest is TestBase {
address public staker = address(0x331);

function setUp() public override {
super.setUp();

staker = address(0x331);
setFailMint();
}

function testWrongStakeReverts() public {
Expand All @@ -204,7 +145,7 @@ contract CantMintStakeTest is TestBaseFailingMint {
}
}

contract UnstakeTest is TestBaseDefault {
contract UnstakeTest is TestBase {
address public staker = address(0x331);
address public staker2 = address(0x332);

Expand Down Expand Up @@ -264,7 +205,7 @@ contract UnstakeTest is TestBaseDefault {
}
}

contract UnstakeNoStakeTest is TestBaseDefault {
contract UnstakeNoStakeTest is TestBase {
address public staker = address(0x331);

function setUp() public override {
Expand All @@ -278,15 +219,15 @@ contract UnstakeNoStakeTest is TestBaseDefault {
}
}

contract CantTransferUnstakeTest is TestBaseFailingTransfer {
contract CantTransferUnstakeTest is TestBase {
address public staker = address(0x331);

function setUp() public override {
super.setUp();

vm.prank(staker);
mc.stake(333);
setFail();
setFailTransfer();
}

function testWrongUnstakeReverts() public {
Expand All @@ -296,17 +237,17 @@ contract CantTransferUnstakeTest is TestBaseFailingTransfer {
}
}

contract CantBurnUnstakeTest is TestBaseFailingMint {
contract CantBurnUnstakeTest is TestBase {
address public staker;

function setUp() public override {
super.setUp();

unsetFail();
unsetFailMint();
staker = address(0x331);
vm.prank(staker);
mc.stake(333); // Set up MoltenCampaign state.
setFail();
setFailMint();
}

function testWrongUntakeReverts() public {
Expand Down
3 changes: 2 additions & 1 deletion test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ Another approach would be to use an abstract contract on our smart contracts,
that would be used in tests but removed from production code. Meaning: code
rewrite for production, but tightly controlled.

This way, mocks would be set during test setups via for example `function setMTokenMock(IERC20)`, but these functions wouldn't be available in production.
This way, mocks would be set during test setups via for example `function
setMTokenMock(IERC20)`, but these functions wouldn't be available in production.

Of couse the problem then lies in how reliable would code rewrite be. To be
tried.
39 changes: 4 additions & 35 deletions test/helpers/ERC20VotesMintable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,38 +26,7 @@ contract ERC20VotesMintable is ERC20Votes {
}

contract ERC20VotesMintableMock is ERC20Votes {
struct TransferFromCall {
address from;
address to;
uint256 amount;
}
TransferFromCall public transferFromCalledWith;

constructor(string memory name, string memory symbol)
ERC20(name, symbol)
ERC20Permit("daoToken")
{}

function mint(address to, uint256 amount) public virtual {
_mint(to, amount);
}

function transferFrom(
address from,
address to,
uint256 amount
) public override returns (bool) {
transferFromCalledWith = TransferFromCall({
from: from,
to: to,
amount: amount
});
return true;
}
}

contract ERC20VotesMintableFailedMock is ERC20Votes {
bool private _fail = false;
bool public _mockFail = false;

struct TransferFromCall {
address from;
Expand Down Expand Up @@ -85,15 +54,15 @@ contract ERC20VotesMintableFailedMock is ERC20Votes {
to: to,
amount: amount
});
require(!_fail, "ERC20VMFM transferFrom");
require(!_mockFail, "ERC20VMFM transferFrom");
return true;
}

function setFail() public {
_fail = true;
_mockFail = true;
}

function unsetFail() public {
_fail = false;
_mockFail = false;
}
}
28 changes: 6 additions & 22 deletions test/helpers/MTokenMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {ERC20, ERC20Pausable, Pausable} from "openzeppelin/token/ERC20/extension
import {Owned} from "solmate/auth/Owned.sol";

contract MTokenMock is ERC20Pausable, Owned {
bool public _mockFail = false;

struct MintCall {
address _sender;
address to;
Expand Down Expand Up @@ -39,6 +41,7 @@ contract MTokenMock is ERC20Pausable, Owned {
to: to,
amount: amount
});
require(!_mockFail, "MTFM mint");
}

function burn(address account, uint256 amount) public virtual onlyOwner {
Expand All @@ -47,37 +50,18 @@ contract MTokenMock is ERC20Pausable, Owned {
account: account,
amount: amount
});
require(!_mockFail, "MTFM burn");
}

function totalSupply() public view override returns (uint256) {
return super.totalSupply();
}
}

contract MTokenFailingMock is MTokenMock {
bool private _fail = false;

constructor(
string memory name_,
string memory symbol_,
address _owner
) MTokenMock(name_, symbol_, _owner) {}

function setFail() public {
_fail = true;
_mockFail = true;
}

function unsetFail() public {
_fail = false;
}

function mint(address to, uint256 amount) public override onlyOwner {
super.mint(to, amount);
require(!_fail, "MTFM mint");
}

function burn(address account, uint256 amount) public override onlyOwner {
super.burn(account, amount);
require(!_fail, "MTFM burn");
_mockFail = false;
}
}

0 comments on commit e82a3a3

Please sign in to comment.