From 3ab22f2750fc49752a12ea0b9ac31b21bbe572e7 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Mon, 25 Sep 2023 11:37:26 -0400 Subject: [PATCH] Modify our Lynx strategy so that TACoApplication can be deployed on Goerli, and child application etc. on Mumbai. The bridge is non-existent but owners of the contract can execute txs to similate bridge/synching functionality. Separate deployment scripts for Goerli deployment, and Mumbai. --- contracts/contracts/testnet/LynxSet.sol | 192 ++---------------- .../lynx/lynx-alpha-13-params.json | 4 +- .../lynx/lynx-alpha-13-root-params.json | 24 +++ scripts/deploy_lynx_root.py | 78 +++++++ 4 files changed, 121 insertions(+), 177 deletions(-) create mode 100644 deployments/constructor_params/lynx/lynx-alpha-13-root-params.json create mode 100644 scripts/deploy_lynx_root.py diff --git a/contracts/contracts/testnet/LynxSet.sol b/contracts/contracts/testnet/LynxSet.sol index 8f6d0542..0fa6503e 100644 --- a/contracts/contracts/testnet/LynxSet.sol +++ b/contracts/contracts/testnet/LynxSet.sol @@ -8,190 +8,32 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../coordination/ITACoRootToChild.sol"; import "../coordination/ITACoChildToRoot.sol"; import "../coordination/TACoChildApplication.sol"; +import "../TACoApplication.sol"; -contract LynxRootApplication is Ownable, ITACoChildToRoot { - struct StakingProviderInfo { - address operator; - bool operatorConfirmed; - uint64 operatorStartTimestamp; - uint96 authorized; - } - - uint96 public immutable minimumAuthorization = 40000000000000000000000; - uint256 public immutable minOperatorSeconds = 3600; - ITACoRootToChild public childApplication; - mapping(address => StakingProviderInfo) public stakingProviderInfo; - address[] public stakingProviders; - mapping(address => address) internal _stakingProviderFromOperator; - - function setChildApplication(ITACoRootToChild _childApplication) external onlyOwner { - childApplication = _childApplication; - } - - function updateAuthorization(address _stakingProvider, uint96 _amount) external onlyOwner { - if (address(childApplication) != address(0)) { - childApplication.updateAuthorization(_stakingProvider, _amount); - } - } - - function confirmOperatorAddress(address _operator) external override { - address stakingProvider = _stakingProviderFromOperator[_operator]; - if (stakingProvider == address(0)) { - return; - } - StakingProviderInfo storage info = stakingProviderInfo[stakingProvider]; - if (!info.operatorConfirmed) { - info.operatorConfirmed = true; - } - } - - // - // Required TACoApplication functions - // - function stakingProviderFromOperator(address _operator) public view returns (address) { - return _stakingProviderFromOperator[_operator]; - } - - function getOperatorFromStakingProvider( - address _stakingProvider - ) public view returns (address) { - return stakingProviderInfo[_stakingProvider].operator; - } - - function getActiveStakingProviders( - uint256 _startIndex, - uint256 _maxStakingProviders - ) - external - view - returns (uint256 allAuthorizedTokens, uint256[2][] memory activeStakingProviders) - { - uint256 endIndex = stakingProviders.length; - require(_startIndex < endIndex, "Wrong start index"); - if (_maxStakingProviders != 0 && _startIndex + _maxStakingProviders < endIndex) { - endIndex = _startIndex + _maxStakingProviders; - } - activeStakingProviders = new uint256[2][](endIndex - _startIndex); - allAuthorizedTokens = 0; - - uint256 resultIndex = 0; - for (uint256 i = _startIndex; i < endIndex; i++) { - address stakingProvider = stakingProviders[i]; - StakingProviderInfo storage info = stakingProviderInfo[stakingProvider]; - uint256 eligibleAmount = info.authorized; - activeStakingProviders[resultIndex][0] = uint256(uint160(stakingProvider)); - activeStakingProviders[resultIndex++][1] = eligibleAmount; - allAuthorizedTokens += eligibleAmount; - } - assembly { - mstore(activeStakingProviders, resultIndex) - } - } - - function isAuthorized(address _stakingProvider) public view returns (bool) { - return stakingProviderInfo[_stakingProvider].authorized > 0; - } - - function authorizedStake(address _stakingProvider) public view returns (uint96) { - return stakingProviderInfo[_stakingProvider].authorized; - } +contract LynxMockTACoChildApplication is Ownable, ITACoChildToRoot { + ITACoChildToRoot public immutable rootApplication; - function isOperatorConfirmed(address _operator) public view returns (bool) { - address stakingProvider = _stakingProviderFromOperator[_operator]; - StakingProviderInfo storage info = stakingProviderInfo[stakingProvider]; - return info.operatorConfirmed; - } - - function getStakingProvidersLength() external view returns (uint256) { - return stakingProviders.length; - } - - function bondOperator(address _stakingProvider, address _operator) external onlyOwner { - StakingProviderInfo storage info = stakingProviderInfo[_stakingProvider]; - address previousOperator = info.operator; + constructor(ITACoChildToRoot _rootApplication) { require( - _operator != previousOperator, - "Specified operator is already bonded with this provider" + address(_rootApplication) != address(0), + "Address for root application must be specified" ); - // If this staker had a operator ... - if (previousOperator != address(0)) { - // Remove the old relation "operator->stakingProvider" - _stakingProviderFromOperator[previousOperator] = address(0); - } - - if (_operator != address(0)) { - require( - _stakingProviderFromOperator[_operator] == address(0), - "Specified operator is already in use" - ); - // Set new operator->stakingProvider relation - _stakingProviderFromOperator[_operator] = _stakingProvider; - } - - if (info.operatorStartTimestamp == 0) { - stakingProviders.push(_stakingProvider); - } - - // Bond new operator (or unbond if _operator == address(0)) - info.operator = _operator; - info.operatorStartTimestamp = uint64(block.timestamp); - info.operatorConfirmed = false; - if (address(childApplication) != address(0)) { - childApplication.updateOperator(_stakingProvider, _operator); - } + rootApplication = _rootApplication; } - // - // Remaining IApplication functions - // - - // solhint-disable-next-line no-empty-blocks - function withdrawRewards(address stakingProvider) external {} - - function authorizationIncreased( - address _stakingProvider, - // solhint-disable-next-line no-unused-vars - uint96 _fromAmount, - uint96 _toAmount - ) external onlyOwner { - require( - _stakingProvider != address(0) && _toAmount > 0, - "Input parameters must be specified" - ); - require(_toAmount >= minimumAuthorization, "Authorization must be greater than minimum"); - - StakingProviderInfo storage info = stakingProviderInfo[_stakingProvider]; - require( - _stakingProviderFromOperator[_stakingProvider] == address(0) || - _stakingProviderFromOperator[_stakingProvider] == _stakingProvider, - "A provider can't be an operator for another provider" - ); - - info.authorized = _toAmount; - if (address(childApplication) != address(0)) { - childApplication.updateAuthorization(_stakingProvider, _toAmount); - } - } - - function authorizationDecreaseRequested( - address stakingProvider, - uint96 fromAmount, - uint96 toAmount // solhint-disable-next-line no-empty-blocks - ) external {} - - function involuntaryAuthorizationDecrease( - address stakingProvider, - uint96 fromAmount, - uint96 toAmount // solhint-disable-next-line no-empty-blocks - ) external {} - - // solhint-disable-next-line no-unused-vars - function availableRewards(address stakingProvider) external view returns (uint96) { - return 0; + function confirmOperatorAddress(address operator) external override onlyOwner { + rootApplication.confirmOperatorAddress(operator); } } -contract LynxMockRootApplication is Ownable, ITACoChildToRoot, ITACoRootToChild { +// Goerli <---------> Mumbai .... +// LynxTACoApplication LynxMockTACoApplication <---> LynxTACoChildApplication +// +// +// Registry: +// ^ TACoApplication +// ^ TACoChildApplication +contract LynxMockTACoApplication is Ownable, ITACoChildToRoot, ITACoRootToChild { ITACoRootToChild public childApplication; function setChildApplication(ITACoRootToChild _childApplication) external onlyOwner { diff --git a/deployments/constructor_params/lynx/lynx-alpha-13-params.json b/deployments/constructor_params/lynx/lynx-alpha-13-params.json index 973a7ad5..d6239c43 100644 --- a/deployments/constructor_params/lynx/lynx-alpha-13-params.json +++ b/deployments/constructor_params/lynx/lynx-alpha-13-params.json @@ -1,7 +1,7 @@ { - "LynxRootApplication": {}, + "LynxMockRootApplication": {}, "LynxTACoChildApplication": { - "_rootApplication": "$LynxRootApplication" + "_rootApplication": "$LynxMockRootApplication" }, "LynxRitualToken": { "_totalSupplyOfTokens": 10000000000000000000000000 diff --git a/deployments/constructor_params/lynx/lynx-alpha-13-root-params.json b/deployments/constructor_params/lynx/lynx-alpha-13-root-params.json new file mode 100644 index 00000000..6fd0dc72 --- /dev/null +++ b/deployments/constructor_params/lynx/lynx-alpha-13-root-params.json @@ -0,0 +1,24 @@ +{ + "LynxRitualToken": { + "_totalSupplyOfTokens": 10000000000000000000000000 + }, + "ThresholdStakingForTACoApplicationMock": {}, + "ProxyAdmin": {}, + "TACoApplication": { + "_token": "$LynxRitualToken", + "_tStaking": "$ThresholdStakingForTACoApplicationMock", + "_minimumAuthorization": 40000000000000000000000, + "_minOperatorSeconds": 3600, + "_rewardDuration": 604800, + "_deauthorizationDuration": 5184000, + "_commitmentDurationOptions": [15724800, 31449600] + }, + "TransparentUpgradeableProxy": { + "_logic": "$TACoApplication", + "admin_": "$ProxyAdmin", + "_data": "$EMPTY_BYTES" + }, + "LynxMockTACoChildApplication": { + "_rootApplication": "$TACoApplication" + } +} diff --git a/scripts/deploy_lynx_root.py b/scripts/deploy_lynx_root.py new file mode 100644 index 00000000..c906c223 --- /dev/null +++ b/scripts/deploy_lynx_root.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 + +from ape import networks, project +from scripts.constants import ( + ARTIFACTS_DIR, + CONSTRUCTOR_PARAMS_DIR, + CURRENT_NETWORK, + LOCAL_BLOCKCHAIN_ENVIRONMENTS, +) +from scripts.deployment import prepare_deployment +from scripts.registry import registry_from_ape_deployments + +VERIFY = CURRENT_NETWORK not in LOCAL_BLOCKCHAIN_ENVIRONMENTS +CONSTRUCTOR_PARAMS_FILEPATH = CONSTRUCTOR_PARAMS_DIR / "lynx" / "lynx-alpha-13-root-params.json" +REGISTRY_FILEPATH = ARTIFACTS_DIR / "lynx" / "lynx-alpha-13-root-registry.json" + +OZ_DEPENDENCY = project.dependencies["openzeppelin"]["4.9.1"] + + +def main(): + """ + This script deploys only the Lynx TACo Root Application. + """ + + deployer, params = prepare_deployment( + params_filepath=CONSTRUCTOR_PARAMS_FILEPATH, + registry_filepath=REGISTRY_FILEPATH, + ) + + reward_token = deployer.deploy(*params.get(project.LynxRitualToken), **params.get_kwargs()) + + mock_threshold_staking = deployer.deploy( + *params.get(project.ThresholdStakingForTACoApplicationMock), **params.get_kwargs() + ) + + proxy_admin = deployer.deploy(*params.get(OZ_DEPENDENCY.ProxyAdmin), **params.get_kwargs()) + + _ = deployer.deploy(*params.get(project.TACoApplication), **params.get_kwargs()) + + proxy = deployer.deploy( + *params.get(OZ_DEPENDENCY.TransparentUpgradeableProxy), **params.get_kwargs() + ) + + print("\nWrapping TACoApplication in proxy") + taco_application = project.TACoApplication.at(proxy.address) + + print("\nSetting TACoApplication on ThresholdStakingMock") + mock_threshold_staking.setApplication(taco_application.address, sender=deployer) + + print("\nInitialize TACoApplication proxy") + taco_application.initialize(sender=deployer) + + mock_taco_child = deployer.deploy( + *params.get(project.LynxMockTACoChildApplication), **params.get_kwargs() + ) + + print(f"\nSetting child application {mock_taco_child.address} on TACoApplication") + taco_application.setChildApplication(mock_taco_child.address, sender=deployer) + + deployments = [ + reward_token, + proxy_admin, + mock_threshold_staking, + proxy, + taco_application, + mock_taco_child, + ] + + output_filepath = registry_from_ape_deployments( + deployments=deployments, output_filepath=REGISTRY_FILEPATH + ) + print(f"(i) Registry written to {output_filepath}!") + + if VERIFY: + etherscan = networks.provider.network.explorer + for deployment in deployments: + print(f"(i) Verifying {deployment.contract_type.name}...") + etherscan.publish_contract(deployment.address)