|
| 1 | +// SPDX-License-Identifier: MIT |
| 2 | + |
| 3 | +pragma solidity ^0.8.10; |
| 4 | + |
| 5 | +import "forge-std/Test.sol"; |
| 6 | +import {IERC20Upgradeable} from "@openzeppelin-upgradeable/interfaces/IERC20Upgradeable.sol"; |
| 7 | +import {SafeERC20Upgradeable} from "@openzeppelin-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; |
| 8 | +import {ERC20} from "@openzeppelin/token/ERC20/ERC20.sol"; |
| 9 | +import {IPoolAddressesProvider} from "@aave-v3-core/interfaces/IPoolAddressesProvider.sol"; |
| 10 | + |
| 11 | +import {MathUpgradeable} from "../src/ATokenVault.sol"; |
| 12 | +import {ImmutableATokenVault} from "../src/ImmutableATokenVault.sol"; |
| 13 | + |
| 14 | +contract ImmutableATokenVaultBaseTest is Test { |
| 15 | + using SafeERC20Upgradeable for IERC20Upgradeable; |
| 16 | + using MathUpgradeable for uint256; |
| 17 | + |
| 18 | + // Fork tests using Polygon for Aave v3 |
| 19 | + address constant POLYGON_DAI = 0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063; |
| 20 | + address constant POLYGON_ADAI = 0x82E64f49Ed5EC1bC6e43DAD4FC8Af9bb3A2312EE; |
| 21 | + address constant POLYGON_AAVE_POOL = 0x794a61358D6845594F94dc1DB02A252b5b4814aD; |
| 22 | + address constant POLYGON_POOL_ADDRESSES_PROVIDER = 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb; |
| 23 | + address constant POLYGON_REWARDS_CONTROLLER = 0x929EC64c34a17401F460460D4B9390518E5B473e; |
| 24 | + address constant POLYGON_DATA_PROVIDER = 0x69FA688f1Dc47d4B5d8029D5a35FB7a548310654; |
| 25 | + |
| 26 | + // Fork tests using Avalanche for Aave v3 |
| 27 | + address constant AVALANCHE_USDC = 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E; |
| 28 | + address constant AVALANCHE_AUSDC = 0x625E7708f30cA75bfd92586e17077590C60eb4cD; |
| 29 | + address constant AVALANCHE_WAVAX = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7; |
| 30 | + address constant AVALANCHE_POOL_ADDRESSES_PROVIDER = 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb; |
| 31 | + address constant AVALANCHE_REWARDS_CONTROLLER = 0x929EC64c34a17401F460460D4B9390518E5B473e; |
| 32 | + |
| 33 | + uint256 constant SCALE = 1e18; |
| 34 | + uint256 constant ONE = 1e18; |
| 35 | + uint256 constant TEN = 10e18; |
| 36 | + uint256 constant HUNDRED = 100e18; |
| 37 | + uint256 constant ONE_PERCENT = 0.01e18; |
| 38 | + uint256 constant ONE_AND_HALF_PERCENT = 0.015e18; |
| 39 | + uint256 constant ONE_BPS = 0.0001e18; |
| 40 | + |
| 41 | + uint256 constant OWNER_PRIV_KEY = 11111; |
| 42 | + uint256 constant ALICE_PRIV_KEY = 12345; |
| 43 | + uint256 constant BOB_PRIV_KEY = 54321; |
| 44 | + uint256 constant CHAD_PRIV_KEY = 98765; |
| 45 | + |
| 46 | + address OWNER = vm.addr(OWNER_PRIV_KEY); |
| 47 | + address ALICE = vm.addr(ALICE_PRIV_KEY); |
| 48 | + address BOB = vm.addr(BOB_PRIV_KEY); |
| 49 | + address CHAD = vm.addr(CHAD_PRIV_KEY); |
| 50 | + |
| 51 | + string constant SHARE_NAME = "Wrapped aDAI"; |
| 52 | + string constant SHARE_SYMBOL = "waDAI"; |
| 53 | + |
| 54 | + uint256 fee = 0.2e18; // 20% |
| 55 | + uint16 referralCode = 4546; |
| 56 | + |
| 57 | + ImmutableATokenVault vault; |
| 58 | + address vaultAssetAddress; // aDAI, must be set in every setUp |
| 59 | + uint256 initialLockDeposit; // Must be set in every setUp |
| 60 | + |
| 61 | + // Initializer Errors |
| 62 | + bytes constant ERR_INITIALIZED = bytes("Initializable: contract is already initialized"); |
| 63 | + |
| 64 | + // Ownable Errors |
| 65 | + bytes constant ERR_NOT_OWNER = bytes("Ownable: caller is not the owner"); |
| 66 | + |
| 67 | + // Meta Tx Errors |
| 68 | + bytes constant ERR_INVALID_SIGNER = bytes("INVALID_SIGNER"); |
| 69 | + bytes constant ERR_PERMIT_DEADLINE_EXPIRED = bytes("PERMIT_DEADLINE_EXPIRED"); |
| 70 | + bytes constant ERR_SIG_INVALID = bytes("SIG_INVALID"); |
| 71 | + bytes constant ERR_SIG_EXPIRED = bytes("SIG_EXPIRED"); |
| 72 | + |
| 73 | + // Vault Errors |
| 74 | + bytes constant ERR_ZERO_ADDRESS_NOT_VALID = bytes("ZERO_ADDRESS_NOT_VALID"); |
| 75 | + bytes constant ERR_ZERO_INITIAL_DEPOSIT = bytes("ZERO_INITIAL_LOCK_DEPOSIT"); |
| 76 | + bytes constant ERR_ZERO_ASSETS = bytes("ZERO_ASSETS"); |
| 77 | + bytes constant ERR_ZERO_SHARES = bytes("ZERO_SHARES"); |
| 78 | + bytes constant ERR_TRANSFER_FROM_FAILED = bytes("TRANSFER_FROM_FAILED"); |
| 79 | + bytes constant ERR_CANNOT_RESCUE_ATOKEN = bytes("CANNOT_RESCUE_ATOKEN"); |
| 80 | + bytes constant ERR_FEE_TOO_HIGH = bytes("FEE_TOO_HIGH"); |
| 81 | + bytes constant ERR_ASSET_NOT_SUPPORTED = bytes("ASSET_NOT_SUPPORTED"); |
| 82 | + bytes constant ERR_INSUFFICIENT_FEES = bytes("INSUFFICIENT_FEES"); |
| 83 | + bytes constant ERR_CANNOT_CLAIM_TO_ZERO_ADDRESS = bytes("CANNOT_CLAIM_TO_ZERO_ADDRESS"); |
| 84 | + bytes constant SAFE_TRANSFER_ARITHMETIC = bytes("NH{q"); |
| 85 | + bytes constant ERR_DEPOSIT_EXCEEDS_MAX = bytes("DEPOSIT_EXCEEDS_MAX"); |
| 86 | + bytes constant ERR_MINT_EXCEEDS_MAX = bytes("MINT_EXCEEDS_MAX"); |
| 87 | + bytes constant ERR_WITHDRAW_EXCEEDS_MAX = bytes("WITHDRAW_EXCEEDS_MAX"); |
| 88 | + bytes constant ERR_REDEEM_EXCEEDS_MAX = bytes("REDEEM_EXCEEDS_MAX"); |
| 89 | + |
| 90 | + // ERC4626 Events |
| 91 | + event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); |
| 92 | + event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares); |
| 93 | + |
| 94 | + // ATokenVault Events |
| 95 | + event FeeUpdated(uint256 indexed oldFee, uint256 indexed newFee); |
| 96 | + event FeesWithdrawn(address indexed to, uint256 indexed amount, uint256 newVaultBalance, uint256 newTotalFeesAccrued); |
| 97 | + event YieldAccrued(uint256 accruedYield, uint256 newFeesFromYield, uint256 newVaultBalance); |
| 98 | + event RewardsClaimed(address indexed to, address[] rewardsList, uint256[] claimedAmounts); |
| 99 | + event EmergencyRescue(address indexed token, address indexed to, uint256 amount); |
| 100 | + |
| 101 | + function setUp() public virtual {} |
| 102 | + |
| 103 | + // For debug purposes |
| 104 | + function _logVaultBalances(address user, string memory label) internal view { |
| 105 | + console.log("\n", label); |
| 106 | + console.log("ERC20 Assets\t\t\t", ERC20(vaultAssetAddress).balanceOf(address(vault))); |
| 107 | + console.log("totalAssets()\t\t\t", vault.totalAssets()); |
| 108 | + console.log("lastVaultBalance()\t\t", vault.getLastVaultBalance()); |
| 109 | + console.log("User Withdrawable\t\t", vault.maxWithdraw(user)); |
| 110 | + console.log("claimable fees\t\t", vault.getClaimableFees()); |
| 111 | + console.log("current time\t\t\t", block.timestamp); |
| 112 | + } |
| 113 | + |
| 114 | + function _deploy(address underlying, address addressesProvider) internal { |
| 115 | + _deploy(underlying, addressesProvider, 10e18); |
| 116 | + } |
| 117 | + |
| 118 | + function _deploy(address underlying, address addressesProvider, uint256 _initialLockDeposit) internal { |
| 119 | + initialLockDeposit = _initialLockDeposit; |
| 120 | + deal(underlying, address(this), _initialLockDeposit); |
| 121 | + address vaultAddress = computeCreateAddress(address(this), vm.getNonce(address(this)) + 1); |
| 122 | + IERC20Upgradeable(underlying).safeApprove(vaultAddress, _initialLockDeposit); |
| 123 | + |
| 124 | + vault = new ImmutableATokenVault( |
| 125 | + underlying, |
| 126 | + referralCode, |
| 127 | + IPoolAddressesProvider(addressesProvider), |
| 128 | + OWNER, |
| 129 | + fee, |
| 130 | + SHARE_NAME, |
| 131 | + SHARE_SYMBOL, |
| 132 | + _initialLockDeposit |
| 133 | + ); |
| 134 | + } |
| 135 | +} |
0 commit comments