Skip to content

Commit

Permalink
test: initialize echidna for fuzz testing (#208)
Browse files Browse the repository at this point in the history
Co-authored-by: lumtis <[email protected]>
  • Loading branch information
skosito and lumtis authored Jul 11, 2024
1 parent b0fbc16 commit 972ceb1
Show file tree
Hide file tree
Showing 16 changed files with 2,247 additions and 11 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ cache
dist
node_modules
typechain-types
docs
docs
crytic-export
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ coverage.json
scripts/slither-results/*
!scripts/slither-results/.gitkeep

abi
abi

crytic-export
2 changes: 1 addition & 1 deletion contracts/prototypes/evm/ERC20CustodyNew.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ contract ERC20CustodyNew is ReentrancyGuard{
// For this, it passes through the Gateway contract, it transfers the tokens to the Gateway contract and then calls the contract
// TODO: Finalize access control
// https://github.com/zeta-chain/protocol-contracts/issues/204
function withdrawAndCall(address token, address to, uint256 amount, bytes calldata data) external nonReentrant {
function withdrawAndCall(address token, address to, uint256 amount, bytes calldata data) public nonReentrant {
// Transfer the tokens to the Gateway contract
IERC20(token).safeTransfer(address(gateway), amount);

Expand Down
6 changes: 3 additions & 3 deletions contracts/prototypes/evm/GatewayEVM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ contract GatewayEVM is Initializable, OwnableUpgradeable, UUPSUpgradeable {
error InsufficientERC20Amount();
error ZeroAddress();
error ApprovalFailed();
error CustodyInitialized();

address public custody;
address public tssAddress;
Expand All @@ -27,9 +28,7 @@ contract GatewayEVM is Initializable, OwnableUpgradeable, UUPSUpgradeable {
event Deposit(address indexed sender, address indexed receiver, uint256 amount, address asset, bytes payload);
event Call(address indexed sender, address indexed receiver, bytes payload);

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function initialize(address _tssAddress) public initializer {
Expand Down Expand Up @@ -71,7 +70,7 @@ contract GatewayEVM is Initializable, OwnableUpgradeable, UUPSUpgradeable {
address to,
uint256 amount,
bytes calldata data
) external returns (bytes memory) {
) public returns (bytes memory) {
if (amount == 0) revert InsufficientETHAmount();
// Approve the target contract to spend the tokens
if(!resetApproval(token, to)) revert ApprovalFailed();
Expand Down Expand Up @@ -136,6 +135,7 @@ contract GatewayEVM is Initializable, OwnableUpgradeable, UUPSUpgradeable {
}

function setCustody(address _custody) external {
if (custody != address(0)) revert CustodyInitialized();
custody = _custody;
}

Expand Down
6 changes: 6 additions & 0 deletions echidna.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# provide solc remappings to crytic-compile
cryticArgs: ['--solc-remaps', '@=node_modules/@']
testMode: "assertion"
testLimit: 50000
seqLen: 10000
allContracts: false

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/contracts/prototypes/evm/gatewayevm.sol/gatewayevm.go

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions test/fuzz/ERC20CustodyNewEchidnaTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import "../../contracts/prototypes/evm/TestERC20.sol";
import "../../contracts/prototypes/evm/ERC20CustodyNew.sol";
import "../../contracts/prototypes/evm/GatewayEVM.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract ERC20CustodyNewEchidnaTest is ERC20CustodyNew {
using SafeERC20 for IERC20;

TestERC20 public testERC20;
address public echidnaCaller = msg.sender;

GatewayEVM testGateway = new GatewayEVM();

constructor() ERC20CustodyNew(address(testGateway)) {
testGateway.initialize(echidnaCaller);
testERC20 = new TestERC20("test", "TEST");
testGateway.setCustody(address(this));
}

function testWithdrawAndCall(address to, uint256 amount, bytes calldata data) public {
// mint more than amount
testERC20.mint(address(this), amount + 5);
// transfer overhead to gateway
testERC20.transfer(address(testGateway), 5);

withdrawAndCall(address(testERC20), to, amount, data);

// Assertion to ensure no ERC20 tokens are left in the gateway contract after execution
assert(testERC20.balanceOf(address(gateway)) == 0);
}
}
27 changes: 27 additions & 0 deletions test/fuzz/GatewayEVMEchidnaTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import "../../contracts/prototypes/evm/GatewayEVM.sol";
import "../../contracts/prototypes/evm/TestERC20.sol";
import "../../contracts/prototypes/evm/ERC20CustodyNew.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract GatewayEVMEchidnaTest is GatewayEVM {
using SafeERC20 for IERC20;

TestERC20 public testERC20;
address public echidnaCaller = msg.sender;

constructor() {
initialize(echidnaCaller);
testERC20 = new TestERC20("test", "TEST");
custody = address(new ERC20CustodyNew(address(this)));
}

function testExecuteWithERC20(address to, uint256 amount, bytes calldata data) public {
testERC20.mint(address(this), amount);

executeWithERC20(address(testERC20), to, amount, data);

// Assertion to ensure no ERC20 tokens are left in the contract after execution
assert(testERC20.balanceOf(address(this)) == 0);
}
}
13 changes: 13 additions & 0 deletions test/fuzz/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Setup echidna

```
brew install echidna
solc-select use 0.8.7
```

## Execute contract tests

```
echidna test/fuzz/ERC20CustodyNewEchidnaTest.sol --contract ERC20CustodyNewEchidnaTest --config echidna.yaml
echidna test/fuzz/GatewayEVMEchidnaTest.sol --contract GatewayEVMEchidnaTest --config echidna.yaml
```
Loading

0 comments on commit 972ceb1

Please sign in to comment.