Skip to content

Commit

Permalink
Merge pull request #72 from catalystdao/update-documentation
Browse files Browse the repository at this point in the history
Update Readme
  • Loading branch information
reednaa committed Dec 5, 2023
2 parents 6019f58 + 9fe66d9 commit 0e85289
Show file tree
Hide file tree
Showing 12 changed files with 546 additions and 101 deletions.
480 changes: 382 additions & 98 deletions evm/README.md

Large diffs are not rendered by default.

Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
144 changes: 144 additions & 0 deletions evm/test/ExampleTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import "forge-std/Test.sol";
import { Token } from "./mocks/token.sol";
import { TestCommon } from "./TestCommon.t.sol";
import { ICatalystV1Vault, ICatalystV1Structs } from "../src/ICatalystV1Vault.sol";

contract ExampleTest is TestCommon {

address vault1;
address vault2;

bytes32 FEE_RECIPITANT = bytes32(uint256(uint160(0)));

function setUp() public override {
// Calls setup() on testCommon
super.setUp();

// Create relevant arrays for the vault.
uint256 numTokens = 2;
address[] memory assets = new address[](numTokens);
uint256[] memory init_balances = new uint256[](numTokens);
uint256[] memory weights = new uint256[](numTokens);

// Deploy a token
assets[0] = address(new Token("TEST", "TEST", 18, 1e6));
init_balances[0] = 1000 * 1e18;
weights[0] = 1;
// Deploy another token
assets[1] = address(new Token("TEST2", "TEST2", 18, 1e6));
init_balances[1] = 1000 * 1e18;
weights[1] = 1;

// Set approvals.
Token(assets[0]).approve(address(catFactory), init_balances[0] * 2);
Token(assets[1]).approve(address(catFactory), init_balances[1] * 2);

vault1 = catFactory.deployVault(
address(volatileTemplate), assets, init_balances, weights, 10**18, 0, "Example Pool1", "EXMP1", address(CCI)
);
vault2 = catFactory.deployVault(
address(volatileTemplate), assets, init_balances, weights, 10**18, 0, "Example Pool2", "EXMP2", address(CCI)
);
}

function test_localswap() external {
// Make an account for testing
address alice = makeAddr("Alice");
uint256 swapAmount = 100 * 10**18;

// Get the token at index 0 from the vault
address fromToken = ICatalystV1Vault(vault1)._tokenIndexing(0);
// Lets also get the to token while we are at it:
address toToken = ICatalystV1Vault(vault1)._tokenIndexing(1);

Token(fromToken).transfer(alice, swapAmount);

// Approve as alice.
vm.prank(alice);
Token(fromToken).approve(vault1, swapAmount);

uint256 minOut = 0;
vm.prank(alice);
uint256 swapReturn = ICatalystV1Vault(vault1).localSwap(fromToken, toToken, swapAmount, minOut);

assertEq(swapReturn, Token(toToken).balanceOf(alice), "Alice didn't get enough tokens");
}

function test_cross_chain_swap() external {
// We need to set address(CCI) as the allowed caller and address(GARP) as the destination.
bytes memory approvedRemoteCaller = convertEVMTo65(address(CCI));
bytes memory remoteGARPImplementation = abi.encode(address(GARP));
// notice that remoteGARPImplementation needs to be encoded with how the AMB expectes it
// and approvedRemoteCaller needs to be encoded with how GARP expects it.
CCI.connectNewChain(DESTINATION_IDENTIFIER, approvedRemoteCaller, remoteGARPImplementation);

ICatalystV1Vault(vault1).setConnection(
DESTINATION_IDENTIFIER,
convertEVMTo65(vault2),
true
);

ICatalystV1Vault(vault2).setConnection(
DESTINATION_IDENTIFIER,
convertEVMTo65(vault1),
true
);

// Get the token at index 0 from the vault
address fromToken = ICatalystV1Vault(vault1)._tokenIndexing(0);
// Lets also get the to token while we are at it:
address toToken = ICatalystV1Vault(vault1)._tokenIndexing(1);

// Make an account for testing
address alice = makeAddr("Alice");
uint256 swapAmount = 100 * 10**18;

payable(alice).transfer(_getTotalIncentive(_INCENTIVE));
Token(fromToken).transfer(alice, swapAmount);
vm.prank(alice);
Token(fromToken).approve(vault1, swapAmount);

// Define the route as a struct:
ICatalystV1Structs.RouteDescription memory routeDescription = ICatalystV1Structs.RouteDescription({
chainIdentifier: DESTINATION_IDENTIFIER,
toVault: convertEVMTo65(vault2),
toAccount: convertEVMTo65(alice),
incentive: _INCENTIVE
});

// We need the log emitted by the mock Generalised Incentives implementation.
vm.recordLogs();
vm.prank(alice);
ICatalystV1Vault(vault1).sendAsset{value: _getTotalIncentive(_INCENTIVE)}(
routeDescription,
fromToken,
1,
swapAmount,
0,
alice,
0,
hex""
);
// Get logs.
Vm.Log[] memory entries = vm.getRecordedLogs();
// Decode log.
(, , bytes memory messageWithContext) = abi.decode(entries[1].data, (bytes32, bytes, bytes));
// Get GARP message.
(bytes memory _metadata, bytes memory toExecuteMessage) = getVerifiedMessage(address(GARP), messageWithContext);
// Process message / Execute the receiveAsset call. This delivers the assets to the user.
vm.recordLogs();
GARP.processPacket(_metadata, toExecuteMessage, FEE_RECIPITANT);
// We need to deliver the ack, so we need to relay another message back:
entries = vm.getRecordedLogs();
(, , messageWithContext) = abi.decode(entries[3].data, (bytes32, bytes, bytes));
(_metadata, toExecuteMessage) = getVerifiedMessage(address(GARP), messageWithContext);
// Process ack
vm.recordLogs();
GARP.processPacket(_metadata, toExecuteMessage, FEE_RECIPITANT);

assertGt(Token(toToken).balanceOf(alice), 0, "Alice didn't get any tokens");
}
}
21 changes: 18 additions & 3 deletions evm/test/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
# Catalust Tests
# Catalyst Tests

Tests can be run by
```
forge test -vvv
```
or coverage with
```
forge coverage --ir-minimum
```
Note that coverage doesn't work right now.

## Test Structure

Tests are organised based on which feature they test:

*./CatalystFactory*

*./CatalystInterface*

*./CatalystRouter*

*./CatalystVault*

And then for larger tests of the system as a whole *./integration*
Expand All @@ -21,6 +35,7 @@ Contains various mocks used throughout testing.

## Vault Testing

To test many different variations of vaults without having to repeat code several times, vault tests (which aren't integration tests) are written such that they can be inherited and the deployment configuration is then provided to the test.
The majority of testing is for the Catalyst vaults, since this is where the majority of the contract risk exists. To test many different variations of vaults without having to repeat code several times, vault tests (which aren't integration tests) are written such that they can be inherited and the deployment configuration is then provided to the test.

For the simplest example, see *./CatalystVault/LocalSwap.t.sol*. This contract is inherited by *./CatalystVault/Volatile/VolatileLocalSwap.t.sol* where the test is run.

For the simplest example, see *./CatalystVault/LocalSwap.t.sol*. This contract is inherited by *./CatalystVault/Volatile/VolatileLocalSwap.t.sol* where the test is run.
2 changes: 2 additions & 0 deletions evm/test/underwriting/underwrite.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ contract TestUnderwrite is TestCommon, ICatalystReceiver {
}

function test_underwrite_storage(address sendTo) external {
vm.assume(sendTo != vault1);
vm.assume(sendTo != vault2);
vm.assume(sendTo != address(0));
vm.assume(sendTo != 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496);
uint256 maxUnderwritingDuration = CCI.maxUnderwritingDuration();
Expand Down

0 comments on commit 0e85289

Please sign in to comment.