All Ante Tests need to implement the IAnteTest.sol interface to work with Ante. To make it easier to work with, we have implemented the abstract classAnteTest.sol that any Ante Test can inherit.
// SPDX-License-Identifier: GPL-3.0-only
// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
pragma solidity >=0.7.0;
/// @title The interface for the Ante V0.5 Ante Test
/// @notice The Ante V0.5 Ante Test wraps test logic for verifying fundamental invariants of a protocol
interface IAnteTest {
/// @notice Returns the author of the Ante Test
/// @dev This overrides the auto-generated getter for testAuthor as a public var
/// @return The address of the test author
function testAuthor() external view returns (address);
/// @notice Returns the name of the protocol the Ante Test is testing
/// @dev This overrides the auto-generated getter for protocolName as a public var
/// @return The name of the protocol in string format
function protocolName() external view returns (string memory);
/// @notice Returns a single address in the testedContracts array
/// @dev This overrides the auto-generated getter for testedContracts [] as a public var
/// @param i The array index of the address to return
/// @return The address of the i-th element in the list of tested contracts
function testedContracts(uint256 i) external view returns (address);
/// @notice Returns the name of the Ante Test
/// @dev This overrides the auto-generated getter for testName as a public var
/// @return The name of the Ante Test in string format
function testName() external view returns (string memory);
/// @notice Function containing test logic to inspect the protocol invariant
/// @dev This should usually return True
/// @return A single bool indicating if the Ante Test passes/fails
function checkTestPasses() external returns (bool);
}
IAnteTest.sol as of 2021-11-26
All Ante Tests must follow the interface outlined in IAnteTest.sol to work with Ante. The interface outlines 5 main components:
testAuthor: this overrides the auto-generated getter and allows testAuthor to be used as a public variable.
testName: this overrides the auto-generated getter and allows testName to be used as a public variable.
protocolName: this overrides the auto-generated getter and allows the optional parameter protocolName to be used as a public variable.
testedContracts: this overrides the auto-generated getter for the optional public variable testedContracts.
checkTestPasses(): the critical function that checks your invariant that is expected to return True, else this will indicate a catastrophic failure.
To aid in working with the IAnteTest.sol interface, we've created an AnteTest.solabstract class that any Ante Test can inherit.
// SPDX-License-Identifier: GPL-3.0-only
// ┏━━━┓━━━━━┏┓━━━━━━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━━━━━
// ┃┏━┓┃━━━━┏┛┗┓━━━━━━━━┃┏━━┛━━━━━━━━━━━━━━━━━━━━━━━
// ┃┗━┛┃┏━┓━┗┓┏┛┏━━┓━━━━┃┗━━┓┏┓┏━┓━┏━━┓━┏━┓━┏━━┓┏━━┓
// ┃┏━┓┃┃┏┓┓━┃┃━┃┏┓┃━━━━┃┏━━┛┣┫┃┏┓┓┗━┓┃━┃┏┓┓┃┏━┛┃┏┓┃
// ┃┃ ┃┃┃┃┃┃━┃┗┓┃┃━┫━┏┓━┃┃━━━┃┃┃┃┃┃┃┗┛┗┓┃┃┃┃┃┗━┓┃┃━┫
// ┗┛ ┗┛┗┛┗┛━┗━┛┗━━┛━┗┛━┗┛━━━┗┛┗┛┗┛┗━━━┛┗┛┗┛┗━━┛┗━━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
pragma solidity >=0.7.0;
import "./interfaces/IAnteTest.sol";
/// @title Ante V0.5 Ante Test smart contract
/// @notice Abstract inheritable contract that supplies syntactic sugar for writing Ante Tests
/// @dev Usage: contract YourAnteTest is AnteTest("String descriptor of test") { ... }
abstract contract AnteTest is IAnteTest {
/// @inheritdoc IAnteTest
address public override testAuthor;
/// @inheritdoc IAnteTest
string public override testName;
/// @inheritdoc IAnteTest
string public override protocolName;
/// @inheritdoc IAnteTest
address[] public override testedContracts;
/// @dev testedContracts and protocolName are optional parameters which should
/// be set in the constructor of your AnteTest
/// @param _testName The name of the Ante Test
constructor(string memory _testName) {
testAuthor = msg.sender;
testName = _testName;
}
/// @notice Returns the testedContracts array of addresses
/// @return The list of tested contracts as an array of addresses
function getTestedContracts() external view returns (address[] memory) {
return testedContracts;
}
/// @inheritdoc IAnteTest
function checkTestPasses() external virtual override returns (bool) {}
}
AnteTest.sol as of 2021-11-26
The AnteTest.sol is an abstract contract that once inherited, can be used to write any Ante Test. All that is needed to be provided is a name for the test, designated by _testName. The optional parameters protocolName and testedContracts can be set in the constructor of your Ante Test.
To use it, when declaring your Ante Test, you can write:
import "@antefinance/contracts/interfaces/AnteTest.sol";
contract AnteNewProtocolTest is AnteTest("String descriptor of test") {
// create Ante Test variables & insert logic here
// you can omit your constructor if not defining these optional parameters
constructor () {
protocolName = "My Protocol";
testedContracts = [0x000000000000000000000000000000000000fEeD];
}
function checkTestPasses() public view override returns (bool) {
// insert logic here to check the My Protocol invariant
}
}
We'll see in the next section, how to use this abstract contract in some Ante Test examples.