Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ contract AbstractAdapterTest is PropertyTest {

address bob = address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
address alice = address(0x70997970C51812dc3A010C7d01b50e0d17dc79C8);
address feeRecipient = address(0x4444);
address feeRecipient = address(0x74bb390786072ea1329f270CA6C0058b2D1Afe3f);

uint256 defaultAmount;
uint256 raise;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15

pragma solidity ^0.8.15;

import { Test } from "forge-std/Test.sol";

import { CompoundV2Adapter, SafeERC20, IERC20, IERC20Metadata, Math, ICToken, IComptroller } from "../../../../../src/vault/adapter/compound/compoundV2/CompoundV2Adapter.sol";
import { VenusTestConfigStorage, VenusTestConfig } from "./VenusTestConfigStorage.sol";
import { AbstractAdapterTest, ITestConfigStorage, IAdapter } from "../../abstract/AbstractAdapterTest.sol";

contract VenusAdapterTest is AbstractAdapterTest {
using Math for uint256;

ICToken vaiToken;
IComptroller comptroller;

uint256 vaiDefaultAmount = 1e18;

function setUp() public {
uint256 forkId = vm.createSelectFork(vm.rpcUrl("bsc"));
vm.selectFork(forkId);

testConfigStorage = ITestConfigStorage(address(new VenusTestConfigStorage()));

_setUpTest(testConfigStorage.getTestConfig(0));
}

function overrideSetup(bytes memory testConfig) public override {
_setUpTest(testConfig);
}

function _setUpTest(bytes memory testConfig) internal {
address _vaiToken = abi.decode(testConfig, (address));

vaiToken = ICToken(_vaiToken);
asset = IERC20(vaiToken.underlying());
comptroller = IComptroller(vaiToken.comptroller());

(bool isListed, , ) = comptroller.markets(address(vaiToken));
assertEq(isListed, true, "InvalidAsset");

setUpBaseTest(IERC20(asset), address(new CompoundV2Adapter()), address(comptroller), 10, "CompoundV2", true);

vm.label(address(vaiToken), "vaiToken");
vm.label(address(comptroller), "comptroller");
vm.label(address(asset), "asset");
vm.label(address(this), "test");

adapter.initialize(abi.encode(asset, address(this), strategy, 0, sigs, ""), externalRegistry, testConfig);

defaultAmount = 10 ** IERC20Metadata(address(asset)).decimals();
minFuzz = defaultAmount;
raise = defaultAmount * 10_000;
maxAssets = defaultAmount * 10_000;
maxShares = maxAssets / 2;

}

/*//////////////////////////////////////////////////////////////
HELPER
//////////////////////////////////////////////////////////////*/

function increasePricePerShare(uint256 amount) public override {
deal(address(asset), address(vaiToken), asset.balanceOf(address(vaiToken)) + amount);
}

function iouBalance() public view override returns (uint256) {
return vaiToken.balanceOf(address(adapter));
}

// Verify that totalAssets returns the expected amount
function verify_totalAssets() public override {
deal(address(asset), bob, defaultAmount);
vm.startPrank(bob);
asset.approve(address(adapter), defaultAmount);
adapter.deposit(defaultAmount, bob);
vm.stopPrank();

assertEq(
adapter.totalAssets(),
adapter.convertToAssets(adapter.totalSupply()),
string.concat("totalSupply converted != totalAssets", baseTestId)
);
}

/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/

function verify_adapterInit() public override {
assertEq(adapter.asset(), vaiToken.underlying(), "asset");
assertEq(
IERC20Metadata(address(adapter)).name(),
string.concat("VaultCraft CompoundV2 ", IERC20Metadata(address(asset)).name(), " Adapter"),
"name"
);
assertEq(
IERC20Metadata(address(adapter)).symbol(),
string.concat("vcCv2-", IERC20Metadata(address(asset)).symbol()),
"symbol"
);

assertEq(asset.allowance(address(adapter), address(vaiToken)), type(uint256).max, "allowance");
}

/*//////////////////////////////////////////////////////////////
ROUNDTRIP TESTS
//////////////////////////////////////////////////////////////*/

function test__RT_deposit_withdraw() public override {
_mintAssetAndApproveForAdapter(vaiDefaultAmount, bob);

vm.startPrank(bob);
uint256 shares1 = adapter.deposit(vaiDefaultAmount, bob);
uint256 shares2 = adapter.withdraw(adapter.maxWithdraw(bob), bob, bob);
vm.stopPrank();

// We compare assets here with maxWithdraw since the shares of withdraw will always be lower than `vaiDefaultAmount`
// This tests the same assumption though. As long as you can withdraw less or equal assets to the input amount you cant round trip
assertGe(vaiDefaultAmount, adapter.maxWithdraw(bob), testId);
}

function test__RT_mint_withdraw() public override {
_mintAssetAndApproveForAdapter(adapter.previewMint(vaiDefaultAmount), bob);

vm.startPrank(bob);
uint256 assets = adapter.mint(vaiDefaultAmount, bob);
uint256 shares = adapter.withdraw(adapter.maxWithdraw(bob), bob, bob);
vm.stopPrank();
// We compare assets here with maxWithdraw since the shares of withdraw will always be lower than `vaiDefaultAmount`
// This tests the same assumption though. As long as you can withdraw less or equal assets to the input amount you cant round trip
assertGe(assets, adapter.maxWithdraw(bob), testId);
}

/*//////////////////////////////////////////////////////////////
PAUSE
//////////////////////////////////////////////////////////////*/

function test__unpause() public override {
_mintAssetAndApproveForAdapter(3e18, bob);

vm.prank(bob);
adapter.deposit(1e18, bob);

uint256 oldTotalAssets = adapter.totalAssets();
uint256 oldTotalSupply = adapter.totalSupply();
uint256 oldIouBalance = iouBalance();

adapter.pause();
adapter.unpause();

// We simply deposit back into the external protocol
// TotalSupply and Assets dont change
// A Tiny change in cToken balance will throw of the assets by some margin.
assertApproxEqAbs(oldTotalAssets, adapter.totalAssets(), 3e8, "totalAssets");
assertApproxEqAbs(oldTotalSupply, adapter.totalSupply(), _delta_, "totalSupply");
assertApproxEqAbs(asset.balanceOf(address(adapter)), 0, _delta_, "asset balance");
assertApproxEqAbs(iouBalance(), oldIouBalance, _delta_, "iou balance");

// Deposit and mint dont revert
vm.startPrank(bob);
adapter.deposit(1e18, bob);
adapter.mint(1e18, bob);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0
// Docgen-SOLC: 0.8.15

pragma solidity ^0.8.15;

import { ITestConfigStorage } from "../../abstract/ITestConfigStorage.sol";

struct VenusTestConfig {
address asset;
}

contract VenusTestConfigStorage is ITestConfigStorage {
VenusTestConfig[] internal testConfigs;

constructor() {
testConfigs.push(VenusTestConfig(0x334b3eCB4DCa3593BCCC3c7EBD1A1C1d1780FBF1));

}

function getTestConfig(uint256 i) public view returns (bytes memory) {
return abi.encode(testConfigs[i].asset);
}

function getTestConfigLength() public view returns (uint256) {
return testConfigs.length;
}
}