Skip to content

Commit

Permalink
fill out remaining handler functions
Browse files Browse the repository at this point in the history
  • Loading branch information
iamchrissmith committed Feb 26, 2024
1 parent 35d53af commit b626847
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 1 deletion.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,27 @@ These contracts are essentially wrappers around the contracts/functionality we w
#### Regressions

If we find a failing sequence, these are the unit tests that we can use to reproduce the failure and check our fix.

### 2 - Handler Setup

branch: `2-handler-setup`

Important Concepts:

#### Handler's purpose

Your handler is the wrapper around the contract that you are testing. You should add all functions you want to be included in your testing to this contract (most likely all external functions that modify state). The test suite will call these functions in random order with random input.

Calls to the contract you're testing should be wrapped in `try/catch` blocks so you can handle errors.

#### Actors

To make the test suite better simulate what will happen post deployment, you need a set of actors and destination addresses that will be the `msg.sender` and targets for your function calls.

#### Error handling

You will need to decide whether you are going to `bound` your inputs so that calls are successful or if you are going to add error exclusions.

#### Requires/Reverts

You can add handler function level assertions to these functions if you want to assert certain things are true during a specific call. This makes the handler functions act like fuzz tests within your invariant test suite.
8 changes: 7 additions & 1 deletion test/invariant/DaiInvariants.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@ contract DaiInvariants is Test {
// setup Actors in Handler
_daiHandler.init();

bytes4[] memory selectors = new bytes4[](1);
bytes4[] memory selectors = new bytes4[](7);
selectors[0] = _daiHandler.transfer.selector;
selectors[1] = _daiHandler.transferFrom.selector;
selectors[2] = _daiHandler.mint.selector;
selectors[3] = _daiHandler.burn.selector;
selectors[4] = _daiHandler.approve.selector;
selectors[5] = _daiHandler.rely.selector;
selectors[6] = _daiHandler.deny.selector;

targetSelector(
FuzzSelector({
Expand Down
109 changes: 109 additions & 0 deletions test/invariant/handlers/DaiHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ contract DaiHandler is Test {
dai.mint(_actor.addr, 1000 ether);
}

Actor memory governance;
(governance.addr, governance.key) = makeAddrAndKey(string(abi.encodePacked("Governance")));
actors.push(governance);
dsts.push(governance);
dai.rely(governance.addr);

Actor memory zero;
(zero.addr, zero.key) = makeAddrAndKey(string(abi.encodePacked("Zero")));
zero.addr = address(0);
Expand All @@ -84,6 +90,109 @@ contract DaiHandler is Test {
}
}

function transferFrom(
uint256 _actorIndex,
uint256 _srcIndex,
uint256 _dstIndex,
uint256 _wad
) public useRandomActor(_actorIndex) resetErrors {
Actor memory src = _selectActor(_srcIndex);
Actor memory dst = _selectDst(_dstIndex);
try dai.transferFrom(src.addr, dst.addr, _wad) {
console.log("TransferFrom succeeded");
} catch Error(string memory reason) {
if(dai.balanceOf(src.addr) < _wad) addExpectedError("Dai/insufficient-balance");
if(dai.allowance(actor.addr, src.addr) < _wad) addExpectedError("Dai/insufficient-allowance");
expectedError(reason);
} catch (bytes memory reason) {
console.log("TransferFrom failed: ");
console.logBytes(reason);
}
}

function mint(
uint256 _actorIndex,
uint256 _dstIndex,
uint256 _wad
) public useRandomActor(_actorIndex) resetErrors {
Actor memory dst = _selectDst(_dstIndex);
try dai.mint(dst.addr, _wad) {
console.log("Mint succeeded");
} catch Error(string memory reason) {
if(dai.wards(actor.addr) == 0) addExpectedError("Dai/not-authorized");
expectedError(reason);
} catch (bytes memory reason) {
console.log("Mint failed: ");
console.logBytes(reason);
}
}

function burn(
uint256 _actorIndex,
uint256 _usrIndex,
uint256 _wad
) public useRandomActor(_actorIndex) resetErrors {
Actor memory usr = _selectActor(_usrIndex);
try dai.burn(usr.addr, _wad) {
console.log("burn succeeded");
} catch Error(string memory reason) {
if(dai.balanceOf(usr.addr) < _wad) addExpectedError("Dai/insufficient-balance");
if(dai.allowance(usr.addr, actor.addr) < _wad) addExpectedError("Dai/insufficient-allowance");
expectedError(reason);
} catch (bytes memory reason) {
console.log("burn failed: ");
console.logBytes(reason);
}
}

function approve(
uint256 _actorIndex,
uint256 _usrIndex,
uint256 _wad
) public useRandomActor(_actorIndex) resetErrors {
Actor memory usr = _selectActor(_usrIndex);
try dai.approve(usr.addr, _wad) {
console.log("approve succeeded");
} catch Error(string memory reason) {
expectedError(reason);
} catch (bytes memory reason) {
console.log("approve failed: ");
console.logBytes(reason);
}
}

function rely(
uint256 _actorIndex,
uint256 _guyIndex
) public useRandomActor(_actorIndex) resetErrors {
Actor memory guy = _selectActor(_guyIndex);
try dai.rely(guy.addr) {
console.log("rely succeeded");
} catch Error(string memory reason) {
if(dai.wards(actor.addr) == 0) addExpectedError("Dai/not-authorized");
expectedError(reason);
} catch (bytes memory reason) {
console.log("rely failed: ");
console.logBytes(reason);
}
}

function deny(
uint256 _actorIndex,
uint256 _guyIndex
) public useRandomActor(_actorIndex) resetErrors {
Actor memory guy = _selectActor(_guyIndex);
try dai.deny(guy.addr) {
console.log("deny succeeded");
} catch Error(string memory reason) {
if(dai.wards(actor.addr) == 0) addExpectedError("Dai/not-authorized");
expectedError(reason);
} catch (bytes memory reason) {
console.log("deny failed: ");
console.logBytes(reason);
}
}

// Internal Helper Functions
function _selectActor(uint256 _actorIndex) internal view returns (Actor memory actor_) {
uint256 index = bound(_actorIndex, 0, actors.length - 1);
Expand Down

0 comments on commit b626847

Please sign in to comment.