diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9cfafc3 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +-include .env + +.EXPORT_ALL_VARIABLES: +MAKEFLAGS += --no-print-directory + +default: + forge build + + +simulate: + @forge script script/DeployUSDeVault.s.sol --fork-url $(PROVIDER_URL) -vvvvv + +deploy: + @forge script script/DeployUSDeVault.s.sol --rpc-url $(PROVIDER_URL) --account deployerKey --sender $(DEPLOYER_ADDRESS) --broadcast --slow --verify -vvvv + + +# Override default `test` and `coverage` targets +.PHONY: test coverage diff --git a/README.md b/README.md index 2e2c4f5..f11972c 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,18 @@ This test suite also includes a16z's [ERC-4626 Property Tests](https://a16zcrypt ## Deployment +ERC-2335 is used to encode the private key using `cast wallet`. To be sure to never reveal it. + +```bash +cast wallet import deployerKey --interactive +``` + To deploy the vault contract, first check that the deployment parameters in `script/Deploy.s.sol` are configured correctly, then check that your `.env` file contains these keys: ``` -POLYGON_RPC_URL=xxx -MUMBAI_RPC_URL=xxx +PROVIDER_URL=xxx ETHERSCAN_API_KEY=xxx -PRIVATE_KEY=xxx +DEPLOYER_ADDRESS=xxx ``` Then run: @@ -45,18 +50,19 @@ source .env Then run one of the following commands: -Mumbai Testnet: +Simulate Deploy: ```bash -forge script script/Deploy.s.sol:Deploy --rpc-url $MUMBAI_RPC_URL --broadcast --verify --legacy -vvvv +make simulate ``` -Polygon Mainnet: +Deploy: ```bash -forge script script/Deploy.s.sol:Deploy --rpc-url $POLYGON_RPC_URL --broadcast --verify --legacy -vvvv +make deploy ``` + ## Audits You can find all audit reports under the audits folder diff --git a/foundry.lock b/foundry.lock new file mode 100644 index 0000000..5f49c4c --- /dev/null +++ b/foundry.lock @@ -0,0 +1,26 @@ +{ + "lib/aave-v3-core": { + "branch": { + "name": "v1.19.4", + "rev": "b74526a7bc67a3a117a1963fc871b3eb8cea8435" + } + }, + "lib/aave-v3-periphery": { + "branch": { + "name": "v1.23.0", + "rev": "0e7b7d929a7f1b26fb4d5a8cc1ab870fc3d85cd9" + } + }, + "lib/createx": { + "rev": "cbac803268835138f86a69bfe01fcf05a50e0447" + }, + "lib/erc4626-tests": { + "rev": "232ff9ba8194e406967f52ecc5cb52ed764209e9" + }, + "lib/openzeppelin-contracts-upgradeable": { + "branch": { + "name": "v4.8.1", + "rev": "7ec6d2a3117eb3487a5f9029203e80ceb89bd984" + } + } +} \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index fbb8653..4ff72b2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,10 +1,10 @@ [profile.default] -solc = "0.8.22" +solc = "0.8.23" bytecode_hash = "none" optimizer = true optimizer-runs = 30_000 via_ir = false -runs = 256 +# runs = 256 gas_reports = ["ATokenVault"] isolate = true ignored_warnings_from = ["lib/", "node_modules/"] # Ignore warnings from dependencies @@ -15,11 +15,3 @@ runs = 256 [profile.intense.fuzz] runs = 10000 - -[rpc_endpoints] -mumbai = "${MUMBAI_RPC_URL}" -polygon = "${POLYGON_RPC_URL}" - -[etherscan] -mumbai = { key = "${ETHERSCAN_API_KEY}" } -polygon = { key = "${ETHERSCAN_API_KEY}" } diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 3cd1ed3..91738fd 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -33,9 +33,9 @@ contract Deploy is Script { } function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + // require(vm.envExists("DEPLOYER_ADDRESS"), "DEPLOYER_ADDRESS env var not set"); + address deployerAddress = vm.envAddress("DEPLOYER_ADDRESS"); - address deployerAddress = vm.addr(deployerPrivateKey); console.log("Deployer address: ", deployerAddress); console.log("Deployer balance: ", deployerAddress.balance); console.log("BlockNumber: ", block.number); @@ -47,7 +47,7 @@ contract Deploy is Script { "Initial deposit not set. This prevents a frontrunning attack, please set a non-trivial initial deposit." ); - vm.startBroadcast(deployerPrivateKey); + vm.startBroadcast(deployerAddress); // Deploy the implementation, which disables initializers on construction vault = new ATokenVault( diff --git a/script/DeployUSDeVault.s.sol b/script/DeployUSDeVault.s.sol new file mode 100644 index 0000000..caa65c7 --- /dev/null +++ b/script/DeployUSDeVault.s.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.10; + +import "forge-std/Script.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {IERC20Upgradeable} from "@openzeppelin-upgradeable/interfaces/IERC20Upgradeable.sol"; + +import "../src/ATokenVault.sol"; + +contract DeployUSDeVault is Script { + // DEPLOYMENT PARAMETERS - CHANGE THESE FOR YOUR VAULT + // =================================================== + address UNDERLYING_ASSET_ADDRESS = 0x4c9EDD5852cd905f086C759E8383e09bff1E68B3; // USDe + uint16 REFERRAL_CODE = 0; // Referral code to use + address AAVE_POOL_ADDRESSES_PROVIDER_ADDRESS = 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e; // PoolAddressesProvider contract of the Aave Pool + address constant PROXY_ADMIN_ADDRESS = 0x35918cDE7233F2dD33fA41ae3Cb6aE0e42E0e69F; // Timelock + address constant OWNER_ADDRESS = 0x35918cDE7233F2dD33fA41ae3Cb6aE0e42E0e69F; // Timelock + string constant SHARE_NAME = "Wrapped aUSDe"; // Name of the token shares + string constant SHARE_SYMBOL = "waUSDe"; // Symbol of the token shares + uint256 constant FEE = 0; // Vault Fee bps in wad (e.g. 0.1e18 results in 10%) + uint256 constant INITIAL_LOCK_DEPOSIT = 1e18; // Initial deposit on behalf of the vault + // =================================================== + + ATokenVault public vault; + + function getChainId() public view returns (uint256) { + uint256 chainId; + assembly { + chainId := chainid() + } + return chainId; + } + + function run() external { + // require(vm.envExists("DEPLOYER_ADDRESS"), "DEPLOYER_ADDRESS env var not set"); + address deployerAddress = vm.envAddress("DEPLOYER_ADDRESS"); + + console.log("Deployer address: ", deployerAddress); + console.log("Deployer balance: ", deployerAddress.balance); + console.log("BlockNumber: ", block.number); + console.log("ChainId: ", getChainId()); + console.log("Deploying vault..."); + + require( + INITIAL_LOCK_DEPOSIT != 0, + "Initial deposit not set. This prevents a frontrunning attack, please set a non-trivial initial deposit." + ); + + vm.startBroadcast(deployerAddress); + + // Deploy the implementation, which disables initializers on construction + vault = new ATokenVault( + UNDERLYING_ASSET_ADDRESS, + REFERRAL_CODE, + IPoolAddressesProvider(AAVE_POOL_ADDRESSES_PROVIDER_ADDRESS) + ); + console.log("Vault impl deployed at: ", address(vault)); + + console.log("Deploying proxy..."); + // Encode the initializer call + bytes memory data = abi.encodeWithSelector( + ATokenVault.initialize.selector, + OWNER_ADDRESS, + FEE, + SHARE_NAME, + SHARE_SYMBOL, + INITIAL_LOCK_DEPOSIT + ); + console.logBytes(data); + + address proxyAddr = computeCreateAddress(deployerAddress, vm.getNonce(deployerAddress) + 1); + IERC20Upgradeable(UNDERLYING_ASSET_ADDRESS).approve(proxyAddr, INITIAL_LOCK_DEPOSIT); + console.log("Precomputed proxy address: ", proxyAddr); + console.log("Allowance for proxy: ", IERC20Upgradeable(UNDERLYING_ASSET_ADDRESS).allowance(deployerAddress, proxyAddr)); + + // Deploy and initialize the proxy + TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(vault), PROXY_ADMIN_ADDRESS, data); + console.log("Vault proxy deployed and initialized at: ", address(proxy)); + + vm.stopBroadcast(); + + console.log("\nVault data:"); + vault = ATokenVault(address(proxy)); + console.log("POOL_ADDRESSES_PROVIDER:", address(vault.POOL_ADDRESSES_PROVIDER())); + console.log("REFERRAL_CODE:", vault.REFERRAL_CODE()); + console.log("UNDERLYING:", address(vault.UNDERLYING())); + console.log("ATOKEN:", address(vault.ATOKEN())); + console.log("Name:", vault.name()); + console.log("Symbol:", vault.symbol()); + console.log("Owner:", vault.owner()); + console.log("Fee:", vault.getFee()); + } +} diff --git a/script/Upgrade.s.sol b/script/Upgrade.s.sol index 9ca0799..5c64ecf 100644 --- a/script/Upgrade.s.sol +++ b/script/Upgrade.s.sol @@ -26,16 +26,16 @@ contract Upgrade is Script { } function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + // require(vm.envExists("DEPLOYER_ADDRESS"), "DEPLOYER_ADDRESS env var not set"); + address deployerAddress = vm.envAddress("DEPLOYER_ADDRESS"); - address deployerAddress = vm.addr(deployerPrivateKey); console.log("Deployer address: ", deployerAddress); console.log("Deployer balance: ", deployerAddress.balance); console.log("BlockNumber: ", block.number); console.log("ChainId: ", getChainId()); console.log("Deploying vault..."); - vm.startBroadcast(deployerPrivateKey); + vm.startBroadcast(deployerAddress); // Deploy new implementation ATokenVaultV2 newImple = new ATokenVaultV2(