diff --git a/.gitmodules b/.gitmodules index 5d08ca4..0983c9e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "lib/collateral"] - path = lib/collateral - url = https://github.com/symbioticfi/collateral [submodule "lib/core"] path = lib/core url = https://github.com/symbioticfi/core diff --git a/README.md b/README.md index e5470b0..cc280ba 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,6 @@ ETH_RPC_URL= ETHERSCAN_API_KEY= ``` -\* ETH_RPC_URL is optional. - \* ETHERSCAN_API_KEY is optional. ### Build diff --git a/lib/collateral b/lib/collateral deleted file mode 160000 index ae76e3e..0000000 --- a/lib/collateral +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ae76e3ee44e0ef584545e2f14f75f4ebc2211957 diff --git a/package.json b/package.json index 277a11c..5a815ad 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ ], "dependencies": { "@openzeppelin/contracts": "5.0.2", - "@openzeppelin/contracts-upgradeable": "5.0.2" + "@openzeppelin/contracts-upgradeable": "5.0.2", + "@symbioticfi/core": "1.0.0-devnet.3" } } diff --git a/remappings.txt b/remappings.txt index 297c185..2c79519 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,8 +1,5 @@ forge-std/=lib/forge-std/src/ @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ -@symbiotic/core/contracts/=lib/core/src/contracts/ -@symbiotic/core/interfaces/=lib/core/src/interfaces/ -@symbiotic/core/mocks/=lib/core/test/mocks/ -@symbiotic/collateral/contracts/=lib/collateral/src/contracts/ -@symbiotic/collateral/interfaces/=lib/collateral/src/interfaces/ -@symbiotic/collateral/mocks/=lib/collateral/test/mocks/ \ No newline at end of file +@symbioticfi/core/src/contracts/=lib/core/src/contracts/ +@symbioticfi/core/src/interfaces/=lib/core/src/interfaces/ +@symbioticfi/core/test/mocks/=lib/core/test/mocks/ \ No newline at end of file diff --git a/src/contracts/DefaultCollateralMigrator.sol b/src/contracts/DefaultCollateralMigrator.sol index fc5f8b6..14cfc54 100644 --- a/src/contracts/DefaultCollateralMigrator.sol +++ b/src/contracts/DefaultCollateralMigrator.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; -import {IDefaultCollateralMigrator} from "src/interfaces/IDefaultCollateralMigrator.sol"; +import {IDefaultCollateralMigrator} from "../interfaces/IDefaultCollateralMigrator.sol"; +import {IDefaultCollateral} from "../interfaces/defaultCollateral/IDefaultCollateral.sol"; -import {IDefaultCollateral} from "@symbiotic/collateral/interfaces/defaultCollateral/IDefaultCollateral.sol"; -import {IVault} from "@symbiotic/core/interfaces/vault/IVault.sol"; +import {IVault} from "@symbioticfi/core/src/interfaces/vault/IVault.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/src/interfaces/defaultCollateral/IDefaultCollateral.sol b/src/interfaces/defaultCollateral/IDefaultCollateral.sol new file mode 100644 index 0000000..265acbf --- /dev/null +++ b/src/interfaces/defaultCollateral/IDefaultCollateral.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IDefaultCollateral is IERC20 { + /** + * @notice Get the collateral's underlying asset. + * @return asset address of the underlying asset + */ + function asset() external view returns (address); + + /** + * @notice Get a maximum possible collateral total supply. + * @return maximum collateral total supply + */ + function limit() external view returns (uint256); + + /** + * @notice Get an address of the limit increaser. + * @return address of the limit increaser + */ + function limitIncreaser() external view returns (address); + + /** + * @notice Deposit a given amount of the underlying asset, and mint the collateral to a particular recipient. + * @param recipient address of the collateral's recipient + * @param amount amount of the underlying asset + * @return amount of the collateral minted + */ + function deposit(address recipient, uint256 amount) external returns (uint256); + + /** + * @notice Deposit a given amount of the underlying asset using a permit functionality, and mint the collateral to a particular recipient. + * @param recipient address of the collateral's recipient + * @param amount amount of the underlying asset + * @param deadline timestamp of the signature's deadline + * @param v v component of the signature + * @param r r component of the signature + * @param s s component of the signature + * @return amount of the collateral minted + */ + function deposit( + address recipient, + uint256 amount, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external returns (uint256); + + /** + * @notice Withdraw a given amount of the underlying asset, and transfer it to a particular recipient. + * @param recipient address of the underlying asset's recipient + * @param amount amount of the underlying asset + */ + function withdraw(address recipient, uint256 amount) external; + + /** + * @notice Increase a limit of maximum collateral total supply. + * @param amount amount to increase the limit by + * @dev Called only by limitIncreaser. + */ + function increaseLimit( + uint256 amount + ) external; + + /** + * @notice Set a new limit increaser. + * @param limitIncreaser address of the new limit increaser + * @dev Called only by limitIncreaser. + */ + function setLimitIncreaser( + address limitIncreaser + ) external; +} diff --git a/src/interfaces/defaultCollateral/IDefaultCollateralFactory.sol b/src/interfaces/defaultCollateral/IDefaultCollateralFactory.sol new file mode 100644 index 0000000..9f28f8b --- /dev/null +++ b/src/interfaces/defaultCollateral/IDefaultCollateralFactory.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +interface IDefaultCollateralFactory { + /** + * @notice Create a default collateral with a given asset. + * @param asset address of the underlying asset + * @param initialLimit initial limit for maximum collateral total supply + * @param limitIncreaser address of the limit increaser (optional) + * @return address of the created collateral + */ + function create(address asset, uint256 initialLimit, address limitIncreaser) external returns (address); +} diff --git a/test/DefaultCollateralMigrator.t.sol b/test/DefaultCollateralMigrator.t.sol index e5fa7f9..c8fc00f 100644 --- a/test/DefaultCollateralMigrator.t.sol +++ b/test/DefaultCollateralMigrator.t.sol @@ -3,32 +3,32 @@ pragma solidity 0.8.25; import {Test, console2} from "forge-std/Test.sol"; -import {DefaultCollateralMigrator} from "src/contracts/DefaultCollateralMigrator.sol"; - -import {DefaultCollateralFactory} from "@symbiotic/collateral/contracts/defaultCollateral/DefaultCollateralFactory.sol"; -import {DefaultCollateral} from "@symbiotic/collateral/contracts/defaultCollateral/DefaultCollateral.sol"; - -import {VaultFactory} from "@symbiotic/core/contracts/VaultFactory.sol"; -import {DelegatorFactory} from "@symbiotic/core/contracts/DelegatorFactory.sol"; -import {SlasherFactory} from "@symbiotic/core/contracts/SlasherFactory.sol"; -import {NetworkRegistry} from "@symbiotic/core/contracts/NetworkRegistry.sol"; -import {OperatorRegistry} from "@symbiotic/core/contracts/OperatorRegistry.sol"; -import {MetadataService} from "@symbiotic/core/contracts/service/MetadataService.sol"; -import {NetworkMiddlewareService} from "@symbiotic/core/contracts/service/NetworkMiddlewareService.sol"; -import {OptInService} from "@symbiotic/core/contracts/service/OptInService.sol"; - -import {Vault} from "@symbiotic/core/contracts/vault/Vault.sol"; -import {NetworkRestakeDelegator} from "@symbiotic/core/contracts/delegator/NetworkRestakeDelegator.sol"; -import {FullRestakeDelegator} from "@symbiotic/core/contracts/delegator/FullRestakeDelegator.sol"; -import {Slasher} from "@symbiotic/core/contracts/slasher/Slasher.sol"; -import {VetoSlasher} from "@symbiotic/core/contracts/slasher/VetoSlasher.sol"; - -import {Token} from "@symbiotic/core/mocks/Token.sol"; -import {FeeOnTransferToken} from "@symbiotic/core/mocks/FeeOnTransferToken.sol"; -import {VaultConfigurator, IVaultConfigurator} from "@symbiotic/core/contracts/VaultConfigurator.sol"; -import {IVault} from "@symbiotic/core/interfaces/IVaultConfigurator.sol"; -import {INetworkRestakeDelegator} from "@symbiotic/core/interfaces/delegator/INetworkRestakeDelegator.sol"; -import {IBaseDelegator} from "@symbiotic/core/interfaces/delegator/IBaseDelegator.sol"; +import {DefaultCollateralMigrator} from "../src/contracts/DefaultCollateralMigrator.sol"; + +import {IDefaultCollateralFactory} from "../src/interfaces/defaultCollateral/IDefaultCollateralFactory.sol"; +import {IDefaultCollateral} from "../src/interfaces/defaultCollateral/IDefaultCollateral.sol"; + +import {VaultFactory} from "@symbioticfi/core/src/contracts/VaultFactory.sol"; +import {DelegatorFactory} from "@symbioticfi/core/src/contracts/DelegatorFactory.sol"; +import {SlasherFactory} from "@symbioticfi/core/src/contracts/SlasherFactory.sol"; +import {NetworkRegistry} from "@symbioticfi/core/src/contracts/NetworkRegistry.sol"; +import {OperatorRegistry} from "@symbioticfi/core/src/contracts/OperatorRegistry.sol"; +import {MetadataService} from "@symbioticfi/core/src/contracts/service/MetadataService.sol"; +import {NetworkMiddlewareService} from "@symbioticfi/core/src/contracts/service/NetworkMiddlewareService.sol"; +import {OptInService} from "@symbioticfi/core/src/contracts/service/OptInService.sol"; + +import {Vault} from "@symbioticfi/core/src/contracts/vault/Vault.sol"; +import {NetworkRestakeDelegator} from "@symbioticfi/core/src/contracts/delegator/NetworkRestakeDelegator.sol"; +import {FullRestakeDelegator} from "@symbioticfi/core/src/contracts/delegator/FullRestakeDelegator.sol"; +import {Slasher} from "@symbioticfi/core/src/contracts/slasher/Slasher.sol"; +import {VetoSlasher} from "@symbioticfi/core/src/contracts/slasher/VetoSlasher.sol"; + +import {Token} from "@symbioticfi/core/test/mocks/Token.sol"; +import {FeeOnTransferToken} from "@symbioticfi/core/test/mocks/FeeOnTransferToken.sol"; +import {VaultConfigurator, IVaultConfigurator} from "@symbioticfi/core/src/contracts/VaultConfigurator.sol"; +import {IVault} from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol"; +import {INetworkRestakeDelegator} from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol"; +import {IBaseDelegator} from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -39,10 +39,12 @@ contract DefaultCollateralMigratorTest is Test { address bob; uint256 bobPrivateKey; - DefaultCollateralFactory defaultCollateralFactory; + address public constant DEFAULT_COLLATERAL_FACTORY = 0x1BC8FCFbE6Aa17e4A7610F51B888f34583D202Ec; - DefaultCollateral collateral; - DefaultCollateral feeOnTransferCollateral; + IDefaultCollateralFactory defaultCollateralFactory; + + IDefaultCollateral collateral; + IDefaultCollateral feeOnTransferCollateral; VaultFactory vaultFactory; DelegatorFactory delegatorFactory; @@ -68,6 +70,9 @@ contract DefaultCollateralMigratorTest is Test { DefaultCollateralMigrator defaultCollateralMigrator; function setUp() public { + uint256 mainnetFork = vm.createFork(vm.rpcUrl("mainnet")); + vm.selectFork(mainnetFork); + owner = address(this); (alice, alicePrivateKey) = makeAddrAndKey("alice"); (bob, bobPrivateKey) = makeAddrAndKey("bob"); @@ -138,15 +143,15 @@ contract DefaultCollateralMigratorTest is Test { Token token = new Token("Token"); FeeOnTransferToken feeOnTransferToken = new FeeOnTransferToken("FeeOnTransferToken"); - defaultCollateralFactory = new DefaultCollateralFactory(); + defaultCollateralFactory = IDefaultCollateralFactory(DEFAULT_COLLATERAL_FACTORY); address defaultCollateralAddress = defaultCollateralFactory.create(address(token), type(uint256).max, address(0)); - collateral = DefaultCollateral(defaultCollateralAddress); + collateral = IDefaultCollateral(defaultCollateralAddress); defaultCollateralAddress = defaultCollateralFactory.create(address(feeOnTransferToken), type(uint256).max, address(0)); - feeOnTransferCollateral = DefaultCollateral(defaultCollateralAddress); + feeOnTransferCollateral = IDefaultCollateral(defaultCollateralAddress); token.approve(address(collateral), type(uint256).max); @@ -201,7 +206,9 @@ contract DefaultCollateralMigratorTest is Test { defaultCollateralMigrator = new DefaultCollateralMigrator(); } - function test_Migrate(uint256 amount) public { + function test_Migrate( + uint256 amount + ) public { amount = bound(amount, 1, 1000 * 1e18); uint256 balanceBeforeCollateralThis = collateral.balanceOf(address(this)); @@ -231,7 +238,9 @@ contract DefaultCollateralMigratorTest is Test { ); } - function test_MigrateFeeOnTransferToken(uint256 amount) public { + function test_MigrateFeeOnTransferToken( + uint256 amount + ) public { amount = bound(amount, 3, 500 * 1e18); uint256 balanceBeforeCollateralThis = feeOnTransferCollateral.balanceOf(address(this)); @@ -274,7 +283,9 @@ contract DefaultCollateralMigratorTest is Test { ); } - function _getVault(uint48 epochDuration) internal returns (Vault) { + function _getVault( + uint48 epochDuration + ) internal returns (Vault) { address[] memory networkLimitSetRoleHolders = new address[](1); networkLimitSetRoleHolders[0] = alice; address[] memory operatorNetworkSharesSetRoleHolders = new address[](1);