From da65a211eb151c1abeaa52f84ea2df7229ccc7e6 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 27 Nov 2023 12:34:28 +0000 Subject: [PATCH 001/210] chore: ready the deployment --- script/Abstract.Deploy.Single.s.sol | 124 ++++++++++-------- script/output/137/Polygon-latest.json | 25 ---- script/output/43114/Avalanche-latest.json | 25 ---- script/output/56/Binance-latest.json | 25 ---- .../137/Polygon-latest.json | 25 ---- .../43114/Avalanche-latest.json | 25 ---- .../56/Binance-latest.json | 25 ---- .../third_deployment/100/Gnosis-latest.json | 26 ---- .../third_deployment/137/Polygon-latest.json | 26 ---- .../43114/Avalanche-latest.json | 26 ---- .../third_deployment/56/Binance-latest.json | 26 ---- src/SuperPositions.sol | 16 +-- test/invariant/VaultShares.invariant.t.sol | 14 +- test/unit/roles/SuperRBAC.t.sol | 28 ++-- .../super-positions/super-positions.t.sol | 4 +- test/unit/super-registry/SuperRegistry.t.sol | 28 ++-- .../superform-router/SuperformRouter.AA.t.sol | 20 +-- test/utils/BaseSetup.sol | 97 ++++++-------- test/utils/InvariantProtocolActions.sol | 4 +- test/utils/ProtocolActions.sol | 24 +--- utils/run_script_tenderly.sh | 8 +- 21 files changed, 174 insertions(+), 447 deletions(-) delete mode 100644 script/output/137/Polygon-latest.json delete mode 100644 script/output/43114/Avalanche-latest.json delete mode 100644 script/output/56/Binance-latest.json delete mode 100644 script/post-2ndaudit-deployment/137/Polygon-latest.json delete mode 100644 script/post-2ndaudit-deployment/43114/Avalanche-latest.json delete mode 100644 script/post-2ndaudit-deployment/56/Binance-latest.json delete mode 100644 script/third_deployment/100/Gnosis-latest.json delete mode 100644 script/third_deployment/137/Polygon-latest.json delete mode 100644 script/third_deployment/43114/Avalanche-latest.json delete mode 100644 script/third_deployment/56/Binance-latest.json diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index f0851392b..1e7281dce 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -114,7 +114,7 @@ abstract contract AbstractDeploySingle is Script { "EmergencyQueue" ]; - bytes32 constant salt = "FOURTH_DEPLOYMENT_POST_GERARD"; + bytes32 constant salt = "CANTINA_DEPLOYMENT_2"; enum Chains { Ethereum, @@ -349,39 +349,44 @@ abstract contract AbstractDeploySingle is Script { /// @dev 1 - Deploy SuperRBAC vars.superRBAC = address( - new SuperRBAC{salt: salt}(ISuperRBAC.InitialRoleSetup({ - admin: ownerAddress, - emergencyAdmin: ownerAddress, - paymentAdmin: 0xD911673eAF0D3e15fe662D58De15511c5509bAbB, - csrProcessor: 0x23c658FE050B4eAeB9401768bF5911D11621629c, - tlProcessor: ownerAddress, - brProcessor: ownerAddress, - csrUpdater: 0xaEbb4b9f7e16BEE2a0963569a5E33eE10E478a5f, - srcVaaRelayer: ownerAddress, - dstSwapper: 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, - csrRescuer: 0x90ed07A867bDb6a73565D7abBc7434Dd810Fafc5, - csrDisputer: ownerAddress - })) + new SuperRBAC{ salt: salt }( + ISuperRBAC.InitialRoleSetup({ + admin: ownerAddress, + emergencyAdmin: ownerAddress, + paymentAdmin: 0xD911673eAF0D3e15fe662D58De15511c5509bAbB, + csrProcessor: 0x23c658FE050B4eAeB9401768bF5911D11621629c, + tlProcessor: ownerAddress, + brProcessor: ownerAddress, + csrUpdater: 0xaEbb4b9f7e16BEE2a0963569a5E33eE10E478a5f, + srcVaaRelayer: ownerAddress, + dstSwapper: 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, + csrRescuer: 0x90ed07A867bDb6a73565D7abBc7434Dd810Fafc5, + csrDisputer: ownerAddress + }) + ) ); contracts[vars.chainId][bytes32(bytes("SuperRBAC"))] = vars.superRBAC; vars.superRBACC = SuperRBAC(vars.superRBAC); /// @dev 2 - Deploy SuperRegistry - vars.superRegistry = address(new SuperRegistry{salt: salt}(vars.superRBAC)); + vars.superRegistry = address(new SuperRegistry{ salt: salt }(vars.superRBAC)); contracts[vars.chainId][bytes32(bytes("SuperRegistry"))] = vars.superRegistry; vars.superRegistryC = SuperRegistry(vars.superRegistry); vars.superRBACC.setSuperRegistry(vars.superRegistry); vars.superRegistryC.setPermit2(CANONICAL_PERMIT2); + /// @dev sets max number of vaults per destination + vars.superRegistryC.setVaultLimitPerTx(vars.chainId, 5); + /// @dev 3.1 - deploy Core State Registry - vars.coreStateRegistry = address(new CoreStateRegistry{salt: salt}(vars.superRegistryC)); + vars.coreStateRegistry = address(new CoreStateRegistry{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("CoreStateRegistry"))] = vars.coreStateRegistry; vars.superRegistryC.setAddress(vars.superRegistryC.CORE_STATE_REGISTRY(), vars.coreStateRegistry, vars.chainId); /// @dev 3.2 - deploy Form State Registry - vars.timelockStateRegistry = address(new TimelockStateRegistry{salt: salt}(vars.superRegistryC)); + vars.timelockStateRegistry = address(new TimelockStateRegistry{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("TimelockStateRegistry"))] = vars.timelockStateRegistry; vars.superRegistryC.setAddress( @@ -389,7 +394,7 @@ abstract contract AbstractDeploySingle is Script { ); /// @dev 3.3 - deploy Broadcast State Registry - vars.broadcastRegistry = address(new BroadcastRegistry{salt: salt}(vars.superRegistryC)); + vars.broadcastRegistry = address(new BroadcastRegistry{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("BroadcastRegistry"))] = vars.broadcastRegistry; vars.superRegistryC.setAddress(vars.superRegistryC.BROADCAST_REGISTRY(), vars.broadcastRegistry, vars.chainId); @@ -407,42 +412,37 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setStateRegistryAddress(registryIds, registryAddresses); /// @dev 4- deploy Payment Helper - vars.paymentHelper = address(new PaymentHelper{salt: salt}(vars.superRegistry)); + vars.paymentHelper = address(new PaymentHelper{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("PaymentHelper"))] = vars.paymentHelper; vars.superRegistryC.setAddress(vars.superRegistryC.PAYMENT_HELPER(), vars.paymentHelper, vars.chainId); + /// @dev 5.1- deploy Layerzero Implementation - vars.lzImplementation = address(new LayerzeroImplementation{salt: salt}(vars.superRegistryC)); + vars.lzImplementation = address(new LayerzeroImplementation{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("LayerzeroImplementation"))] = vars.lzImplementation; LayerzeroImplementation(payable(vars.lzImplementation)).setLzEndpoint(lzEndpoints[trueIndex]); /// @dev 5.2- deploy Hyperlane Implementation - vars.hyperlaneImplementation = address(new HyperlaneImplementation{salt: salt}(vars.superRegistryC)); + vars.hyperlaneImplementation = address(new HyperlaneImplementation{ salt: salt }(vars.superRegistryC)); HyperlaneImplementation(vars.hyperlaneImplementation).setHyperlaneConfig( IMailbox(hyperlaneMailboxes[trueIndex]), IInterchainGasPaymaster(hyperlanePaymasters[trueIndex]) ); contracts[vars.chainId][bytes32(bytes("HyperlaneImplementation"))] = vars.hyperlaneImplementation; /// @dev 5.3- deploy Wormhole Automatic Relayer Implementation - vars.wormholeImplementation = address( - new WormholeARImplementation{salt: salt}( - vars.superRegistryC - ) - ); + vars.wormholeImplementation = address(new WormholeARImplementation{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("WormholeARImplementation"))] = vars.wormholeImplementation; WormholeARImplementation(vars.wormholeImplementation).setWormholeRelayer(wormholeRelayer); /// @dev 6.5- deploy Wormhole Specialized Relayer Implementation - vars.wormholeSRImplementation = address( - new WormholeSRImplementation{salt: salt}( - vars.superRegistryC - ) - ); + vars.wormholeSRImplementation = address(new WormholeSRImplementation{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("WormholeSRImplementation"))] = vars.wormholeSRImplementation; WormholeSRImplementation(vars.wormholeSRImplementation).setWormholeCore(wormholeCore[trueIndex]); + /// @dev FIXME who is the wormhole relayer on mainnet? + WormholeSRImplementation(vars.wormholeSRImplementation).setRelayer(ownerAddress); vars.ambAddresses[0] = vars.lzImplementation; vars.ambAddresses[1] = vars.hyperlaneImplementation; @@ -450,13 +450,13 @@ abstract contract AbstractDeploySingle is Script { vars.ambAddresses[3] = vars.wormholeSRImplementation; /// @dev 6- deploy liquidity validators - vars.lifiValidator = address(new LiFiValidator{salt: salt}(vars.superRegistry)); + vars.lifiValidator = address(new LiFiValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("LiFiValidator"))] = vars.lifiValidator; - vars.socketValidator = address(new SocketValidator{salt: salt}(vars.superRegistry)); + vars.socketValidator = address(new SocketValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SocketValidator"))] = vars.socketValidator; - vars.socketOneInchValidator = address(new SocketOneInchValidator{salt: salt}(vars.superRegistry)); + vars.socketOneInchValidator = address(new SocketOneInchValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SocketOneInchValidator"))] = vars.socketOneInchValidator; bridgeValidators[0] = vars.lifiValidator; @@ -464,7 +464,7 @@ abstract contract AbstractDeploySingle is Script { bridgeValidators[2] = vars.socketOneInchValidator; /// @dev 7 - Deploy SuperformFactory - vars.factory = address(new SuperformFactory{salt: salt}(vars.superRegistry)); + vars.factory = address(new SuperformFactory{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperformFactory"))] = vars.factory; @@ -474,15 +474,15 @@ abstract contract AbstractDeploySingle is Script { /// @dev 8 - Deploy 4626Form implementations // Standard ERC4626 Form - vars.erc4626Form = address(new ERC4626Form{salt: salt}(vars.superRegistry)); + vars.erc4626Form = address(new ERC4626Form{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("ERC4626Form"))] = vars.erc4626Form; // Timelock + ERC4626 Form - vars.erc4626TimelockForm = address(new ERC4626TimelockForm{salt: salt}(vars.superRegistry)); + vars.erc4626TimelockForm = address(new ERC4626TimelockForm{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("ERC4626TimelockForm"))] = vars.erc4626TimelockForm; /// 9 KYCDao ERC4626 Form - vars.kycDao4626Form = address(new ERC4626KYCDaoForm{salt: salt}(vars.superRegistry)); + vars.kycDao4626Form = address(new ERC4626KYCDaoForm{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; /// @dev 9 - Add newly deployed form implementations to Factory, formBeaconId 1 @@ -493,14 +493,14 @@ abstract contract AbstractDeploySingle is Script { ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2]); /// @dev 10 - Deploy SuperformRouter - vars.superformRouter = address(new SuperformRouter{salt: salt}(vars.superRegistry)); + vars.superformRouter = address(new SuperformRouter{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperformRouter"))] = vars.superformRouter; vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_ROUTER(), vars.superformRouter, vars.chainId); /// @dev 11 - Deploy SuperPositions vars.superPositions = - address(new SuperPositions{salt: salt}("https://apiv2-dev.superform.xyz/", vars.superRegistry)); + address(new SuperPositions{ salt: salt }("https://apiv2-dev.superform.xyz/", vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperPositions"))] = vars.superPositions; vars.superRegistryC.setAddress(vars.superRegistryC.SUPER_POSITIONS(), vars.superPositions, vars.chainId); @@ -511,24 +511,37 @@ abstract contract AbstractDeploySingle is Script { ); /// @dev 12 - Deploy Payload Helper - vars.PayloadHelper = address(new PayloadHelper{salt: salt}( vars.superRegistry)); + vars.PayloadHelper = address(new PayloadHelper{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("PayloadHelper"))] = vars.PayloadHelper; vars.superRegistryC.setAddress(vars.superRegistryC.PAYLOAD_HELPER(), vars.PayloadHelper, vars.chainId); /// @dev 13 - Deploy PayMaster - vars.payMaster = address(new PayMaster{salt: salt}(vars.superRegistry)); + vars.payMaster = address(new PayMaster{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes32("PayMaster"))] = vars.payMaster; vars.superRegistryC.setAddress(vars.superRegistryC.PAYMASTER(), vars.payMaster, vars.chainId); /// @dev 14 - Deploy Dst Swapper - vars.dstSwapper = address(new DstSwapper{salt: salt}(vars.superRegistry)); + vars.dstSwapper = address(new DstSwapper{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("DstSwapper"))] = vars.dstSwapper; vars.superRegistryC.setAddress(vars.superRegistryC.DST_SWAPPER(), vars.dstSwapper, vars.chainId); - /// @dev 15 - Super Registry extra setters - vars.superRegistryC.setBridgeAddresses(bridgeIds, BRIDGE_ADDRESSES[vars.chainId], bridgeValidators); + if (vars.chainId == BASE) { + uint8[] memory bridgeIdsBase = new uint8[](1); + bridgeIdsBase[0] = 1; + + address[] memory bridgeAddressesBase = new address[](1); + bridgeAddressesBase[0] = BRIDGE_ADDRESSES[vars.chainId][0]; + + address[] memory bridgeValidatorsBase = new address[](1); + bridgeValidatorsBase[0] = bridgeValidators[0]; + /// @dev 15 - Super Registry extra setters + vars.superRegistryC.setBridgeAddresses(bridgeIdsBase, bridgeAddressesBase, bridgeValidatorsBase); + } else { + /// @dev 15 - Super Registry extra setters + vars.superRegistryC.setBridgeAddresses(bridgeIds, BRIDGE_ADDRESSES[vars.chainId], bridgeValidators); + } /// @dev configures lzImplementation and hyperlane to super registry SuperRegistry(payable(getContract(vars.chainId, "SuperRegistry"))).setAmbAddress( @@ -542,11 +555,11 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_PROCESSOR(), 0x23c658FE050B4eAeB9401768bF5911D11621629c, vars.chainId ); + vars.superRegistryC.setAddress(vars.superRegistryC.BROADCAST_REGISTRY_PROCESSOR(), ownerAddress, vars.chainId); + vars.superRegistryC.setAddress(vars.superRegistryC.TIMELOCK_REGISTRY_PROCESSOR(), ownerAddress, vars.chainId); vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_UPDATER(), 0xaEbb4b9f7e16BEE2a0963569a5E33eE10E478a5f, vars.chainId ); - vars.superRegistryC.setAddress(vars.superRegistryC.BROADCAST_REGISTRY_PROCESSOR(), ownerAddress, vars.chainId); - vars.superRegistryC.setAddress(vars.superRegistryC.TIMELOCK_REGISTRY_PROCESSOR(), ownerAddress, vars.chainId); vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_RESCUER(), 0x90ed07A867bDb6a73565D7abBc7434Dd810Fafc5, vars.chainId ); @@ -557,7 +570,7 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setDelay(86_400); /// @dev 17 deploy emergency queue - vars.emergencyQueue = address(new EmergencyQueue{salt: salt}(vars.superRegistry)); + vars.emergencyQueue = address(new EmergencyQueue{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("EmergencyQueue"))] = vars.emergencyQueue; vars.superRegistryC.setAddress(vars.superRegistryC.EMERGENCY_QUEUE(), vars.emergencyQueue, vars.chainId); @@ -565,9 +578,10 @@ abstract contract AbstractDeploySingle is Script { PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain( vars.chainId, 1, abi.encode(PRICE_FEEDS[vars.chainId][vars.chainId]) ); + PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 8, abi.encode(50 * 10 ** 9 wei)); + PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 9, abi.encode(750)); PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 10, abi.encode(40_000)); PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 11, abi.encode(50_000)); - PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 8, abi.encode(50 * 10 ** 9 wei)); vm.stopBroadcast(); @@ -602,10 +616,7 @@ abstract contract AbstractDeploySingle is Script { vars.wormholeSRImplementation = _readContract(chainNames[trueIndex], vars.chainId, "WormholeSRImplementation"); vars.superRegistry = _readContract(chainNames[trueIndex], vars.chainId, "SuperRegistry"); vars.paymentHelper = _readContract(chainNames[trueIndex], vars.chainId, "PaymentHelper"); - vars.superRegistryC = - SuperRegistry(payable(_readContract(chainNames[trueIndex], vars.chainId, "SuperRegistry"))); - - vars.superRegistryC.setVaultLimitPerTx(vars.chainId, 5); + vars.superRegistryC = SuperRegistry(vars.superRegistry); /// @dev Set all trusted remotes for each chain & configure amb chains ids for (uint256 j = 0; j < finalDeployedChains.length; j++) { @@ -687,8 +698,7 @@ abstract contract AbstractDeploySingle is Script { vars.wormholeSRImplementation = _readContract(chainNames[trueIndex], vars.chainId, "WormholeSRImplementation"); vars.superRegistry = _readContract(chainNames[trueIndex], vars.chainId, "SuperRegistry"); vars.paymentHelper = _readContract(chainNames[trueIndex], vars.chainId, "PaymentHelper"); - vars.superRegistryC = - SuperRegistry(payable(_readContract(chainNames[trueIndex], vars.chainId, "SuperRegistry"))); + vars.superRegistryC = SuperRegistry(payable(vars.superRegistry)); _configureCurrentChainBasedOnTargetDestinations( CurrentChainBasedOnDstvars( @@ -796,7 +806,6 @@ abstract contract AbstractDeploySingle is Script { /// @dev FIXME missing attribution of WORMHOLE_VAA_RELAYER_ROLE SuperRegistry(payable(vars.superRegistry)).setRequiredMessagingQuorum(vars.dstChainId, 1); - vars.superRegistryC.setVaultLimitPerTx(vars.dstChainId, 5); /// @dev these values are mocks and has to be replaced @@ -817,7 +826,7 @@ abstract contract AbstractDeploySingle is Script { 12e8, /// 12 usd 28 gwei, - 10 wei, + 750, 10_000, 10_000 ) @@ -915,6 +924,7 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_RESCUER(), 0x90ed07A867bDb6a73565D7abBc7434Dd810Fafc5, vars.dstChainId ); + vars.superRegistryC.setAddress(vars.superRegistryC.CORE_REGISTRY_DISPUTER(), ownerAddress, vars.dstChainId); vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, vars.dstChainId diff --git a/script/output/137/Polygon-latest.json b/script/output/137/Polygon-latest.json deleted file mode 100644 index 92e8b98c8..000000000 --- a/script/output/137/Polygon-latest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "BroadcastRegistry": "0x0000De3D90Ccb27F68243ab40108441a5e3B86E2", - "CoreStateRegistry": "0x8bb85499f0A5597d3A9906aCcd08F5f8a174821C", - "DstSwapper": "0xD8A271116A13f303a732FD03daae21D39fa43c77", - "ERC4626Form": "0x072C1161752f32E7bf4194cEc27169EB073cE454", - "ERC4626KYCDaoForm": "0x67E0E62D93aB690B953e837588bF4EC9359509Dc", - "ERC4626TimelockForm": "0x6a5f7d306A8671b98c46b5E688f8Cc278a94242f", - "EmergencyQueue": "0x4Fe261779D4F8809779C784aEc5804b14dcaBdA2", - "HyperlaneImplementation": "0x8e903340B85a883794D5815659EE626f537C1B62", - "LayerzeroImplementation": "0x4a87F7b7FC35ECE020217162771A1F7A1Ef28bdd", - "LiFiValidator": "0x11c6fa99d3dA49bAfAB41955E3522854177B8f08", - "PayMaster": "0xa6090933B175Dacd6eaF371b6F30eb2DdE66f309", - "PayloadHelper": "0x7C2077cd2Bcfa57774c966D68C7D71Ec00CaE03f", - "PaymentHelper": "0xFF2AC7F895aB3CE9Dc4F2Dc418F055D16f9809Bd", - "SocketOneInchValidator": "0x7223AdbE94A4A68b16F361B162F8E8D5620F2794", - "SocketValidator": "0xD325d5E01583456CB41F497aD6F19b1E84fF0048", - "SuperPositions": "0x32cfCE25D2046E117014f55FEDef9920FEbb521d", - "SuperRBAC": "0xaEe51F3447FE2729cB37FeE8293d7ade322fC212", - "SuperRegistry": "0x8aDb0665aC9e9d19fEB6a885bE4149c72B4f02F5", - "SuperformFactory": "0x75F5e5D3b13275F6Bbca9Ee8B6391257EBA060F8", - "SuperformRouter": "0x7f75E44ba19E6448815F9BDb81B963aB2F82D6dc", - "TimelockStateRegistry": "0x9593099fCBac1aCc1De5d4BF98B50F87aa034dB7", - "WormholeARImplementation": "0xfBa6220cadff48B3381B3B2f59013e73015fC024", - "WormholeSRImplementation": "0xe2E9b3D0A15f42ad275da855Bf93ba6440D20ce2" -} \ No newline at end of file diff --git a/script/output/43114/Avalanche-latest.json b/script/output/43114/Avalanche-latest.json deleted file mode 100644 index 92e8b98c8..000000000 --- a/script/output/43114/Avalanche-latest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "BroadcastRegistry": "0x0000De3D90Ccb27F68243ab40108441a5e3B86E2", - "CoreStateRegistry": "0x8bb85499f0A5597d3A9906aCcd08F5f8a174821C", - "DstSwapper": "0xD8A271116A13f303a732FD03daae21D39fa43c77", - "ERC4626Form": "0x072C1161752f32E7bf4194cEc27169EB073cE454", - "ERC4626KYCDaoForm": "0x67E0E62D93aB690B953e837588bF4EC9359509Dc", - "ERC4626TimelockForm": "0x6a5f7d306A8671b98c46b5E688f8Cc278a94242f", - "EmergencyQueue": "0x4Fe261779D4F8809779C784aEc5804b14dcaBdA2", - "HyperlaneImplementation": "0x8e903340B85a883794D5815659EE626f537C1B62", - "LayerzeroImplementation": "0x4a87F7b7FC35ECE020217162771A1F7A1Ef28bdd", - "LiFiValidator": "0x11c6fa99d3dA49bAfAB41955E3522854177B8f08", - "PayMaster": "0xa6090933B175Dacd6eaF371b6F30eb2DdE66f309", - "PayloadHelper": "0x7C2077cd2Bcfa57774c966D68C7D71Ec00CaE03f", - "PaymentHelper": "0xFF2AC7F895aB3CE9Dc4F2Dc418F055D16f9809Bd", - "SocketOneInchValidator": "0x7223AdbE94A4A68b16F361B162F8E8D5620F2794", - "SocketValidator": "0xD325d5E01583456CB41F497aD6F19b1E84fF0048", - "SuperPositions": "0x32cfCE25D2046E117014f55FEDef9920FEbb521d", - "SuperRBAC": "0xaEe51F3447FE2729cB37FeE8293d7ade322fC212", - "SuperRegistry": "0x8aDb0665aC9e9d19fEB6a885bE4149c72B4f02F5", - "SuperformFactory": "0x75F5e5D3b13275F6Bbca9Ee8B6391257EBA060F8", - "SuperformRouter": "0x7f75E44ba19E6448815F9BDb81B963aB2F82D6dc", - "TimelockStateRegistry": "0x9593099fCBac1aCc1De5d4BF98B50F87aa034dB7", - "WormholeARImplementation": "0xfBa6220cadff48B3381B3B2f59013e73015fC024", - "WormholeSRImplementation": "0xe2E9b3D0A15f42ad275da855Bf93ba6440D20ce2" -} \ No newline at end of file diff --git a/script/output/56/Binance-latest.json b/script/output/56/Binance-latest.json deleted file mode 100644 index 92e8b98c8..000000000 --- a/script/output/56/Binance-latest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "BroadcastRegistry": "0x0000De3D90Ccb27F68243ab40108441a5e3B86E2", - "CoreStateRegistry": "0x8bb85499f0A5597d3A9906aCcd08F5f8a174821C", - "DstSwapper": "0xD8A271116A13f303a732FD03daae21D39fa43c77", - "ERC4626Form": "0x072C1161752f32E7bf4194cEc27169EB073cE454", - "ERC4626KYCDaoForm": "0x67E0E62D93aB690B953e837588bF4EC9359509Dc", - "ERC4626TimelockForm": "0x6a5f7d306A8671b98c46b5E688f8Cc278a94242f", - "EmergencyQueue": "0x4Fe261779D4F8809779C784aEc5804b14dcaBdA2", - "HyperlaneImplementation": "0x8e903340B85a883794D5815659EE626f537C1B62", - "LayerzeroImplementation": "0x4a87F7b7FC35ECE020217162771A1F7A1Ef28bdd", - "LiFiValidator": "0x11c6fa99d3dA49bAfAB41955E3522854177B8f08", - "PayMaster": "0xa6090933B175Dacd6eaF371b6F30eb2DdE66f309", - "PayloadHelper": "0x7C2077cd2Bcfa57774c966D68C7D71Ec00CaE03f", - "PaymentHelper": "0xFF2AC7F895aB3CE9Dc4F2Dc418F055D16f9809Bd", - "SocketOneInchValidator": "0x7223AdbE94A4A68b16F361B162F8E8D5620F2794", - "SocketValidator": "0xD325d5E01583456CB41F497aD6F19b1E84fF0048", - "SuperPositions": "0x32cfCE25D2046E117014f55FEDef9920FEbb521d", - "SuperRBAC": "0xaEe51F3447FE2729cB37FeE8293d7ade322fC212", - "SuperRegistry": "0x8aDb0665aC9e9d19fEB6a885bE4149c72B4f02F5", - "SuperformFactory": "0x75F5e5D3b13275F6Bbca9Ee8B6391257EBA060F8", - "SuperformRouter": "0x7f75E44ba19E6448815F9BDb81B963aB2F82D6dc", - "TimelockStateRegistry": "0x9593099fCBac1aCc1De5d4BF98B50F87aa034dB7", - "WormholeARImplementation": "0xfBa6220cadff48B3381B3B2f59013e73015fC024", - "WormholeSRImplementation": "0xe2E9b3D0A15f42ad275da855Bf93ba6440D20ce2" -} \ No newline at end of file diff --git a/script/post-2ndaudit-deployment/137/Polygon-latest.json b/script/post-2ndaudit-deployment/137/Polygon-latest.json deleted file mode 100644 index 92e8b98c8..000000000 --- a/script/post-2ndaudit-deployment/137/Polygon-latest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "BroadcastRegistry": "0x0000De3D90Ccb27F68243ab40108441a5e3B86E2", - "CoreStateRegistry": "0x8bb85499f0A5597d3A9906aCcd08F5f8a174821C", - "DstSwapper": "0xD8A271116A13f303a732FD03daae21D39fa43c77", - "ERC4626Form": "0x072C1161752f32E7bf4194cEc27169EB073cE454", - "ERC4626KYCDaoForm": "0x67E0E62D93aB690B953e837588bF4EC9359509Dc", - "ERC4626TimelockForm": "0x6a5f7d306A8671b98c46b5E688f8Cc278a94242f", - "EmergencyQueue": "0x4Fe261779D4F8809779C784aEc5804b14dcaBdA2", - "HyperlaneImplementation": "0x8e903340B85a883794D5815659EE626f537C1B62", - "LayerzeroImplementation": "0x4a87F7b7FC35ECE020217162771A1F7A1Ef28bdd", - "LiFiValidator": "0x11c6fa99d3dA49bAfAB41955E3522854177B8f08", - "PayMaster": "0xa6090933B175Dacd6eaF371b6F30eb2DdE66f309", - "PayloadHelper": "0x7C2077cd2Bcfa57774c966D68C7D71Ec00CaE03f", - "PaymentHelper": "0xFF2AC7F895aB3CE9Dc4F2Dc418F055D16f9809Bd", - "SocketOneInchValidator": "0x7223AdbE94A4A68b16F361B162F8E8D5620F2794", - "SocketValidator": "0xD325d5E01583456CB41F497aD6F19b1E84fF0048", - "SuperPositions": "0x32cfCE25D2046E117014f55FEDef9920FEbb521d", - "SuperRBAC": "0xaEe51F3447FE2729cB37FeE8293d7ade322fC212", - "SuperRegistry": "0x8aDb0665aC9e9d19fEB6a885bE4149c72B4f02F5", - "SuperformFactory": "0x75F5e5D3b13275F6Bbca9Ee8B6391257EBA060F8", - "SuperformRouter": "0x7f75E44ba19E6448815F9BDb81B963aB2F82D6dc", - "TimelockStateRegistry": "0x9593099fCBac1aCc1De5d4BF98B50F87aa034dB7", - "WormholeARImplementation": "0xfBa6220cadff48B3381B3B2f59013e73015fC024", - "WormholeSRImplementation": "0xe2E9b3D0A15f42ad275da855Bf93ba6440D20ce2" -} \ No newline at end of file diff --git a/script/post-2ndaudit-deployment/43114/Avalanche-latest.json b/script/post-2ndaudit-deployment/43114/Avalanche-latest.json deleted file mode 100644 index 92e8b98c8..000000000 --- a/script/post-2ndaudit-deployment/43114/Avalanche-latest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "BroadcastRegistry": "0x0000De3D90Ccb27F68243ab40108441a5e3B86E2", - "CoreStateRegistry": "0x8bb85499f0A5597d3A9906aCcd08F5f8a174821C", - "DstSwapper": "0xD8A271116A13f303a732FD03daae21D39fa43c77", - "ERC4626Form": "0x072C1161752f32E7bf4194cEc27169EB073cE454", - "ERC4626KYCDaoForm": "0x67E0E62D93aB690B953e837588bF4EC9359509Dc", - "ERC4626TimelockForm": "0x6a5f7d306A8671b98c46b5E688f8Cc278a94242f", - "EmergencyQueue": "0x4Fe261779D4F8809779C784aEc5804b14dcaBdA2", - "HyperlaneImplementation": "0x8e903340B85a883794D5815659EE626f537C1B62", - "LayerzeroImplementation": "0x4a87F7b7FC35ECE020217162771A1F7A1Ef28bdd", - "LiFiValidator": "0x11c6fa99d3dA49bAfAB41955E3522854177B8f08", - "PayMaster": "0xa6090933B175Dacd6eaF371b6F30eb2DdE66f309", - "PayloadHelper": "0x7C2077cd2Bcfa57774c966D68C7D71Ec00CaE03f", - "PaymentHelper": "0xFF2AC7F895aB3CE9Dc4F2Dc418F055D16f9809Bd", - "SocketOneInchValidator": "0x7223AdbE94A4A68b16F361B162F8E8D5620F2794", - "SocketValidator": "0xD325d5E01583456CB41F497aD6F19b1E84fF0048", - "SuperPositions": "0x32cfCE25D2046E117014f55FEDef9920FEbb521d", - "SuperRBAC": "0xaEe51F3447FE2729cB37FeE8293d7ade322fC212", - "SuperRegistry": "0x8aDb0665aC9e9d19fEB6a885bE4149c72B4f02F5", - "SuperformFactory": "0x75F5e5D3b13275F6Bbca9Ee8B6391257EBA060F8", - "SuperformRouter": "0x7f75E44ba19E6448815F9BDb81B963aB2F82D6dc", - "TimelockStateRegistry": "0x9593099fCBac1aCc1De5d4BF98B50F87aa034dB7", - "WormholeARImplementation": "0xfBa6220cadff48B3381B3B2f59013e73015fC024", - "WormholeSRImplementation": "0xe2E9b3D0A15f42ad275da855Bf93ba6440D20ce2" -} \ No newline at end of file diff --git a/script/post-2ndaudit-deployment/56/Binance-latest.json b/script/post-2ndaudit-deployment/56/Binance-latest.json deleted file mode 100644 index 92e8b98c8..000000000 --- a/script/post-2ndaudit-deployment/56/Binance-latest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "BroadcastRegistry": "0x0000De3D90Ccb27F68243ab40108441a5e3B86E2", - "CoreStateRegistry": "0x8bb85499f0A5597d3A9906aCcd08F5f8a174821C", - "DstSwapper": "0xD8A271116A13f303a732FD03daae21D39fa43c77", - "ERC4626Form": "0x072C1161752f32E7bf4194cEc27169EB073cE454", - "ERC4626KYCDaoForm": "0x67E0E62D93aB690B953e837588bF4EC9359509Dc", - "ERC4626TimelockForm": "0x6a5f7d306A8671b98c46b5E688f8Cc278a94242f", - "EmergencyQueue": "0x4Fe261779D4F8809779C784aEc5804b14dcaBdA2", - "HyperlaneImplementation": "0x8e903340B85a883794D5815659EE626f537C1B62", - "LayerzeroImplementation": "0x4a87F7b7FC35ECE020217162771A1F7A1Ef28bdd", - "LiFiValidator": "0x11c6fa99d3dA49bAfAB41955E3522854177B8f08", - "PayMaster": "0xa6090933B175Dacd6eaF371b6F30eb2DdE66f309", - "PayloadHelper": "0x7C2077cd2Bcfa57774c966D68C7D71Ec00CaE03f", - "PaymentHelper": "0xFF2AC7F895aB3CE9Dc4F2Dc418F055D16f9809Bd", - "SocketOneInchValidator": "0x7223AdbE94A4A68b16F361B162F8E8D5620F2794", - "SocketValidator": "0xD325d5E01583456CB41F497aD6F19b1E84fF0048", - "SuperPositions": "0x32cfCE25D2046E117014f55FEDef9920FEbb521d", - "SuperRBAC": "0xaEe51F3447FE2729cB37FeE8293d7ade322fC212", - "SuperRegistry": "0x8aDb0665aC9e9d19fEB6a885bE4149c72B4f02F5", - "SuperformFactory": "0x75F5e5D3b13275F6Bbca9Ee8B6391257EBA060F8", - "SuperformRouter": "0x7f75E44ba19E6448815F9BDb81B963aB2F82D6dc", - "TimelockStateRegistry": "0x9593099fCBac1aCc1De5d4BF98B50F87aa034dB7", - "WormholeARImplementation": "0xfBa6220cadff48B3381B3B2f59013e73015fC024", - "WormholeSRImplementation": "0xe2E9b3D0A15f42ad275da855Bf93ba6440D20ce2" -} \ No newline at end of file diff --git a/script/third_deployment/100/Gnosis-latest.json b/script/third_deployment/100/Gnosis-latest.json deleted file mode 100644 index e96048c46..000000000 --- a/script/third_deployment/100/Gnosis-latest.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "BroadcastRegistry": "0xF565376A77c3c03759a999090F652De1B99d66a0", - "CoreStateRegistry": "0x3ddcaad48B0312e1558b481e04E3805bD14c3848", - "DstSwapper": "0x8b5cb412108ecF4d88906f0D251EFab9039e3EAC", - "ERC4626Form": "0xE00Bd2f1CCb8E68426E778E3e4824c27a103DcD3", - "ERC4626KYCDaoForm": "0x5f89C4eB79e7150bE0e4776eD0CdC943b4D70396", - "ERC4626TimelockForm": "0xF17C4DfF77E0304789b13492b6BCc3d9eB1E9F76", - "EmergencyQueue": "0x55621dB794B84A0F26174267de7D2bd8548f0Ebe", - "HyperlaneImplementation": "0x7bDF57585d23e5605ae466Be0ec829A0cF2884A5", - "LayerzeroImplementation": "0x109D47fF9c8BBdD2dC91a7f57FED93b8E5e34277", - "LiFiValidator": "0x918666c51ADC87D13dEd78FA1169D705103F2B12", - "PayMaster": "0x011a925048E52E2F2129F9CA5A1cE75FC597DFf8", - "PayloadHelper": "0x50d8D65aB23fD8e8859f4cAEb7834926d0647994", - "PaymentHelper": "0x019f18235E0dF2064e1AA1B786fD8bFF55B99485", - "SocketOneInchValidator": "0xb74b1549911B8bD3c5c55A38c3b72D5C4F467c16", - "SocketValidator": "0xFe630DD09Ce2e51fE48D68801754Cf822C5F4a45", - "SuperPositions": "0x96206FB919Ef45617cfcf8ED35109FE8431D7B20", - "SuperRBAC": "0xF175De3a338515a192b83624FC5b547072983252", - "SuperRegistry": "0x78aFc74b8cEf314aB2f0EFA6E7743F26c99e5119", - "SuperTransmuter": "0x3cB9E989cBb5BF09195D337De8F56076EFdEC3AD", - "SuperformFactory": "0x40726c201999Db951B430c6A9A054F4a3Cac3ae4", - "SuperformRouter": "0x4d66F472024567BC7Dd7677B4baCd29E10d00CA1", - "TimelockStateRegistry": "0xD23316B549e355303c75fa87EB206aF4011aDC0c", - "WormholeARImplementation": "0x254AB3Fa9246265f8156Bf0c1DdEB0CF5a0Db53E", - "WormholeSRImplementation": "0x540d834BD8388e515A011ad36ec204ac44C0C508" -} \ No newline at end of file diff --git a/script/third_deployment/137/Polygon-latest.json b/script/third_deployment/137/Polygon-latest.json deleted file mode 100644 index e96048c46..000000000 --- a/script/third_deployment/137/Polygon-latest.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "BroadcastRegistry": "0xF565376A77c3c03759a999090F652De1B99d66a0", - "CoreStateRegistry": "0x3ddcaad48B0312e1558b481e04E3805bD14c3848", - "DstSwapper": "0x8b5cb412108ecF4d88906f0D251EFab9039e3EAC", - "ERC4626Form": "0xE00Bd2f1CCb8E68426E778E3e4824c27a103DcD3", - "ERC4626KYCDaoForm": "0x5f89C4eB79e7150bE0e4776eD0CdC943b4D70396", - "ERC4626TimelockForm": "0xF17C4DfF77E0304789b13492b6BCc3d9eB1E9F76", - "EmergencyQueue": "0x55621dB794B84A0F26174267de7D2bd8548f0Ebe", - "HyperlaneImplementation": "0x7bDF57585d23e5605ae466Be0ec829A0cF2884A5", - "LayerzeroImplementation": "0x109D47fF9c8BBdD2dC91a7f57FED93b8E5e34277", - "LiFiValidator": "0x918666c51ADC87D13dEd78FA1169D705103F2B12", - "PayMaster": "0x011a925048E52E2F2129F9CA5A1cE75FC597DFf8", - "PayloadHelper": "0x50d8D65aB23fD8e8859f4cAEb7834926d0647994", - "PaymentHelper": "0x019f18235E0dF2064e1AA1B786fD8bFF55B99485", - "SocketOneInchValidator": "0xb74b1549911B8bD3c5c55A38c3b72D5C4F467c16", - "SocketValidator": "0xFe630DD09Ce2e51fE48D68801754Cf822C5F4a45", - "SuperPositions": "0x96206FB919Ef45617cfcf8ED35109FE8431D7B20", - "SuperRBAC": "0xF175De3a338515a192b83624FC5b547072983252", - "SuperRegistry": "0x78aFc74b8cEf314aB2f0EFA6E7743F26c99e5119", - "SuperTransmuter": "0x3cB9E989cBb5BF09195D337De8F56076EFdEC3AD", - "SuperformFactory": "0x40726c201999Db951B430c6A9A054F4a3Cac3ae4", - "SuperformRouter": "0x4d66F472024567BC7Dd7677B4baCd29E10d00CA1", - "TimelockStateRegistry": "0xD23316B549e355303c75fa87EB206aF4011aDC0c", - "WormholeARImplementation": "0x254AB3Fa9246265f8156Bf0c1DdEB0CF5a0Db53E", - "WormholeSRImplementation": "0x540d834BD8388e515A011ad36ec204ac44C0C508" -} \ No newline at end of file diff --git a/script/third_deployment/43114/Avalanche-latest.json b/script/third_deployment/43114/Avalanche-latest.json deleted file mode 100644 index e96048c46..000000000 --- a/script/third_deployment/43114/Avalanche-latest.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "BroadcastRegistry": "0xF565376A77c3c03759a999090F652De1B99d66a0", - "CoreStateRegistry": "0x3ddcaad48B0312e1558b481e04E3805bD14c3848", - "DstSwapper": "0x8b5cb412108ecF4d88906f0D251EFab9039e3EAC", - "ERC4626Form": "0xE00Bd2f1CCb8E68426E778E3e4824c27a103DcD3", - "ERC4626KYCDaoForm": "0x5f89C4eB79e7150bE0e4776eD0CdC943b4D70396", - "ERC4626TimelockForm": "0xF17C4DfF77E0304789b13492b6BCc3d9eB1E9F76", - "EmergencyQueue": "0x55621dB794B84A0F26174267de7D2bd8548f0Ebe", - "HyperlaneImplementation": "0x7bDF57585d23e5605ae466Be0ec829A0cF2884A5", - "LayerzeroImplementation": "0x109D47fF9c8BBdD2dC91a7f57FED93b8E5e34277", - "LiFiValidator": "0x918666c51ADC87D13dEd78FA1169D705103F2B12", - "PayMaster": "0x011a925048E52E2F2129F9CA5A1cE75FC597DFf8", - "PayloadHelper": "0x50d8D65aB23fD8e8859f4cAEb7834926d0647994", - "PaymentHelper": "0x019f18235E0dF2064e1AA1B786fD8bFF55B99485", - "SocketOneInchValidator": "0xb74b1549911B8bD3c5c55A38c3b72D5C4F467c16", - "SocketValidator": "0xFe630DD09Ce2e51fE48D68801754Cf822C5F4a45", - "SuperPositions": "0x96206FB919Ef45617cfcf8ED35109FE8431D7B20", - "SuperRBAC": "0xF175De3a338515a192b83624FC5b547072983252", - "SuperRegistry": "0x78aFc74b8cEf314aB2f0EFA6E7743F26c99e5119", - "SuperTransmuter": "0x3cB9E989cBb5BF09195D337De8F56076EFdEC3AD", - "SuperformFactory": "0x40726c201999Db951B430c6A9A054F4a3Cac3ae4", - "SuperformRouter": "0x4d66F472024567BC7Dd7677B4baCd29E10d00CA1", - "TimelockStateRegistry": "0xD23316B549e355303c75fa87EB206aF4011aDC0c", - "WormholeARImplementation": "0x254AB3Fa9246265f8156Bf0c1DdEB0CF5a0Db53E", - "WormholeSRImplementation": "0x540d834BD8388e515A011ad36ec204ac44C0C508" -} \ No newline at end of file diff --git a/script/third_deployment/56/Binance-latest.json b/script/third_deployment/56/Binance-latest.json deleted file mode 100644 index e96048c46..000000000 --- a/script/third_deployment/56/Binance-latest.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "BroadcastRegistry": "0xF565376A77c3c03759a999090F652De1B99d66a0", - "CoreStateRegistry": "0x3ddcaad48B0312e1558b481e04E3805bD14c3848", - "DstSwapper": "0x8b5cb412108ecF4d88906f0D251EFab9039e3EAC", - "ERC4626Form": "0xE00Bd2f1CCb8E68426E778E3e4824c27a103DcD3", - "ERC4626KYCDaoForm": "0x5f89C4eB79e7150bE0e4776eD0CdC943b4D70396", - "ERC4626TimelockForm": "0xF17C4DfF77E0304789b13492b6BCc3d9eB1E9F76", - "EmergencyQueue": "0x55621dB794B84A0F26174267de7D2bd8548f0Ebe", - "HyperlaneImplementation": "0x7bDF57585d23e5605ae466Be0ec829A0cF2884A5", - "LayerzeroImplementation": "0x109D47fF9c8BBdD2dC91a7f57FED93b8E5e34277", - "LiFiValidator": "0x918666c51ADC87D13dEd78FA1169D705103F2B12", - "PayMaster": "0x011a925048E52E2F2129F9CA5A1cE75FC597DFf8", - "PayloadHelper": "0x50d8D65aB23fD8e8859f4cAEb7834926d0647994", - "PaymentHelper": "0x019f18235E0dF2064e1AA1B786fD8bFF55B99485", - "SocketOneInchValidator": "0xb74b1549911B8bD3c5c55A38c3b72D5C4F467c16", - "SocketValidator": "0xFe630DD09Ce2e51fE48D68801754Cf822C5F4a45", - "SuperPositions": "0x96206FB919Ef45617cfcf8ED35109FE8431D7B20", - "SuperRBAC": "0xF175De3a338515a192b83624FC5b547072983252", - "SuperRegistry": "0x78aFc74b8cEf314aB2f0EFA6E7743F26c99e5119", - "SuperTransmuter": "0x3cB9E989cBb5BF09195D337De8F56076EFdEC3AD", - "SuperformFactory": "0x40726c201999Db951B430c6A9A054F4a3Cac3ae4", - "SuperformRouter": "0x4d66F472024567BC7Dd7677B4baCd29E10d00CA1", - "TimelockStateRegistry": "0xD23316B549e355303c75fa87EB206aF4011aDC0c", - "WormholeARImplementation": "0x254AB3Fa9246265f8156Bf0c1DdEB0CF5a0Db53E", - "WormholeSRImplementation": "0x540d834BD8388e515A011ad36ec204ac44C0C508" -} \ No newline at end of file diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index 5085e45e5..b5891b974 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -351,13 +351,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { string(abi.encodePacked("SuperPositions AERC20 ", IBaseForm(superform).superformYieldTokenName())); string memory symbol = string(abi.encodePacked("aERC20-", IBaseForm(superform).superformYieldTokenSymbol())); uint8 decimal = uint8(IBaseForm(superform).getVaultDecimals()); - aErc20Token = address( - new aERC20( - name, - symbol, - decimal - ) - ); + aErc20Token = address(new aERC20(name, symbol, decimal)); /// @dev broadcast and deploy to the other destination chains BroadcastMessage memory transmuterPayload = BroadcastMessage( "SUPER_POSITIONS", @@ -397,13 +391,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { abi.decode(message_, (uint64, uint256, uint256, string, string, uint8)); if (aErc20TokenId[superformId] != address(0)) revert AERC20_ALREADY_REGISTERED(); - address aErc20Token = address( - new aERC20( - name, - symbol, - decimal - ) - ); + address aErc20Token = address(new aERC20(name, symbol, decimal)); aErc20TokenId[superformId] = aErc20Token; diff --git a/test/invariant/VaultShares.invariant.t.sol b/test/invariant/VaultShares.invariant.t.sol index 85df4c22e..011cb75c1 100644 --- a/test/invariant/VaultShares.invariant.t.sol +++ b/test/invariant/VaultShares.invariant.t.sol @@ -23,9 +23,17 @@ contract VaultSharesInvariantTest is BaseInvariantTest { vm.selectFork(FORKS[0]); vaultSharesStore = new VaultSharesStore(); - vaultSharesHandler = - new VaultSharesHandler(chainIds, contractNames, coreAddresses, underlyingAddresses, vaultAddresses, - superformAddresses, forksArray, vaultSharesStore, timestampStore); + vaultSharesHandler = new VaultSharesHandler( + chainIds, + contractNames, + coreAddresses, + underlyingAddresses, + vaultAddresses, + superformAddresses, + forksArray, + vaultSharesStore, + timestampStore + ); vm.label({ account: address(vaultSharesStore), newLabel: "VaultSharesStore" }); vm.label({ account: address(vaultSharesHandler), newLabel: "VaultSharesHandler" }); diff --git a/test/unit/roles/SuperRBAC.t.sol b/test/unit/roles/SuperRBAC.t.sol index 074abf1de..8bff8f248 100644 --- a/test/unit/roles/SuperRBAC.t.sol +++ b/test/unit/roles/SuperRBAC.t.sol @@ -24,19 +24,21 @@ contract SuperRBACTest is BaseSetup { function test_setSuperRegistry() public { vm.startPrank(deployer); - SuperRBAC newReg = new SuperRBAC(ISuperRBAC.InitialRoleSetup({ - admin: deployer, - emergencyAdmin: deployer, - paymentAdmin: deployer, - csrProcessor: deployer, - tlProcessor: deployer, - brProcessor: deployer, - csrUpdater: deployer, - srcVaaRelayer: deployer, - dstSwapper: deployer, - csrRescuer: deployer, - csrDisputer: deployer - })); + SuperRBAC newReg = new SuperRBAC( + ISuperRBAC.InitialRoleSetup({ + admin: deployer, + emergencyAdmin: deployer, + paymentAdmin: deployer, + csrProcessor: deployer, + tlProcessor: deployer, + brProcessor: deployer, + csrUpdater: deployer, + srcVaaRelayer: deployer, + dstSwapper: deployer, + csrRescuer: deployer, + csrDisputer: deployer + }) + ); vm.expectRevert(Error.ZERO_ADDRESS.selector); newReg.setSuperRegistry(address(0)); diff --git a/test/unit/super-positions/super-positions.t.sol b/test/unit/super-positions/super-positions.t.sol index d7ff321bb..a593b5d52 100644 --- a/test/unit/super-positions/super-positions.t.sol +++ b/test/unit/super-positions/super-positions.t.sol @@ -354,9 +354,7 @@ contract SuperPositionsTest is BaseSetup { assertGt( uint256( - uint160( - SuperPositions(getContract(chainIds[i], "SuperPositions")).aErc20TokenId(superformId) - ) + uint160(SuperPositions(getContract(chainIds[i], "SuperPositions")).aErc20TokenId(superformId)) ), uint256(0) ); diff --git a/test/unit/super-registry/SuperRegistry.t.sol b/test/unit/super-registry/SuperRegistry.t.sol index 9ff615fe3..9e0b65a22 100644 --- a/test/unit/super-registry/SuperRegistry.t.sol +++ b/test/unit/super-registry/SuperRegistry.t.sol @@ -20,19 +20,21 @@ contract SuperRegistryTest is BaseSetup { vm.selectFork(FORKS[ETH]); superRegistry = SuperRegistry(getContract(ETH, "SuperRegistry")); - fakeRBAC = new SuperRBAC(ISuperRBAC.InitialRoleSetup({ - admin: deployer, - emergencyAdmin: deployer, - paymentAdmin: deployer, - csrProcessor: deployer, - tlProcessor: deployer, - brProcessor: deployer, - csrUpdater: deployer, - srcVaaRelayer: deployer, - dstSwapper: deployer, - csrRescuer: deployer, - csrDisputer: deployer - })); + fakeRBAC = new SuperRBAC( + ISuperRBAC.InitialRoleSetup({ + admin: deployer, + emergencyAdmin: deployer, + paymentAdmin: deployer, + csrProcessor: deployer, + tlProcessor: deployer, + brProcessor: deployer, + csrUpdater: deployer, + srcVaaRelayer: deployer, + dstSwapper: deployer, + csrRescuer: deployer, + csrDisputer: deployer + }) + ); fakeRegistry = new SuperRegistry(address(fakeRBAC)); /// @dev malicious caller diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index 44835c35d..f221dfbc7 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -36,12 +36,14 @@ contract SuperformRouterAATest is ProtocolActions { super.setUp(); vm.selectFork(FORKS[ETH]); - walletSource = - new SmartContractWallet(SuperformRouter(payable(getContract(ETH, "SuperformRouter"))), getContract(ETH, "DAI")); + walletSource = new SmartContractWallet( + SuperformRouter(payable(getContract(ETH, "SuperformRouter"))), getContract(ETH, "DAI") + ); vm.selectFork(FORKS[ARBI]); - walletDestination = - new SmartContractWallet(SuperformRouter(payable(getContract(ARBI, "SuperformRouter"))), getContract(ARBI, "DAI")); + walletDestination = new SmartContractWallet( + SuperformRouter(payable(getContract(ARBI, "SuperformRouter"))), getContract(ARBI, "DAI") + ); } function test_depositWithSmartContractWallet() public { @@ -65,8 +67,9 @@ contract SuperformRouterAATest is ProtocolActions { function test_withdrawWithSmartContractWallet_3rdChainId() public { _xChainDeposit_SmartContractWallet(false, true, "VaultMock", 0); vm.selectFork(FORKS[AVAX]); - SmartContractWallet walletDestinationAVAX = - new SmartContractWallet(SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI")); + SmartContractWallet walletDestinationAVAX = new SmartContractWallet( + SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") + ); _xChainWithdraw_SmartContractWallet(AVAX, address(walletDestinationAVAX), false, "VaultMock", 0); } @@ -80,8 +83,9 @@ contract SuperformRouterAATest is ProtocolActions { function test_withdrawWithSmartContractWallet_3rdChainId_timelock() public { _xChainDeposit_SmartContractWallet(false, true, "ERC4626TimelockMock", 1); vm.selectFork(FORKS[AVAX]); - SmartContractWallet walletDestinationAVAX = - new SmartContractWallet(SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI")); + SmartContractWallet walletDestinationAVAX = new SmartContractWallet( + SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") + ); _xChainWithdraw_SmartContractWallet(AVAX, address(walletDestinationAVAX), false, "ERC4626TimelockMock", 1); } diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index ba57dbfa4..c37fe2a3c 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -366,38 +366,39 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vm.selectFork(vars.fork); /// @dev preference for a local deployment of Permit2 over mainnet version. Has same bytcode - vars.canonicalPermit2 = address(new Permit2Clone{salt: salt}()); + vars.canonicalPermit2 = address(new Permit2Clone{ salt: salt }()); contracts[vars.chainId][bytes32(bytes("CanonicalPermit2"))] = vars.canonicalPermit2; /// @dev 1 - Pigeon helpers allow us to fullfill cross-chain messages in a manner as close to mainnet as /// possible /// @dev 1.1- deploy LZ Helper from Pigeon - vars.lzHelper = address(new LayerZeroHelper{salt: salt}()); + vars.lzHelper = address(new LayerZeroHelper{ salt: salt }()); vm.allowCheatcodes(vars.lzHelper); contracts[vars.chainId][bytes32(bytes("LayerZeroHelper"))] = vars.lzHelper; /// @dev 1.2- deploy Hyperlane Helper from Pigeon - vars.hyperlaneHelper = address(new HyperlaneHelper{salt: salt}()); + vars.hyperlaneHelper = address(new HyperlaneHelper{ salt: salt }()); vm.allowCheatcodes(vars.hyperlaneHelper); contracts[vars.chainId][bytes32(bytes("HyperlaneHelper"))] = vars.hyperlaneHelper; /// @dev 1.3- deploy Wormhole Automatic Relayer Helper from Pigeon - vars.wormholeHelper = address(new WormholeHelper{salt: salt}()); + vars.wormholeHelper = address(new WormholeHelper{ salt: salt }()); vm.allowCheatcodes(vars.wormholeHelper); contracts[vars.chainId][bytes32(bytes("WormholeHelper"))] = vars.wormholeHelper; /// @dev 1.4- deploy Wormhole Specialized Relayer Helper from Pigeon - vars.wormholeBroadcastHelper = address(new WormholeBroadcastHelper.WormholeHelper{salt: salt}()); + vars.wormholeBroadcastHelper = address(new WormholeBroadcastHelper.WormholeHelper{ salt: salt }()); vm.allowCheatcodes(vars.wormholeBroadcastHelper); contracts[vars.chainId][bytes32(bytes("WormholeBroadcastHelper"))] = vars.wormholeBroadcastHelper; /// @dev 2 - Deploy SuperRBAC vars.superRBAC = address( - new SuperRBAC{salt: salt}(ISuperRBAC.InitialRoleSetup({ + new SuperRBAC{ salt: salt }( + ISuperRBAC.InitialRoleSetup({ admin: deployer, emergencyAdmin: deployer, paymentAdmin: deployer, @@ -409,14 +410,15 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { dstSwapper: deployer, csrRescuer: deployer, csrDisputer: deployer - })) + }) + ) ); contracts[vars.chainId][bytes32(bytes("SuperRBAC"))] = vars.superRBAC; vars.superRBACC = SuperRBAC(vars.superRBAC); /// @dev 3 - Deploy SuperRegistry - vars.superRegistry = address(new SuperRegistry{salt: salt}(vars.superRBAC)); + vars.superRegistry = address(new SuperRegistry{ salt: salt }(vars.superRBAC)); contracts[vars.chainId][bytes32(bytes("SuperRegistry"))] = vars.superRegistry; vars.superRegistryC = SuperRegistry(vars.superRegistry); @@ -429,11 +431,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { assert(vars.superRBACC.hasProtocolAdminRole(deployer)); /// @dev 4.1 - deploy Core State Registry - vars.coreStateRegistry = address( - new CoreStateRegistry{salt: salt}( - SuperRegistry(vars.superRegistry) - ) - ); + vars.coreStateRegistry = address(new CoreStateRegistry{ salt: salt }(SuperRegistry(vars.superRegistry))); contracts[vars.chainId][bytes32(bytes("CoreStateRegistry"))] = vars.coreStateRegistry; vars.superRegistryC.setAddress( @@ -441,7 +439,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { ); /// @dev 4.2 - deploy Form State Registry - vars.timelockStateRegistry = address(new TimelockStateRegistry{salt: salt}(vars.superRegistryC)); + vars.timelockStateRegistry = address(new TimelockStateRegistry{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("TimelockStateRegistry"))] = vars.timelockStateRegistry; vars.superRegistryC.setAddress( @@ -449,7 +447,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { ); /// @dev 4.3 - deploy Broadcast State Registry - vars.broadcastRegistry = address(new BroadcastRegistry{salt: salt}(vars.superRegistryC)); + vars.broadcastRegistry = address(new BroadcastRegistry{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("BroadcastRegistry"))] = vars.broadcastRegistry; vars.superRegistryC.setAddress( @@ -469,44 +467,33 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.setStateRegistryAddress(registryIds, registryAddresses); /// @dev 5- deploy Payment Helper - vars.paymentHelper = address(new PaymentHelper{salt: salt}(vars.superRegistry)); + vars.paymentHelper = address(new PaymentHelper{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("PaymentHelper"))] = vars.paymentHelper; vars.superRegistryC.setAddress(vars.superRegistryC.PAYMENT_HELPER(), vars.paymentHelper, vars.chainId); /// @dev 6.1 - deploy Layerzero Implementation - vars.lzImplementation = address(new LayerzeroImplementation{salt: salt}(vars.superRegistryC)); + vars.lzImplementation = address(new LayerzeroImplementation{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("LayerzeroImplementation"))] = vars.lzImplementation; LayerzeroImplementation(payable(vars.lzImplementation)).setLzEndpoint(lzEndpoints[i]); /// @dev 6.2 - deploy Hyperlane Implementation - vars.hyperlaneImplementation = address( - new HyperlaneImplementation{salt: salt}( - SuperRegistry(vars.superRegistry) - ) - ); + vars.hyperlaneImplementation = + address(new HyperlaneImplementation{ salt: salt }(SuperRegistry(vars.superRegistry))); HyperlaneImplementation(vars.hyperlaneImplementation).setHyperlaneConfig( IMailbox(hyperlaneMailboxes[i]), IInterchainGasPaymaster(hyperlanePaymasters[i]) ); contracts[vars.chainId][bytes32(bytes("HyperlaneImplementation"))] = vars.hyperlaneImplementation; /// @dev 6.3- deploy Wormhole Automatic Relayer Implementation - vars.wormholeImplementation = address( - new WormholeARImplementation{salt: salt}( - vars.superRegistryC - ) - ); + vars.wormholeImplementation = address(new WormholeARImplementation{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("WormholeARImplementation"))] = vars.wormholeImplementation; WormholeARImplementation(vars.wormholeImplementation).setWormholeRelayer(wormholeRelayer); /// @dev 6.5- deploy Wormhole Specialized Relayer Implementation - vars.wormholeSRImplementation = address( - new WormholeSRImplementation{salt: salt}( - vars.superRegistryC - ) - ); + vars.wormholeSRImplementation = address(new WormholeSRImplementation{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("WormholeSRImplementation"))] = vars.wormholeSRImplementation; WormholeSRImplementation(vars.wormholeSRImplementation).setWormholeCore(wormholeCore[i]); @@ -519,36 +506,36 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { /// @dev 7.1.1 deploy LiFiRouterMock. This mock is a very minimal versions to allow /// liquidity bridge testing - vars.lifiRouter = address(new LiFiMock{salt: salt}()); + vars.lifiRouter = address(new LiFiMock{ salt: salt }()); contracts[vars.chainId][bytes32(bytes("LiFiMock"))] = vars.lifiRouter; vm.allowCheatcodes(vars.lifiRouter); /// @dev 7.1.2 deploy SocketMock. This mock is a very minimal versions to allow /// liquidity bridge testing - vars.socketRouter = address(new SocketMock{salt:salt}()); + vars.socketRouter = address(new SocketMock{ salt: salt }()); contracts[vars.chainId][bytes32(bytes("SocketMock"))] = vars.socketRouter; vm.allowCheatcodes(vars.socketRouter); /// @dev 7.1.3 deploy SocketOneInchMock. This mock is a very minimal versions to allow /// socket same chain swaps - vars.socketOneInch = address(new SocketOneInchMock{salt: salt}()); + vars.socketOneInch = address(new SocketOneInchMock{ salt: salt }()); contracts[vars.chainId][bytes32(bytes("SocketOneInchMock"))] = vars.socketOneInch; vm.allowCheatcodes(vars.socketOneInch); /// @dev 7.2.1- deploy lifi validator - vars.lifiValidator = address(new LiFiValidator{salt: salt}(vars.superRegistry)); + vars.lifiValidator = address(new LiFiValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("LiFiValidator"))] = vars.lifiValidator; /// @dev 7.2.2- deploy socket validator - vars.socketValidator = address(new SocketValidator{salt: salt}(vars.superRegistry)); + vars.socketValidator = address(new SocketValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SocketValidator"))] = vars.socketValidator; /// @dev 7.2.3- deploy socket one inch validator - vars.socketOneInchValidator = address(new SocketOneInchValidator{salt: salt}(vars.superRegistry)); + vars.socketOneInchValidator = address(new SocketOneInchValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SocketOneInchValidator"))] = vars.socketOneInchValidator; /// @dev 7.3- kycDAO NFT used to test kycDAO vaults - vars.kycDAOMock = address(new KYCDaoNFTMock{salt: salt}()); + vars.kycDAOMock = address(new KYCDaoNFTMock{ salt: salt }()); contracts[vars.chainId][bytes32(bytes("KYCDAOMock"))] = vars.kycDAOMock; bridgeAddresses.push(vars.lifiRouter); @@ -565,7 +552,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { if (vars.UNDERLYING_TOKEN == address(0)) { vars.UNDERLYING_TOKEN = address( - new MockERC20{salt: salt}(UNDERLYING_TOKENS[j], UNDERLYING_TOKENS[j], deployer, hundredBilly) + new MockERC20{ salt: salt }(UNDERLYING_TOKENS[j], UNDERLYING_TOKENS[j], deployer, hundredBilly) ); } else { deal(vars.UNDERLYING_TOKEN, deployer, hundredBilly); @@ -577,9 +564,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { /// NOTE: This loop deploys all vaults on all chainIds with all of the UNDERLYING TOKENS (id x form) x /// chainId for (uint32 j = 0; j < FORM_IMPLEMENTATION_IDS.length; ++j) { - IERC4626[][] memory doubleVaults = new IERC4626[][]( - UNDERLYING_TOKENS.length - ); + IERC4626[][] memory doubleVaults = new IERC4626[][](UNDERLYING_TOKENS.length); for (uint256 k = 0; k < UNDERLYING_TOKENS.length; ++k) { uint256 lenBytecodes = vaultBytecodes2[FORM_IMPLEMENTATION_IDS[j]].vaultBytecode.length; @@ -624,7 +609,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { } /// @dev 9 - Deploy SuperformFactory - vars.factory = address(new SuperformFactory{salt: salt}(vars.superRegistry)); + vars.factory = address(new SuperformFactory{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperformFactory"))] = vars.factory; vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_FACTORY(), vars.factory, vars.chainId); @@ -632,15 +617,15 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { /// @dev 10 - Deploy 4626Form implementations // Standard ERC4626 Form - vars.erc4626Form = address(new ERC4626Form{salt: salt}(vars.superRegistry)); + vars.erc4626Form = address(new ERC4626Form{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("ERC4626Form"))] = vars.erc4626Form; // Timelock + ERC4626 Form - vars.erc4626TimelockForm = address(new ERC4626TimelockForm{salt: salt}(vars.superRegistry)); + vars.erc4626TimelockForm = address(new ERC4626TimelockForm{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("ERC4626TimelockForm"))] = vars.erc4626TimelockForm; // KYCDao ERC4626 Form - vars.kycDao4626Form = address(new ERC4626KYCDaoForm{salt: salt}(vars.superRegistry)); + vars.kycDao4626Form = address(new ERC4626KYCDaoForm{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; /// @dev 11 - Add newly deployed form implementations to Factory @@ -651,14 +636,14 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2]); /// @dev 12 - Deploy SuperformRouter - vars.superformRouter = address(new SuperformRouter{salt: salt}(vars.superRegistry)); + vars.superformRouter = address(new SuperformRouter{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperformRouter"))] = vars.superformRouter; vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_ROUTER(), vars.superformRouter, vars.chainId); /// @dev 13 - Deploy SuperPositions vars.superPositions = - address(new SuperPositions{salt: salt}("https://apiv2-dev.superform.xyz/", vars.superRegistry)); + address(new SuperPositions{ salt: salt }("https://apiv2-dev.superform.xyz/", vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperPositions"))] = vars.superPositions; vars.superRegistryC.setAddress(vars.superRegistryC.SUPER_POSITIONS(), vars.superPositions, vars.chainId); @@ -668,22 +653,18 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { ); /// @dev 14- deploy Payload Helper - vars.PayloadHelper = address( - new PayloadHelper{salt: salt}( - vars.superRegistry - ) - ); + vars.PayloadHelper = address(new PayloadHelper{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("PayloadHelper"))] = vars.PayloadHelper; vars.superRegistryC.setAddress(vars.superRegistryC.PAYLOAD_HELPER(), vars.PayloadHelper, vars.chainId); /// @dev 15 - Deploy PayMaster - vars.payMaster = address(new PayMaster{salt: salt}(vars.superRegistry)); + vars.payMaster = address(new PayMaster{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes32("PayMaster"))] = vars.payMaster; vars.superRegistryC.setAddress(vars.superRegistryC.PAYMASTER(), vars.payMaster, vars.chainId); /// @dev 16 - Deploy Dst Swapper - vars.dstSwapper = address(new DstSwapper{salt: salt}(vars.superRegistry)); + vars.dstSwapper = address(new DstSwapper{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes32("DstSwapper"))] = vars.dstSwapper; vars.superRegistryC.setAddress(vars.superRegistryC.DST_SWAPPER(), vars.dstSwapper, vars.chainId); @@ -705,7 +686,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.setAddress(vars.superRegistryC.DST_SWAPPER_PROCESSOR(), deployer, vars.chainId); vars.superRegistryC.setDelay(86_400); /// @dev 17 deploy emergency queue - vars.emergencyQueue = address(new EmergencyQueue{salt: salt}(vars.superRegistry)); + vars.emergencyQueue = address(new EmergencyQueue{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("EmergencyQueue"))] = vars.emergencyQueue; vars.superRegistryC.setAddress(vars.superRegistryC.EMERGENCY_QUEUE(), vars.emergencyQueue, vars.chainId); @@ -803,7 +784,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { 12e8, /// 12 usd 28 gwei, - 10 wei, + 750, 10_000, 10_000 ) diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index 1e8870e66..87dda7fa9 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -637,9 +637,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { } } - MessagingAssertVars[] memory aV = new MessagingAssertVars[]( - vars.nDestinations - ); + MessagingAssertVars[] memory aV = new MessagingAssertVars[](vars.nDestinations); /// @dev assert good delivery of message on destination by analyzing superformIds and mounts for (uint256 i = 0; i < vars.nDestinations; ++i) { diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 3bc7bde99..321d43ba5 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -844,9 +844,7 @@ abstract contract ProtocolActions is CommonProtocolActions { } } - MessagingAssertVars[] memory aV = new MessagingAssertVars[]( - vars.nDestinations - ); + MessagingAssertVars[] memory aV = new MessagingAssertVars[](vars.nDestinations); CoreStateRegistry stateRegistry; /// @dev assert good delivery of message on destination by analyzing superformIds and mounts @@ -2057,8 +2055,8 @@ abstract contract ProtocolActions is CommonProtocolActions { returns (uint256[] memory previewRedeemAmounts) { vm.selectFork(FORKS[CHAIN_0]); - uint256[] memory superPositionBalances = new uint256[] (superformIds.length); - previewRedeemAmounts = new uint256[] (superformIds.length); + uint256[] memory superPositionBalances = new uint256[](superformIds.length); + previewRedeemAmounts = new uint256[](superformIds.length); address superRegistryAddress = getContract(CHAIN_0, "SuperRegistry"); address superPositionsAddress = @@ -2444,9 +2442,7 @@ abstract contract ProtocolActions is CommonProtocolActions { uint256[] memory amountsToRemint; for (uint256 i = 0; i < vars.nDestinations; ++i) { if (action.multiVaults) { - amountsToRemint = new uint256[]( - multiSuperformsData[i].superformIds.length - ); + amountsToRemint = new uint256[](multiSuperformsData[i].superformIds.length); for (uint256 j = 0; j < multiSuperformsData[i].superformIds.length; ++j) { amountsToRemint[j] = multiSuperformsData[i].amounts[j]; @@ -2508,9 +2504,7 @@ abstract contract ProtocolActions is CommonProtocolActions { uint256[] memory amountsToRemint; for (uint256 i = 0; i < vars.nDestinations; ++i) { if (action.multiVaults) { - amountsToRemint = new uint256[]( - multiSuperformsData[i].superformIds.length - ); + amountsToRemint = new uint256[](multiSuperformsData[i].superformIds.length); for (uint256 j = 0; j < multiSuperformsData[i].superformIds.length; ++j) { amountsToRemint[j] = multiSuperformsData[i].amounts[j]; @@ -2967,9 +2961,7 @@ abstract contract ProtocolActions is CommonProtocolActions { inputBalanceBefore = v.token != NATIVE_TOKEN ? IERC20(v.token).balanceOf(users[action.user]) : users[action.user].balance; } - spAmountBeforeWithdrawPerDestination = new uint256[]( - vars.nDestinations - ); + spAmountBeforeWithdrawPerDestination = new uint256[](vars.nDestinations); for (uint256 i = 0; i < vars.nDestinations; ++i) { (v.superform,,) = singleSuperformsData[i].superformId.getSuperform(); v.partialWithdrawVault = abi.decode(singleSuperformsData[i].extraFormData, (bool)); @@ -3048,9 +3040,7 @@ abstract contract ProtocolActions is CommonProtocolActions { _assertMultiVaultBalance( action.user, multiSuperformsData[i].superformIds, - new uint256[]( - multiSuperformsData[i].superformIds.length - ), + new uint256[](multiSuperformsData[i].superformIds.length), new bool[](multiSuperformsData[i].superformIds.length), false ); diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index ad40b4177..cc45688f2 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -14,9 +14,9 @@ wait FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 -#wait +wait -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 --legacy wait @@ -29,9 +29,9 @@ wait FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 -#wait +wait -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 --legacy #echo Running Stage 3: ... From 562eeaacdfccec854cd9c9f8bf7663e86382a965 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:34:05 +0000 Subject: [PATCH 002/210] chore: deployment complete --- script/Abstract.Deploy.Single.s.sol | 2 +- script/output/137/Polygon-latest.json | 25 +++++++++++++++++++++++ script/output/43114/Avalanche-latest.json | 25 +++++++++++++++++++++++ script/output/56/Binance-latest.json | 25 +++++++++++++++++++++++ utils/run_script_tenderly.sh | 5 +++-- 5 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 script/output/137/Polygon-latest.json create mode 100644 script/output/43114/Avalanche-latest.json create mode 100644 script/output/56/Binance-latest.json diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index 1e7281dce..132ba4580 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -114,7 +114,7 @@ abstract contract AbstractDeploySingle is Script { "EmergencyQueue" ]; - bytes32 constant salt = "CANTINA_DEPLOYMENT_2"; + bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; enum Chains { Ethereum, diff --git a/script/output/137/Polygon-latest.json b/script/output/137/Polygon-latest.json new file mode 100644 index 000000000..16602521e --- /dev/null +++ b/script/output/137/Polygon-latest.json @@ -0,0 +1,25 @@ +{ + "BroadcastRegistry": "0x91A4a6E08401FFC5Cf155d7d6A7234AA0302B160", + "CoreStateRegistry": "0xC525e2EE88E0014F46cb031C33c5148A153108eB", + "DstSwapper": "0x363A6294897577522795c80447f2f2829DCc85c4", + "ERC4626Form": "0x3bfEe78d526063e0207B1a55fD4B284306882247", + "ERC4626KYCDaoForm": "0xd72Ec34384b1ba5bCeC852Fa88420D0f6F90363c", + "ERC4626TimelockForm": "0x87D539863EaB9f3CB99B405929464f6aAb77e81B", + "EmergencyQueue": "0x8Ef837576f37C29BAcd1efb2Eb0ddAadB01DA189", + "HyperlaneImplementation": "0x922d821ddfA8958890d69053CA79a7E619A2790E", + "LayerzeroImplementation": "0x22adbC6BBb1A8C4eFB579268772E7516869E2Cc6", + "LiFiValidator": "0xe1E7b5011E0DcFb823916E8a91DBA9eC383E82C2", + "PayMaster": "0x917455CE06FCD3acFB697781D5E937e1ABcb7694", + "PayloadHelper": "0x3fF04DB7C5D74A544bC76BFabE37732196d56e34", + "PaymentHelper": "0xa4498fa6b5f964a84432Fa007B04255610E21992", + "SocketOneInchValidator": "0xceb161DAC215389B44FE15634A3e207bC886fa09", + "SocketValidator": "0x156889A11Ed41fdAAF3da7394D5cF577bb69eaC4", + "SuperPositions": "0xD240a9674E9a306009071Bd60966F66eA33341Fd", + "SuperRBAC": "0x3487eD8b15c93138573CDC1226CC3ecBb4CD31af", + "SuperRegistry": "0xB0bBFC88896c1a218fbAFab6C8dcf43eD587Ad63", + "SuperformFactory": "0x7791026F1770780c00cEe224F9d0B61c962E9fF8", + "SuperformRouter": "0x51d0a7a59F4e54a273FCbA4Fd4ea9E647e785d95", + "TimelockStateRegistry": "0x1cbf6A3B019dAef506e13bf6A353e3C47Cd8250c", + "WormholeARImplementation": "0x6f1d34A20C0d62A4Fc2eCA0919Fb6fDD73F37428", + "WormholeSRImplementation": "0x63a62c7AF0Ed62C394420dBC7Aa0f803236886aC" +} \ No newline at end of file diff --git a/script/output/43114/Avalanche-latest.json b/script/output/43114/Avalanche-latest.json new file mode 100644 index 000000000..16602521e --- /dev/null +++ b/script/output/43114/Avalanche-latest.json @@ -0,0 +1,25 @@ +{ + "BroadcastRegistry": "0x91A4a6E08401FFC5Cf155d7d6A7234AA0302B160", + "CoreStateRegistry": "0xC525e2EE88E0014F46cb031C33c5148A153108eB", + "DstSwapper": "0x363A6294897577522795c80447f2f2829DCc85c4", + "ERC4626Form": "0x3bfEe78d526063e0207B1a55fD4B284306882247", + "ERC4626KYCDaoForm": "0xd72Ec34384b1ba5bCeC852Fa88420D0f6F90363c", + "ERC4626TimelockForm": "0x87D539863EaB9f3CB99B405929464f6aAb77e81B", + "EmergencyQueue": "0x8Ef837576f37C29BAcd1efb2Eb0ddAadB01DA189", + "HyperlaneImplementation": "0x922d821ddfA8958890d69053CA79a7E619A2790E", + "LayerzeroImplementation": "0x22adbC6BBb1A8C4eFB579268772E7516869E2Cc6", + "LiFiValidator": "0xe1E7b5011E0DcFb823916E8a91DBA9eC383E82C2", + "PayMaster": "0x917455CE06FCD3acFB697781D5E937e1ABcb7694", + "PayloadHelper": "0x3fF04DB7C5D74A544bC76BFabE37732196d56e34", + "PaymentHelper": "0xa4498fa6b5f964a84432Fa007B04255610E21992", + "SocketOneInchValidator": "0xceb161DAC215389B44FE15634A3e207bC886fa09", + "SocketValidator": "0x156889A11Ed41fdAAF3da7394D5cF577bb69eaC4", + "SuperPositions": "0xD240a9674E9a306009071Bd60966F66eA33341Fd", + "SuperRBAC": "0x3487eD8b15c93138573CDC1226CC3ecBb4CD31af", + "SuperRegistry": "0xB0bBFC88896c1a218fbAFab6C8dcf43eD587Ad63", + "SuperformFactory": "0x7791026F1770780c00cEe224F9d0B61c962E9fF8", + "SuperformRouter": "0x51d0a7a59F4e54a273FCbA4Fd4ea9E647e785d95", + "TimelockStateRegistry": "0x1cbf6A3B019dAef506e13bf6A353e3C47Cd8250c", + "WormholeARImplementation": "0x6f1d34A20C0d62A4Fc2eCA0919Fb6fDD73F37428", + "WormholeSRImplementation": "0x63a62c7AF0Ed62C394420dBC7Aa0f803236886aC" +} \ No newline at end of file diff --git a/script/output/56/Binance-latest.json b/script/output/56/Binance-latest.json new file mode 100644 index 000000000..16602521e --- /dev/null +++ b/script/output/56/Binance-latest.json @@ -0,0 +1,25 @@ +{ + "BroadcastRegistry": "0x91A4a6E08401FFC5Cf155d7d6A7234AA0302B160", + "CoreStateRegistry": "0xC525e2EE88E0014F46cb031C33c5148A153108eB", + "DstSwapper": "0x363A6294897577522795c80447f2f2829DCc85c4", + "ERC4626Form": "0x3bfEe78d526063e0207B1a55fD4B284306882247", + "ERC4626KYCDaoForm": "0xd72Ec34384b1ba5bCeC852Fa88420D0f6F90363c", + "ERC4626TimelockForm": "0x87D539863EaB9f3CB99B405929464f6aAb77e81B", + "EmergencyQueue": "0x8Ef837576f37C29BAcd1efb2Eb0ddAadB01DA189", + "HyperlaneImplementation": "0x922d821ddfA8958890d69053CA79a7E619A2790E", + "LayerzeroImplementation": "0x22adbC6BBb1A8C4eFB579268772E7516869E2Cc6", + "LiFiValidator": "0xe1E7b5011E0DcFb823916E8a91DBA9eC383E82C2", + "PayMaster": "0x917455CE06FCD3acFB697781D5E937e1ABcb7694", + "PayloadHelper": "0x3fF04DB7C5D74A544bC76BFabE37732196d56e34", + "PaymentHelper": "0xa4498fa6b5f964a84432Fa007B04255610E21992", + "SocketOneInchValidator": "0xceb161DAC215389B44FE15634A3e207bC886fa09", + "SocketValidator": "0x156889A11Ed41fdAAF3da7394D5cF577bb69eaC4", + "SuperPositions": "0xD240a9674E9a306009071Bd60966F66eA33341Fd", + "SuperRBAC": "0x3487eD8b15c93138573CDC1226CC3ecBb4CD31af", + "SuperRegistry": "0xB0bBFC88896c1a218fbAFab6C8dcf43eD587Ad63", + "SuperformFactory": "0x7791026F1770780c00cEe224F9d0B61c962E9fF8", + "SuperformRouter": "0x51d0a7a59F4e54a273FCbA4Fd4ea9E647e785d95", + "TimelockStateRegistry": "0x1cbf6A3B019dAef506e13bf6A353e3C47Cd8250c", + "WormholeARImplementation": "0x6f1d34A20C0d62A4Fc2eCA0919Fb6fDD73F37428", + "WormholeSRImplementation": "0x63a62c7AF0Ed62C394420dBC7Aa0f803236886aC" +} \ No newline at end of file diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index cc45688f2..020b2fe22 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -3,6 +3,7 @@ BSC_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template bscdevnet --account superform --return-url) POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template polygondevnet --account superform --return-url) AVAX_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template avaxdevnet --account superform --return-url) +BASE_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template basedevnet --account superform --return-url) # Run the script echo Running Stage 1: ... @@ -16,7 +17,7 @@ FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy - wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 --legacy +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait @@ -31,7 +32,7 @@ FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy - wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 --legacy +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 #echo Running Stage 3: ... From 91d1b5f69543dfb0f577f41ded805a84bdad0d96 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 27 Nov 2023 17:26:37 +0000 Subject: [PATCH 003/210] test: fix --- .../137/Polygon-latest.json | 25 ++++++++++++++++++ .../43114/Avalanche-latest.json | 25 ++++++++++++++++++ .../cantina_deployment/56/Binance-latest.json | 25 ++++++++++++++++++ script/output/100/Gnosis-latest.json | 26 ------------------- test/utils/BaseSetup.sol | 16 ++---------- test/utils/ProtocolActions.sol | 6 ++--- 6 files changed, 80 insertions(+), 43 deletions(-) create mode 100644 script/cantina_deployment/137/Polygon-latest.json create mode 100644 script/cantina_deployment/43114/Avalanche-latest.json create mode 100644 script/cantina_deployment/56/Binance-latest.json delete mode 100644 script/output/100/Gnosis-latest.json diff --git a/script/cantina_deployment/137/Polygon-latest.json b/script/cantina_deployment/137/Polygon-latest.json new file mode 100644 index 000000000..16602521e --- /dev/null +++ b/script/cantina_deployment/137/Polygon-latest.json @@ -0,0 +1,25 @@ +{ + "BroadcastRegistry": "0x91A4a6E08401FFC5Cf155d7d6A7234AA0302B160", + "CoreStateRegistry": "0xC525e2EE88E0014F46cb031C33c5148A153108eB", + "DstSwapper": "0x363A6294897577522795c80447f2f2829DCc85c4", + "ERC4626Form": "0x3bfEe78d526063e0207B1a55fD4B284306882247", + "ERC4626KYCDaoForm": "0xd72Ec34384b1ba5bCeC852Fa88420D0f6F90363c", + "ERC4626TimelockForm": "0x87D539863EaB9f3CB99B405929464f6aAb77e81B", + "EmergencyQueue": "0x8Ef837576f37C29BAcd1efb2Eb0ddAadB01DA189", + "HyperlaneImplementation": "0x922d821ddfA8958890d69053CA79a7E619A2790E", + "LayerzeroImplementation": "0x22adbC6BBb1A8C4eFB579268772E7516869E2Cc6", + "LiFiValidator": "0xe1E7b5011E0DcFb823916E8a91DBA9eC383E82C2", + "PayMaster": "0x917455CE06FCD3acFB697781D5E937e1ABcb7694", + "PayloadHelper": "0x3fF04DB7C5D74A544bC76BFabE37732196d56e34", + "PaymentHelper": "0xa4498fa6b5f964a84432Fa007B04255610E21992", + "SocketOneInchValidator": "0xceb161DAC215389B44FE15634A3e207bC886fa09", + "SocketValidator": "0x156889A11Ed41fdAAF3da7394D5cF577bb69eaC4", + "SuperPositions": "0xD240a9674E9a306009071Bd60966F66eA33341Fd", + "SuperRBAC": "0x3487eD8b15c93138573CDC1226CC3ecBb4CD31af", + "SuperRegistry": "0xB0bBFC88896c1a218fbAFab6C8dcf43eD587Ad63", + "SuperformFactory": "0x7791026F1770780c00cEe224F9d0B61c962E9fF8", + "SuperformRouter": "0x51d0a7a59F4e54a273FCbA4Fd4ea9E647e785d95", + "TimelockStateRegistry": "0x1cbf6A3B019dAef506e13bf6A353e3C47Cd8250c", + "WormholeARImplementation": "0x6f1d34A20C0d62A4Fc2eCA0919Fb6fDD73F37428", + "WormholeSRImplementation": "0x63a62c7AF0Ed62C394420dBC7Aa0f803236886aC" +} \ No newline at end of file diff --git a/script/cantina_deployment/43114/Avalanche-latest.json b/script/cantina_deployment/43114/Avalanche-latest.json new file mode 100644 index 000000000..16602521e --- /dev/null +++ b/script/cantina_deployment/43114/Avalanche-latest.json @@ -0,0 +1,25 @@ +{ + "BroadcastRegistry": "0x91A4a6E08401FFC5Cf155d7d6A7234AA0302B160", + "CoreStateRegistry": "0xC525e2EE88E0014F46cb031C33c5148A153108eB", + "DstSwapper": "0x363A6294897577522795c80447f2f2829DCc85c4", + "ERC4626Form": "0x3bfEe78d526063e0207B1a55fD4B284306882247", + "ERC4626KYCDaoForm": "0xd72Ec34384b1ba5bCeC852Fa88420D0f6F90363c", + "ERC4626TimelockForm": "0x87D539863EaB9f3CB99B405929464f6aAb77e81B", + "EmergencyQueue": "0x8Ef837576f37C29BAcd1efb2Eb0ddAadB01DA189", + "HyperlaneImplementation": "0x922d821ddfA8958890d69053CA79a7E619A2790E", + "LayerzeroImplementation": "0x22adbC6BBb1A8C4eFB579268772E7516869E2Cc6", + "LiFiValidator": "0xe1E7b5011E0DcFb823916E8a91DBA9eC383E82C2", + "PayMaster": "0x917455CE06FCD3acFB697781D5E937e1ABcb7694", + "PayloadHelper": "0x3fF04DB7C5D74A544bC76BFabE37732196d56e34", + "PaymentHelper": "0xa4498fa6b5f964a84432Fa007B04255610E21992", + "SocketOneInchValidator": "0xceb161DAC215389B44FE15634A3e207bC886fa09", + "SocketValidator": "0x156889A11Ed41fdAAF3da7394D5cF577bb69eaC4", + "SuperPositions": "0xD240a9674E9a306009071Bd60966F66eA33341Fd", + "SuperRBAC": "0x3487eD8b15c93138573CDC1226CC3ecBb4CD31af", + "SuperRegistry": "0xB0bBFC88896c1a218fbAFab6C8dcf43eD587Ad63", + "SuperformFactory": "0x7791026F1770780c00cEe224F9d0B61c962E9fF8", + "SuperformRouter": "0x51d0a7a59F4e54a273FCbA4Fd4ea9E647e785d95", + "TimelockStateRegistry": "0x1cbf6A3B019dAef506e13bf6A353e3C47Cd8250c", + "WormholeARImplementation": "0x6f1d34A20C0d62A4Fc2eCA0919Fb6fDD73F37428", + "WormholeSRImplementation": "0x63a62c7AF0Ed62C394420dBC7Aa0f803236886aC" +} \ No newline at end of file diff --git a/script/cantina_deployment/56/Binance-latest.json b/script/cantina_deployment/56/Binance-latest.json new file mode 100644 index 000000000..16602521e --- /dev/null +++ b/script/cantina_deployment/56/Binance-latest.json @@ -0,0 +1,25 @@ +{ + "BroadcastRegistry": "0x91A4a6E08401FFC5Cf155d7d6A7234AA0302B160", + "CoreStateRegistry": "0xC525e2EE88E0014F46cb031C33c5148A153108eB", + "DstSwapper": "0x363A6294897577522795c80447f2f2829DCc85c4", + "ERC4626Form": "0x3bfEe78d526063e0207B1a55fD4B284306882247", + "ERC4626KYCDaoForm": "0xd72Ec34384b1ba5bCeC852Fa88420D0f6F90363c", + "ERC4626TimelockForm": "0x87D539863EaB9f3CB99B405929464f6aAb77e81B", + "EmergencyQueue": "0x8Ef837576f37C29BAcd1efb2Eb0ddAadB01DA189", + "HyperlaneImplementation": "0x922d821ddfA8958890d69053CA79a7E619A2790E", + "LayerzeroImplementation": "0x22adbC6BBb1A8C4eFB579268772E7516869E2Cc6", + "LiFiValidator": "0xe1E7b5011E0DcFb823916E8a91DBA9eC383E82C2", + "PayMaster": "0x917455CE06FCD3acFB697781D5E937e1ABcb7694", + "PayloadHelper": "0x3fF04DB7C5D74A544bC76BFabE37732196d56e34", + "PaymentHelper": "0xa4498fa6b5f964a84432Fa007B04255610E21992", + "SocketOneInchValidator": "0xceb161DAC215389B44FE15634A3e207bC886fa09", + "SocketValidator": "0x156889A11Ed41fdAAF3da7394D5cF577bb69eaC4", + "SuperPositions": "0xD240a9674E9a306009071Bd60966F66eA33341Fd", + "SuperRBAC": "0x3487eD8b15c93138573CDC1226CC3ecBb4CD31af", + "SuperRegistry": "0xB0bBFC88896c1a218fbAFab6C8dcf43eD587Ad63", + "SuperformFactory": "0x7791026F1770780c00cEe224F9d0B61c962E9fF8", + "SuperformRouter": "0x51d0a7a59F4e54a273FCbA4Fd4ea9E647e785d95", + "TimelockStateRegistry": "0x1cbf6A3B019dAef506e13bf6A353e3C47Cd8250c", + "WormholeARImplementation": "0x6f1d34A20C0d62A4Fc2eCA0919Fb6fDD73F37428", + "WormholeSRImplementation": "0x63a62c7AF0Ed62C394420dBC7Aa0f803236886aC" +} \ No newline at end of file diff --git a/script/output/100/Gnosis-latest.json b/script/output/100/Gnosis-latest.json deleted file mode 100644 index e96048c46..000000000 --- a/script/output/100/Gnosis-latest.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "BroadcastRegistry": "0xF565376A77c3c03759a999090F652De1B99d66a0", - "CoreStateRegistry": "0x3ddcaad48B0312e1558b481e04E3805bD14c3848", - "DstSwapper": "0x8b5cb412108ecF4d88906f0D251EFab9039e3EAC", - "ERC4626Form": "0xE00Bd2f1CCb8E68426E778E3e4824c27a103DcD3", - "ERC4626KYCDaoForm": "0x5f89C4eB79e7150bE0e4776eD0CdC943b4D70396", - "ERC4626TimelockForm": "0xF17C4DfF77E0304789b13492b6BCc3d9eB1E9F76", - "EmergencyQueue": "0x55621dB794B84A0F26174267de7D2bd8548f0Ebe", - "HyperlaneImplementation": "0x7bDF57585d23e5605ae466Be0ec829A0cF2884A5", - "LayerzeroImplementation": "0x109D47fF9c8BBdD2dC91a7f57FED93b8E5e34277", - "LiFiValidator": "0x918666c51ADC87D13dEd78FA1169D705103F2B12", - "PayMaster": "0x011a925048E52E2F2129F9CA5A1cE75FC597DFf8", - "PayloadHelper": "0x50d8D65aB23fD8e8859f4cAEb7834926d0647994", - "PaymentHelper": "0x019f18235E0dF2064e1AA1B786fD8bFF55B99485", - "SocketOneInchValidator": "0xb74b1549911B8bD3c5c55A38c3b72D5C4F467c16", - "SocketValidator": "0xFe630DD09Ce2e51fE48D68801754Cf822C5F4a45", - "SuperPositions": "0x96206FB919Ef45617cfcf8ED35109FE8431D7B20", - "SuperRBAC": "0xF175De3a338515a192b83624FC5b547072983252", - "SuperRegistry": "0x78aFc74b8cEf314aB2f0EFA6E7743F26c99e5119", - "SuperTransmuter": "0x3cB9E989cBb5BF09195D337De8F56076EFdEC3AD", - "SuperformFactory": "0x40726c201999Db951B430c6A9A054F4a3Cac3ae4", - "SuperformRouter": "0x4d66F472024567BC7Dd7677B4baCd29E10d00CA1", - "TimelockStateRegistry": "0xD23316B549e355303c75fa87EB206aF4011aDC0c", - "WormholeARImplementation": "0x254AB3Fa9246265f8156Bf0c1DdEB0CF5a0Db53E", - "WormholeSRImplementation": "0x540d834BD8388e515A011ad36ec204ac44C0C508" -} \ No newline at end of file diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index c37fe2a3c..5ba384dd0 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -1385,18 +1385,11 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { ) internal view - returns (uint256 msgValue, bytes memory) + returns (uint256 msgValue) { LocalAckVars memory vars; (vars.srcChainId, vars.dstChainId) = abi.decode(chainIds_, (uint64, uint64)); - vars.ambCount = selectedAmbIds.length; - - bytes[] memory paramsPerAMB = new bytes[](vars.ambCount); - paramsPerAMB = _generateExtraData(selectedAmbIds); - - uint256[] memory gasPerAMB = new uint256[](vars.ambCount); - address _paymentHelper = contracts[vars.dstChainId][bytes32(bytes("PaymentHelper"))]; vars.paymentHelper = PaymentHelper(_paymentHelper); @@ -1409,12 +1402,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.message = abi.encode(AMBMessage(2 ** 256 - 1, abi.encode(ReturnSingleData(payloadId, superformId, amount)))); - (vars.totalFees, gasPerAMB) = - vars.paymentHelper.estimateAMBFees(selectedAmbIds, vars.srcChainId, abi.encode(vars.message), paramsPerAMB); - - AMBExtraData memory extraData = AMBExtraData(gasPerAMB, paramsPerAMB); - - return (vars.totalFees, abi.encode(AckAMBData(selectedAmbIds, abi.encode(extraData)))); + (msgValue,) = vars.paymentHelper.calculateAMBData(vars.srcChainId, selectedAmbIds, vars.message); } function _payload(address registry, uint64 chainId, uint256 payloadId_) internal returns (bytes memory payload_) { diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 321d43ba5..743867d07 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -1182,7 +1182,7 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev performs unlock before the time ends for (uint256 j = countTimelocked[i]; j > 0; j--) { - (uint256 nativeFee,) = _generateAckGasFeesAndParamsForTimeLock( + uint256 nativeFee = _generateAckGasFeesAndParamsForTimeLock( abi.encode(CHAIN_0, DST_CHAINS[i]), AMBs, currentUnlockId - j + 1 ); @@ -1200,8 +1200,8 @@ abstract contract ProtocolActions is CommonProtocolActions { uint256 timelockPerformed; /// @dev perform the calls from beginning to last because of easiness in passing unlock id for (uint256 j = countTimelocked[i]; j > 0; j--) { - (uint256 nativeFee,) = _generateAckGasFeesAndParamsForTimeLock( - abi.encode(CHAIN_0, DST_CHAINS[i]), AMBs, currentUnlockId - j + 1 + uint256 nativeFee = _generateAckGasFeesAndParamsForTimeLock( + abi.encode(CHAIN_0, DST_CHAINS[i]), AMBs, currentUnlockId - timelockPerformed ); /// @dev increase time by 5 days From a4f78d0fac29077f174f2e614da99e3668972f47 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 27 Nov 2023 17:55:01 +0000 Subject: [PATCH 004/210] chore: informational setVaultLimitPerTx to setVaultLimitPerDestination --- script/Abstract.Deploy.Single.s.sol | 4 ++-- src/BaseRouterImplementation.sol | 2 +- src/interfaces/ISuperRegistry.sol | 6 +++--- src/settings/SuperRegistry.sol | 6 +++--- test/unit/super-registry/SuperRegistry.t.sol | 10 +++++----- test/unit/superform-router/SuperformRouter.t.sol | 2 +- test/utils/BaseSetup.sol | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index 132ba4580..fb9ea2fa5 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -377,7 +377,7 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setPermit2(CANONICAL_PERMIT2); /// @dev sets max number of vaults per destination - vars.superRegistryC.setVaultLimitPerTx(vars.chainId, 5); + vars.superRegistryC.setVaultLimitPerDestination(vars.chainId, 5); /// @dev 3.1 - deploy Core State Registry vars.coreStateRegistry = address(new CoreStateRegistry{ salt: salt }(vars.superRegistryC)); @@ -806,7 +806,7 @@ abstract contract AbstractDeploySingle is Script { /// @dev FIXME missing attribution of WORMHOLE_VAA_RELAYER_ROLE SuperRegistry(payable(vars.superRegistry)).setRequiredMessagingQuorum(vars.dstChainId, 1); - vars.superRegistryC.setVaultLimitPerTx(vars.dstChainId, 5); + vars.superRegistryC.setVaultLimitPerDestination(vars.dstChainId, 5); /// @dev these values are mocks and has to be replaced /// swap gas cost: 50000 diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 2133b478f..3e6416dc2 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -825,7 +825,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (len != liqRequestsLen) return false; /// @dev deposits beyond max vaults per tx is blocked only for xchain - if (lenSuperforms > superRegistry.getVaultLimitPerTx(dstChainId_)) { + if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { return false; } diff --git a/src/interfaces/ISuperRegistry.sol b/src/interfaces/ISuperRegistry.sol index 41c277d41..a082b05c5 100644 --- a/src/interfaces/ISuperRegistry.sol +++ b/src/interfaces/ISuperRegistry.sol @@ -33,7 +33,7 @@ interface ISuperRegistry { event SetDelay(uint256 oldDelay_, uint256 newDelay_); /// @dev is emitted when a new vault limit is configured - event SetVaultLimitPerTx(uint64 chainId_, uint256 vaultLimit_); + event SetVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // @@ -152,7 +152,7 @@ interface ISuperRegistry { /// @param chainId_ is the id of the remote chain /// @return vaultLimitPerTx_ is the safe number of vaults to deposit /// without hitting out of gas error - function getVaultLimitPerTx(uint64 chainId_) external view returns (uint256 vaultLimitPerTx_); + function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerTx_); /// @dev helps validate if an address is a valid state registry /// @param registryAddress_ is the address of the state registry @@ -184,7 +184,7 @@ interface ISuperRegistry { /// @dev sets the safe vault limit /// @param chainId_ is the remote chain identifier /// @param vaultLimit_ is the max limit of vaults per transaction - function setVaultLimitPerTx(uint64 chainId_, uint256 vaultLimit_) external; + function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external; /// @dev sets a new address on a specific chain. /// @param id_ the identifier of the address on that chain diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 3d770ed23..81c0a58d9 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -170,7 +170,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { } /// @inheritdoc ISuperRegistry - function getVaultLimitPerTx(uint64 chainId_) external view override returns (uint256 vaultLimitPerTx_) { + function getVaultLimitPerDestination(uint64 chainId_) external view override returns (uint256 vaultLimitPerTx_) { vaultLimitPerTx_ = vaultLimitPerTx[chainId_]; } @@ -229,13 +229,13 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { } /// @inheritdoc ISuperRegistry - function setVaultLimitPerTx(uint64 chainId_, uint256 vaultLimit_) external override onlyProtocolAdmin { + function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external override onlyProtocolAdmin { if (vaultLimit_ == 0) { revert Error.ZERO_INPUT_VALUE(); } vaultLimitPerTx[chainId_] = vaultLimit_; - emit SetVaultLimitPerTx(chainId_, vaultLimit_); + emit SetVaultLimitPerDestination(chainId_, vaultLimit_); } /// @inheritdoc ISuperRegistry diff --git a/test/unit/super-registry/SuperRegistry.t.sol b/test/unit/super-registry/SuperRegistry.t.sol index 9e0b65a22..1cd484776 100644 --- a/test/unit/super-registry/SuperRegistry.t.sol +++ b/test/unit/super-registry/SuperRegistry.t.sol @@ -322,18 +322,18 @@ contract SuperRegistryTest is BaseSetup { superRegistry.setStateRegistryAddress(registryId, registryAddress); } - function test_setVaultLimitPerTx() public { + function test_setVaultLimitPerDestination() public { vm.prank(deployer); - superRegistry.setVaultLimitPerTx(1, 100); - assertEq(superRegistry.getVaultLimitPerTx(1), 100); + superRegistry.setVaultLimitPerDestination(1, 100); + assertEq(superRegistry.getVaultLimitPerDestination(1), 100); vm.prank(deployer); vm.expectRevert(Error.ZERO_INPUT_VALUE.selector); - superRegistry.setVaultLimitPerTx(1, 0); + superRegistry.setVaultLimitPerDestination(1, 0); vm.prank(address(420)); vm.expectRevert(Error.NOT_PROTOCOL_ADMIN.selector); - superRegistry.setVaultLimitPerTx(1, 100); + superRegistry.setVaultLimitPerDestination(1, 100); } function test_setRequiredMessagingQuorum_and_revert_invalidCaller() public { diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 98afd6120..02d716b09 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -274,7 +274,7 @@ contract SuperformRouterTest is ProtocolActions { /// @dev approves before call MockERC20(getContract(ETH, "DAI")).approve(router, 1e18); - SuperRegistry(getContract(ETH, "SuperRegistry")).setVaultLimitPerTx(ETH, 1); + SuperRegistry(getContract(ETH, "SuperRegistry")).setVaultLimitPerDestination(ETH, 1); vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectMultiVaultDeposit(req); diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 5ba384dd0..f235ec843 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -709,7 +709,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistry = getContract(vars.chainId, "SuperRegistry"); vars.paymentHelper = getContract(vars.chainId, "PaymentHelper"); vars.superRegistryC = SuperRegistry(payable(vars.superRegistry)); - vars.superRegistryC.setVaultLimitPerTx(vars.chainId, 5); + vars.superRegistryC.setVaultLimitPerDestination(vars.chainId, 5); /// @dev Set all trusted remotes for each chain, configure amb chains ids, setupQuorum for all chains as 1 /// and setup PaymentHelper @@ -765,7 +765,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { ); vars.superRegistryC.setRequiredMessagingQuorum(vars.dstChainId, 1); - vars.superRegistryC.setVaultLimitPerTx(vars.dstChainId, 5); + vars.superRegistryC.setVaultLimitPerDestination(vars.dstChainId, 5); /// swap gas cost: 50000 /// update gas cost: 40000 From 827c924fb9bc386f03a14745f35b0865bfbc4b2d Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 28 Nov 2023 10:20:25 +0000 Subject: [PATCH 005/210] ci: add devnets --- .github/workflows/CI.yml | 23 +++++++++++++++++++++-- utils/run_script_tenderly.sh | 7 +++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1fe1536c1..56ab306d2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,6 +18,7 @@ env: POLYGON_RPC_URL: ${{ secrets.POLYGON_RPC_URL }} AVALANCHE_RPC_URL: ${{ secrets.AVALANCHE_RPC_URL }} FANTOM_RPC_URL: ${{ secrets.FANTOM_RPC_URL }} + TENDERLY_ACCESS_KEY: ${{ secrets.TENDERLY_ACCESS_KEY }} jobs: build: @@ -85,11 +86,10 @@ jobs: - name: "Add test summary" run: | - echo "## Fork tests result" >> $GITHUB_STEP_SUMMARY + echo "## Tests result" >> $GITHUB_STEP_SUMMARY echo "✅ Passed" >> $GITHUB_STEP_SUMMARY coverage: - needs: ["build"] runs-on: SuperformCore2 steps: - name: "Check out the repo" @@ -114,3 +114,22 @@ jobs: run: | echo "## Coverage result" >> $GITHUB_STEP_SUMMARY echo "✅ Uploaded to Codecov" >> $GITHUB_STEP_SUMMARY + + deploy-tenderly-devnets: + runs-on: SuperformCore2 + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + with: + submodules: "recursive" + - name: "Install Foundry" + uses: "foundry-rs/foundry-toolchain@v1" + - name: 'Install Tenderly CLI' + run: curl https://raw.githubusercontent.com/Tenderly/tenderly-cli/master/scripts/install-linux.sh | sudo sh + - name: 'Deploy to Tenderly Devnets' + run: ./utils/run_script_tenderly.sh + shell: bash + - name: "Add devnet deployment summary" + run: | + echo "## Devnet deployment result" >> $GITHUB_STEP_SUMMARY + echo "✅ Deployed to Tenderly Devnet" >> $GITHUB_STEP_SUMMARY diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index 020b2fe22..3da64d788 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -1,9 +1,8 @@ #!/usr/bin/env bash -BSC_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template bscdevnet --account superform --return-url) -POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template polygondevnet --account superform --return-url) -AVAX_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template avaxdevnet --account superform --return-url) -BASE_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d4 --template basedevnet --account superform --return-url) +BSC_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d5 --template bscdevnet --account superform --return-url) +POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d5 --template polygondevnet --account superform --return-url) +BASE_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d5 --template basedevnet --account superform --return-url) # Run the script echo Running Stage 1: ... From 0012147acb1fc803e7d9f5af3b2df8d5a4e13f17 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 28 Nov 2023 12:07:45 +0000 Subject: [PATCH 006/210] ci: adapt tenderly env vars and make salt dynamic --- .env.example | 4 +++- .github/workflows/CI.yml | 2 ++ script/Abstract.Deploy.Single.s.sol | 4 ++-- script/Mainnet.Deploy.NewChain.s.sol | 4 ++-- script/Mainnet.Deploy.s.sol | 5 +++-- utils/run_script_tenderly.sh | 15 +++++++++------ 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/.env.example b/.env.example index 69a945bfc..2f7235afb 100644 --- a/.env.example +++ b/.env.example @@ -23,4 +23,6 @@ MULTI_SIG_ADDRESS= DEPLOYER_KEY= FOUNDRY_EXPORTS_OVERWRITE_LATEST=true RUST_BACKTRACE=full -FOUNDRY_PROFILE=localdev \ No newline at end of file +FOUNDRY_PROFILE=localdev +TENDERLY_PROJECT_SLUG= +TENDERLY_ACCOUNT_ID= \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 56ab306d2..dee9115d4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -19,6 +19,8 @@ env: AVALANCHE_RPC_URL: ${{ secrets.AVALANCHE_RPC_URL }} FANTOM_RPC_URL: ${{ secrets.FANTOM_RPC_URL }} TENDERLY_ACCESS_KEY: ${{ secrets.TENDERLY_ACCESS_KEY }} + TENDERLY_PROJECT_SLUG: 'superform-v1-d5' # your project slug + TENDERLY_ACCOUNT_ID: 'superform' # your username or organization name jobs: build: diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index 132ba4580..4bc87c2b8 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -114,7 +114,6 @@ abstract contract AbstractDeploySingle is Script { "EmergencyQueue" ]; - bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; enum Chains { Ethereum, @@ -332,7 +331,8 @@ abstract contract AbstractDeploySingle is Script { uint256 i, uint256 trueIndex, Cycle cycle, - uint64[] memory targetDeploymentChains + uint64[] memory targetDeploymentChains, + bytes32 salt ) internal setEnvDeploy(cycle) diff --git a/script/Mainnet.Deploy.NewChain.s.sol b/script/Mainnet.Deploy.NewChain.s.sol index bc7cc0c2f..b5c4c83b8 100644 --- a/script/Mainnet.Deploy.NewChain.s.sol +++ b/script/Mainnet.Deploy.NewChain.s.sol @@ -25,7 +25,7 @@ contract MainnetDeployNewChain is AbstractDeploySingle { uint64[] PREVIOUS_DEPLOYMENT = [POLY, AVAX, GNOSIS]; /// @notice The main stage 1 script entrypoint - function deployStage1(uint256 selectedChainIndex) external { + function deployStage1(uint256 selectedChainIndex, uint256 salt) external { _preDeploymentSetup(); uint256 trueIndex; for (uint256 i = 0; i < chainIds.length; i++) { @@ -36,7 +36,7 @@ contract MainnetDeployNewChain is AbstractDeploySingle { } } - _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS); + _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS, keccak256(abi.encode(salt))); } /// @dev stage 2 must be called only after stage 1 is complete for all chains! diff --git a/script/Mainnet.Deploy.s.sol b/script/Mainnet.Deploy.s.sol index da7fab55a..b217b76b0 100644 --- a/script/Mainnet.Deploy.s.sol +++ b/script/Mainnet.Deploy.s.sol @@ -9,9 +9,10 @@ contract MainnetDeploy is AbstractDeploySingle { //////////////////////////////////////////////////////////////*/ uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC, POLY, AVAX]; + ///@dev ORIGINAL SALT bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; /// @notice The main stage 1 script entrypoint - function deployStage1(uint256 selectedChainIndex) external { + function deployStage1(uint256 selectedChainIndex, uint256 salt) external { _preDeploymentSetup(); uint256 trueIndex; for (uint256 i = 0; i < chainIds.length; i++) { @@ -22,7 +23,7 @@ contract MainnetDeploy is AbstractDeploySingle { } } - _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS); + _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS, keccak256(abi.encode(salt))); } /// @dev stage 2 must be called only after stage 1 is complete for all chains! diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index 3da64d788..2d4db10a8 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -1,22 +1,25 @@ #!/usr/bin/env bash -BSC_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d5 --template bscdevnet --account superform --return-url) -POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d5 --template polygondevnet --account superform --return-url) -BASE_DEVNET=$(tenderly devnet spawn-rpc --project superform-v1-d5 --template basedevnet --account superform --return-url) +# Read the RPC URL +source .env + +BSC_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --return-url) +POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --return-url) +BASE_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basedevnet --account $TENDERLY_ACCOUNT_ID --return-url) # Run the script echo Running Stage 1: ... -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 0 1337 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 1 1337 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait From 5d52f86fa37bd637e000a6f39333a1d898321f60 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 28 Nov 2023 12:21:05 +0000 Subject: [PATCH 007/210] ci: fix to run on avax devnet --- utils/run_script_tenderly.sh | 6 +++--- utils/spawn_tenderly_devnets.sh | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index 2d4db10a8..046dcd7d6 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -5,7 +5,7 @@ source .env BSC_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --return-url) POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --return-url) -BASE_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basedevnet --account $TENDERLY_ACCOUNT_ID --return-url) +AVAX_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template avaxdevnet --account $TENDERLY_ACCOUNT_ID --return-url) # Run the script echo Running Stage 1: ... @@ -19,7 +19,7 @@ FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy - wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait @@ -34,7 +34,7 @@ FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy - wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 #echo Running Stage 3: ... diff --git a/utils/spawn_tenderly_devnets.sh b/utils/spawn_tenderly_devnets.sh index f6693ea4b..55ab26728 100644 --- a/utils/spawn_tenderly_devnets.sh +++ b/utils/spawn_tenderly_devnets.sh @@ -4,6 +4,6 @@ source .env -# tenderly devnet spawn-rpc --project superform-v1-d4 --template ethereumdevnet --account superform -tenderly devnet spawn-rpc --project superform-v1-d4 --template avaxdevnet --account superform -tenderly devnet spawn-rpc --project superform-v1-d4 --template gnosisdevnet --account superform +tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID +tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID +tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basedevnet --account $TENDERLY_ACCOUNT_ID \ No newline at end of file From a1794f47337ad45542c89a7bee462503c8dcd449 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 28 Nov 2023 13:05:50 +0000 Subject: [PATCH 008/210] ci: add tenderly access key --- .env.example | 3 ++- script/Mainnet.Deploy.s.sol | 2 +- utils/run_script_tenderly.sh | 10 +++++----- utils/spawn_tenderly_devnets.sh | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 2f7235afb..8c510d408 100644 --- a/.env.example +++ b/.env.example @@ -25,4 +25,5 @@ FOUNDRY_EXPORTS_OVERWRITE_LATEST=true RUST_BACKTRACE=full FOUNDRY_PROFILE=localdev TENDERLY_PROJECT_SLUG= -TENDERLY_ACCOUNT_ID= \ No newline at end of file +TENDERLY_ACCOUNT_ID= +TENDERLY_ACCESS_KEY= \ No newline at end of file diff --git a/script/Mainnet.Deploy.s.sol b/script/Mainnet.Deploy.s.sol index b217b76b0..d868d0a1c 100644 --- a/script/Mainnet.Deploy.s.sol +++ b/script/Mainnet.Deploy.s.sol @@ -8,7 +8,7 @@ contract MainnetDeploy is AbstractDeploySingle { SELECT CHAIN IDS TO DEPLOY HERE //////////////////////////////////////////////////////////////*/ - uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC, POLY, AVAX]; + uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC, POLY, BASE]; ///@dev ORIGINAL SALT bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; /// @notice The main stage 1 script entrypoint diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index 046dcd7d6..36501eecb 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -3,9 +3,9 @@ # Read the RPC URL source .env -BSC_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --return-url) -POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --return-url) -AVAX_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template avaxdevnet --account $TENDERLY_ACCOUNT_ID --return-url) +BSC_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +BASE_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basedevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) # Run the script echo Running Stage 1: ... @@ -19,7 +19,7 @@ FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy - wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait @@ -34,7 +34,7 @@ FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy - wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 #echo Running Stage 3: ... diff --git a/utils/spawn_tenderly_devnets.sh b/utils/spawn_tenderly_devnets.sh index 55ab26728..da4e32c96 100644 --- a/utils/spawn_tenderly_devnets.sh +++ b/utils/spawn_tenderly_devnets.sh @@ -4,6 +4,6 @@ source .env -tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID -tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID -tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basedevnet --account $TENDERLY_ACCOUNT_ID \ No newline at end of file +tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY +tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY +tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basedevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY \ No newline at end of file From 2d182a7d3654a1501e91ea9dcccb8a6646ed4063 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 28 Nov 2023 14:40:02 +0000 Subject: [PATCH 009/210] ci: separate script files --- script/Abstract.Deploy.Single.s.sol | 10 +++-- script/Mainnet.Deploy.NewChain.s.sol | 7 +++- script/Mainnet.Deploy.s.sol | 10 +++-- script/Tenderly.Deploy.s.sol | 57 ++++++++++++++++++++++++++++ utils/run_script_tenderly.sh | 18 ++++----- 5 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 script/Tenderly.Deploy.s.sol diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index 4bc87c2b8..a424ff6cb 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -114,7 +114,6 @@ abstract contract AbstractDeploySingle is Script { "EmergencyQueue" ]; - enum Chains { Ethereum, Polygon, @@ -143,6 +142,7 @@ abstract contract AbstractDeploySingle is Script { uint256 public deployerPrivateKey; address public ownerAddress; + address public burnerPrivateKey; address public multiSigAddress; /// @dev Mapping of chain enum to rpc url @@ -287,9 +287,8 @@ abstract contract AbstractDeploySingle is Script { /// @param cycle deployment cycle (dev, prod) modifier setEnvDeploy(Cycle cycle) { if (cycle == Cycle.Dev) { - deployerPrivateKey = vm.envUint("LOCAL_PRIVATE_KEY"); - ownerAddress = vm.envAddress("LOCAL_OWNER_ADDRESS"); - multiSigAddress = vm.envAddress("MULTI_SIG_ADDRESS"); + (ownerAddress, deployerPrivateKey) = makeAddrAndKey("tenderly"); + //multiSigAddress = vm.envAddress("MULTI_SIG_ADDRESS"); } else { deployerPrivateKey = vm.envUint("DEPLOYER_KEY"); ownerAddress = vm.envAddress("OWNER_ADDRESS"); @@ -608,6 +607,7 @@ abstract contract AbstractDeploySingle is Script { // j = 0 // vars.chainId = targetDeploymentChains[i]; + vm.startBroadcast(deployerPrivateKey); vars.lzImplementation = _readContract(chainNames[trueIndex], vars.chainId, "LayerzeroImplementation"); @@ -662,6 +662,7 @@ abstract contract AbstractDeploySingle is Script { vars.chainId = s_superFormChainIds[i]; vm.startBroadcast(deployerPrivateKey); + SuperRBAC srbac = SuperRBAC(payable(_readContract(chainNames[trueIndex], vars.chainId, "SuperRBAC"))); bytes32 protocolAdminRole = srbac.PROTOCOL_ADMIN_ROLE(); bytes32 emergencyAdminRole = srbac.EMERGENCY_ADMIN_ROLE(); @@ -690,6 +691,7 @@ abstract contract AbstractDeploySingle is Script { SetupVars memory vars; vars.chainId = previousDeploymentChains[i]; + vm.startBroadcast(deployerPrivateKey); vars.lzImplementation = _readContract(chainNames[trueIndex], vars.chainId, "LayerzeroImplementation"); diff --git a/script/Mainnet.Deploy.NewChain.s.sol b/script/Mainnet.Deploy.NewChain.s.sol index b5c4c83b8..537a93edf 100644 --- a/script/Mainnet.Deploy.NewChain.s.sol +++ b/script/Mainnet.Deploy.NewChain.s.sol @@ -24,8 +24,11 @@ contract MainnetDeployNewChain is AbstractDeploySingle { uint64[] FINAL_DEPLOYED_CHAINS = [BSC, POLY, AVAX, GNOSIS]; uint64[] PREVIOUS_DEPLOYMENT = [POLY, AVAX, GNOSIS]; + ///@dev ORIGINAL SALT + bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; + /// @notice The main stage 1 script entrypoint - function deployStage1(uint256 selectedChainIndex, uint256 salt) external { + function deployStage1(uint256 selectedChainIndex) external { _preDeploymentSetup(); uint256 trueIndex; for (uint256 i = 0; i < chainIds.length; i++) { @@ -36,7 +39,7 @@ contract MainnetDeployNewChain is AbstractDeploySingle { } } - _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS, keccak256(abi.encode(salt))); + _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS, salt); } /// @dev stage 2 must be called only after stage 1 is complete for all chains! diff --git a/script/Mainnet.Deploy.s.sol b/script/Mainnet.Deploy.s.sol index d868d0a1c..86a9312cf 100644 --- a/script/Mainnet.Deploy.s.sol +++ b/script/Mainnet.Deploy.s.sol @@ -8,11 +8,13 @@ contract MainnetDeploy is AbstractDeploySingle { SELECT CHAIN IDS TO DEPLOY HERE //////////////////////////////////////////////////////////////*/ - uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC, POLY, BASE]; - ///@dev ORIGINAL SALT bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; + uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC, POLY, AVAX]; + + ///@dev ORIGINAL SALT + bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; /// @notice The main stage 1 script entrypoint - function deployStage1(uint256 selectedChainIndex, uint256 salt) external { + function deployStage1(uint256 selectedChainIndex) external { _preDeploymentSetup(); uint256 trueIndex; for (uint256 i = 0; i < chainIds.length; i++) { @@ -23,7 +25,7 @@ contract MainnetDeploy is AbstractDeploySingle { } } - _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS, keccak256(abi.encode(salt))); + _deployStage1(selectedChainIndex, trueIndex, Cycle.Prod, TARGET_DEPLOYMENT_CHAINS, salt); } /// @dev stage 2 must be called only after stage 1 is complete for all chains! diff --git a/script/Tenderly.Deploy.s.sol b/script/Tenderly.Deploy.s.sol new file mode 100644 index 000000000..feba3fb7b --- /dev/null +++ b/script/Tenderly.Deploy.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.23; + +import { AbstractDeploySingle } from "./Abstract.Deploy.Single.s.sol"; + +contract TenderlyDeploy is AbstractDeploySingle { + /*////////////////////////////////////////////////////////////// + SELECT CHAIN IDS TO DEPLOY HERE + //////////////////////////////////////////////////////////////*/ + + uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC, POLY, BASE]; + + /// @notice The main stage 1 script entrypoint + function deployStage1(uint256 selectedChainIndex, uint256 salt) external { + _preDeploymentSetup(); + uint256 trueIndex; + for (uint256 i = 0; i < chainIds.length; i++) { + if (TARGET_DEPLOYMENT_CHAINS[selectedChainIndex] == chainIds[i]) { + trueIndex = i; + + break; + } + } + + _deployStage1(selectedChainIndex, trueIndex, Cycle.Dev, TARGET_DEPLOYMENT_CHAINS, keccak256(abi.encode(salt))); + } + + /// @dev stage 2 must be called only after stage 1 is complete for all chains! + function deployStage2(uint256 selectedChainIndex) external { + _preDeploymentSetup(); + + uint256 trueIndex; + for (uint256 i = 0; i < chainIds.length; i++) { + if (TARGET_DEPLOYMENT_CHAINS[selectedChainIndex] == chainIds[i]) { + trueIndex = i; + break; + } + } + + _deployStage2(selectedChainIndex, trueIndex, Cycle.Dev, TARGET_DEPLOYMENT_CHAINS, TARGET_DEPLOYMENT_CHAINS); + } + + /// @dev stage 3 must be called only after stage 1 is complete for all chains! + function deployStage3(uint256 selectedChainIndex) external { + _preDeploymentSetup(); + + uint256 trueIndex; + for (uint256 i = 0; i < chainIds.length; i++) { + if (TARGET_DEPLOYMENT_CHAINS[selectedChainIndex] == chainIds[i]) { + trueIndex = i; + break; + } + } + + _deployStage3(selectedChainIndex, trueIndex, Cycle.Dev, TARGET_DEPLOYMENT_CHAINS); + } +} diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index 36501eecb..4fb5d93bf 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -11,42 +11,42 @@ BASE_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --templ echo Running Stage 1: ... -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 0 1337 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 0 1337 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 1 1337 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 1 1337 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait echo Running Stage 2: ... -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 #echo Running Stage 3: ... #wait -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +#FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 #wait -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +#FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 #wait -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +#FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 From 643945781e6b5f28188c2821bc020cd9bf4fc350 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 28 Nov 2023 16:51:43 +0000 Subject: [PATCH 010/210] ci: add overwrite latest --- .github/workflows/CI.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index dee9115d4..8cdb4bfdb 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -21,6 +21,7 @@ env: TENDERLY_ACCESS_KEY: ${{ secrets.TENDERLY_ACCESS_KEY }} TENDERLY_PROJECT_SLUG: 'superform-v1-d5' # your project slug TENDERLY_ACCOUNT_ID: 'superform' # your username or organization name + FOUNDRY_EXPORTS_OVERWRITE_LATEST: 'true' jobs: build: From ee988ba60582a5c16002dd775b630a4c502946b2 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 28 Nov 2023 18:09:39 +0000 Subject: [PATCH 011/210] ci: deploy on different devnets --- script/Tenderly.Deploy.s.sol | 2 +- script/output/1/Ethereum-latest.json | 0 script/output/10/Optimism-latest.json | 0 script/output/250/Fantom-latest.json | 0 script/output/42161/Arbitrum-latest.json | 0 script/output/8453/Base-latest.json | 0 utils/run_script_tenderly.sh | 12 ++++++------ 7 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 script/output/1/Ethereum-latest.json create mode 100644 script/output/10/Optimism-latest.json create mode 100644 script/output/250/Fantom-latest.json create mode 100644 script/output/42161/Arbitrum-latest.json create mode 100644 script/output/8453/Base-latest.json diff --git a/script/Tenderly.Deploy.s.sol b/script/Tenderly.Deploy.s.sol index feba3fb7b..fc76a7b1d 100644 --- a/script/Tenderly.Deploy.s.sol +++ b/script/Tenderly.Deploy.s.sol @@ -8,7 +8,7 @@ contract TenderlyDeploy is AbstractDeploySingle { SELECT CHAIN IDS TO DEPLOY HERE //////////////////////////////////////////////////////////////*/ - uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC, POLY, BASE]; + uint64[] TARGET_DEPLOYMENT_CHAINS = [OP, POLY, ARBI]; /// @notice The main stage 1 script entrypoint function deployStage1(uint256 selectedChainIndex, uint256 salt) external { diff --git a/script/output/1/Ethereum-latest.json b/script/output/1/Ethereum-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/output/10/Optimism-latest.json b/script/output/10/Optimism-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/output/250/Fantom-latest.json b/script/output/250/Fantom-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/output/42161/Arbitrum-latest.json b/script/output/42161/Arbitrum-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/output/8453/Base-latest.json b/script/output/8453/Base-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index 4fb5d93bf..6d5ae74e4 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -3,15 +3,15 @@ # Read the RPC URL source .env -BSC_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +OPTIMISM_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template optimismdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) -BASE_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basedevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +ARBITRUM_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template arbitrumdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) # Run the script echo Running Stage 1: ... -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 0 1337 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 0 1337 --rpc-url $OPTIMISM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait @@ -19,14 +19,14 @@ FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy wait -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 2 1337 --rpc-url $ARBITRUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait echo Running Stage 2: ... -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 0 --rpc-url $OPTIMISM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait @@ -34,7 +34,7 @@ FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy wait -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 2 --rpc-url $ARBITRUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 #echo Running Stage 3: ... From 520d850e3301db1cf26e3aae4125e85c2847cfa2 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:08:32 -0500 Subject: [PATCH 012/210] chore: fix readme typo test --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 85814ec31..9ad374e34 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,6 @@ $ forge test ## Audits -- [Gerard Pearson](https://twitter.com/gpersoon): [2023-09-superform.pdf](https://github.com/superform-xyz/superform-core/files/13300598/2023-09-superform.pdf) +- [Gerard Persoon](https://twitter.com/gpersoon): [2023-09-superform.pdf](https://github.com/superform-xyz/superform-core/files/13300598/2023-09-superform.pdf) - [Hans Friese](https://twitter.com/hansfriese): [Superform_Core_Review_Final_Hans_20230921.pdf](https://github.com/superform-xyz/superform-core/files/13300591/Superform_Core_Review_Final_Hans_20230921.pdf) From d6e59fea7549743dd89b707a98ee1ea003b93b98 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:46:40 -0500 Subject: [PATCH 013/210] chore: DstSwapper updates --- src/crosschain-liquidity/DstSwapper.sol | 25 ++++++++++++++++++------- src/libraries/Error.sol | 6 +++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 6050b1464..50c1c0f40 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -160,7 +160,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { /// @inheritdoc IDstSwapper function batchProcessTx( uint256 payloadId_, - uint256[] calldata indices, + uint256[] calldata indices_, uint8[] calldata bridgeIds_, bytes[] calldata txData_ ) @@ -169,6 +169,10 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { onlySwapper nonReentrant { + if (indices_.length != bridgeIds_.length || bridgeIds_.length != txData_.length) { + revert Error.ARRAY_LENGTH_MISMATCH(); + } + IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); _isValidPayloadId(payloadId_, coreStateRegistry); @@ -178,10 +182,10 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { InitMultiVaultData memory data = abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitMultiVaultData)); - uint256 len = txData_.length; + uint256 len = indices_.length; for (uint256 i; i < len; ++i) { _processTx( - payloadId_, indices[i], bridgeIds_[i], txData_[i], data.liqData[i].interimToken, coreStateRegistry + payloadId_, indices_[i], bridgeIds_[i], txData_[i], data.liqData[i].interimToken, coreStateRegistry ); } } @@ -226,7 +230,10 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { override onlySwapper { - uint256 len = indices_.length; + + if (indices_.length != interimTokens_.length || interimTokens_.length != amounts_.length) { + revert Error.ARRAY_LENGTH_MISMATCH(); + } IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); @@ -237,6 +244,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { InitMultiVaultData memory data = abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitMultiVaultData)); + uint256 len = indices_.length; for (uint256 i; i < len; ++i) { _updateFailedTx( payloadId_, indices_[i], interimTokens_[i], data.liqData[i].interimToken, amounts_[i], coreStateRegistry @@ -348,13 +356,16 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { /// too low) /// @notice this doesn't mean that the keeper or the user can swap any amount, because of the 2nd slippage check /// in CoreStateRegistry - /// @notice in this check, we check if there is negative slippage, for which case, the user is capped to receive - /// the v.expAmount of tokens (originally defined) if (v.balanceDiff < ((v.expAmount * (10_000 - v.maxSlippage)) / 10_000)) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); } - /// @dev updates swapped amount + /// @dev updates swapped amount adjusting for + /// @notice in this check, we check if there is negative slippage, for which case, the user is capped to receive + /// the v.expAmount of tokens (originally defined) + if (v.balanceDiff > v.expAmount) { + v.balanceDiff = v.expAmount; + } swappedAmount[payloadId_][index_] = v.balanceDiff; /// @dev emits final event diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..1f49dbac5 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -7,9 +7,6 @@ library Error { ////////////////////////////////////////////////////////////// ///@notice errors thrown in protocol setup - /// @dev thrown if there is an array length mismatch - error ARRAY_LENGTH_MISMATCH(); - /// @dev thrown if chain id exceeds max(uint64) error BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); @@ -119,6 +116,9 @@ library Error { ///@notice errors thrown if input variables are not valid /// COMMON INPUT VALIDATION ERRORS + /// @dev thrown if there is an array length mismatch + error ARRAY_LENGTH_MISMATCH(); + /// @dev thrown if payload id does not exist error INVALID_PAYLOAD_ID(); From 70dc5350b8c8f1c9a441b54b3dedc5e8eace7372 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 18:32:17 -0500 Subject: [PATCH 014/210] chore: BaseRouter event cleanup + refactor --- src/BaseRouterImplementation.sol | 36 ++++++++++++-------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 2133b478f..bf0e5acce 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -56,7 +56,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou IERC20 token; uint256 txDataLength; uint256 totalAmount; - uint256 approvalAmount; uint256 amountIn; uint8 bridgeId; address permit2; @@ -68,7 +67,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou uint256 totalAmount; uint256 permit2dataLen; uint256 targetLen; - uint256[] approvalAmounts; uint256[] amountsIn; uint8[] bridgeIds; address permit2; @@ -895,18 +893,13 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou v.amountIn = IBridgeValidator(superRegistry.getBridgeValidator(v.bridgeId)).decodeAmountIn( vaultData_.liqData.txData, false ); + } else { + v.amountIn = vaultData_.amount; } if (vaultData_.liqData.token != NATIVE) { v.token = IERC20(vaultData_.liqData.token); - if (v.txDataLength == 0) { - v.approvalAmount = vaultData_.amount; - } else { - v.approvalAmount = v.amountIn; - /// e.g asset in is USDC (6 decimals), we use this amount to approve the transfer to superform - } - if (permit2data_.length != 0) { v.permit2 = _getPermit2(); @@ -918,12 +911,12 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou IPermit2(v.permit2).permitTransferFrom( // The permit message. IPermit2.PermitTransferFrom({ - permitted: IPermit2.TokenPermissions({ token: v.token, amount: v.approvalAmount }), + permitted: IPermit2.TokenPermissions({ token: v.token, amount: v.amountIn}), nonce: nonce, deadline: deadline }), // The transfer recipient and amount. - IPermit2.SignatureTransferDetails({ to: address(this), requestedAmount: v.approvalAmount }), + IPermit2.SignatureTransferDetails({ to: address(this), requestedAmount: v.amountIn }), // The owner of the tokens, which must also be // the signer of the message, otherwise this call // will fail. @@ -933,17 +926,17 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou signature ); } else { - if (v.token.allowance(srcSender_, address(this)) < v.approvalAmount) { + if (v.token.allowance(srcSender_, address(this)) < v.amountIn) { revert Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); } /// @dev moves the tokens from the user to the router - v.token.safeTransferFrom(srcSender_, address(this), v.approvalAmount); + v.token.safeTransferFrom(srcSender_, address(this), v.amountIn); } if (target_ != address(0)) { /// @dev approves the input amount to the target - v.token.safeIncreaseAllowance(target_, v.approvalAmount); + v.token.safeIncreaseAllowance(target_, v.amountIn); } } @@ -975,6 +968,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou v.amountsIn[i] = IBridgeValidator(superRegistry.getBridgeValidator(v.bridgeIds[i])).decodeAmountIn( vaultData_.liqData[i].txData, false ); + } else { + v.amountsIn[i] = vaultData_.amounts[i]; } } @@ -984,7 +979,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou v.totalAmount; v.permit2dataLen = permit2data_.length; - v.approvalAmounts = new uint256[](v.len); for (uint256 i; i < v.len; ++i) { if (vaultData_.liqData[i].token != address(v.token)) { @@ -992,15 +986,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } uint256 txDataLength = vaultData_.liqData[i].txData.length; - if (txDataLength == 0 && !xChain) { - v.approvalAmounts[i] = vaultData_.amounts[i]; - } else if (txDataLength == 0 && xChain) { + if (txDataLength == 0 && xChain) { revert Error.NO_TXDATA_PRESENT(); - } else { - v.approvalAmounts[i] = v.amountsIn[i]; - } + } - v.totalAmount += v.approvalAmounts[i]; + v.totalAmount += v.amountsIn[i]; } if (v.totalAmount == 0) { @@ -1043,7 +1033,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou v.targetLen = targets_.length; for (uint256 j; j < v.targetLen; ++j) { /// @dev approves the superform - v.token.safeIncreaseAllowance(targets_[j], v.approvalAmounts[j]); + v.token.safeIncreaseAllowance(targets_[j], v.amountsIn[j]); } } From 9e870c8da0d4a0a9a922b695ca5b5149091fdb33 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 23:37:55 +0000 Subject: [PATCH 015/210] Add renovate.json --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000..39a2b6e9a --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +} From 5b162723651f2adc56df57ffcdfb59a65be34054 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 19:28:05 -0500 Subject: [PATCH 016/210] chore: validatooors and errors --- src/BaseForm.sol | 9 ++++++--- src/BaseRouterImplementation.sol | 4 ++-- .../adapters/hyperlane/HyperlaneImplementation.sol | 4 ++++ .../adapters/layerzero/LayerzeroImplementation.sol | 9 +++++++-- .../automatic-relayer/WormholeARImplementation.sol | 8 ++++++-- .../specialized-relayer/WormholeSRImplementation.sol | 2 +- src/forms/ERC4626FormImplementation.sol | 8 ++++++-- src/libraries/Error.sol | 11 ++++------- .../adapters/LayerzeroImplementation.t.sol | 2 +- .../ERC4626ImplementationInterfaceNotSupported.sol | 2 +- .../adapters/WormholeSRImplementation.t.sol | 2 +- .../superform-forms/superform-form.ERC4626Form.t.sol | 8 ++++---- test/unit/superform-router/SuperformRouter.t.sol | 4 ++-- 13 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 04683b8d8..05d3d9ecd 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -82,6 +82,10 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ////////////////////////////////////////////////////////////// constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } @@ -158,9 +162,8 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { receive() external payable { } - /// @param superRegistry_ ISuperRegistry address deployed - /// @param vault_ The vault address this form pertains to - /// @dev sets caller as the admin of the contract. + /// @param superRegistry_ ISuperRegistry address deployed + /// @param vault_ The vault address this form pertains to function initialize(address superRegistry_, address vault_, address asset_) external initializer { if (ISuperRegistry(superRegistry_) != superRegistry) revert Error.NOT_SUPER_REGISTRY(); if (vault_ == address(0) || asset_ == address(0)) revert Error.ZERO_ADDRESS(); diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 2133b478f..a80f8362c 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -934,7 +934,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); } else { if (v.token.allowance(srcSender_, address(this)) < v.approvalAmount) { - revert Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); + revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); } /// @dev moves the tokens from the user to the router @@ -1032,7 +1032,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); } else { if (v.token.allowance(srcSender_, address(this)) < v.totalAmount) { - revert Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); + revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); } /// @dev moves the tokens from the user to the router diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index f739ee970..45bc1f946 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -137,6 +137,10 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { { uint32 domain = ambChainId[dstChainId_]; + if (domain == 0) { + revert Error.INVALID_CHAIN_ID(); + } + mailbox.dispatch{ value: msg.value }( domain, _castAddr(authorizedImpl[domain]), message_, _generateHookMetadata(extraData_, srcSender_) ); diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index 8a69db1f3..5b76415b4 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -195,7 +195,12 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio override onlyValidStateRegistry { - _lzSend(ambChainId[dstChainId_], message_, payable(srcSender_), address(0x0), extraData_, msg.value); + uint16 domain = ambChainId[dstChainId_]; + if (domain == 0) { + revert Error.INVALID_CHAIN_ID(); + } + + _lzSend(domain, message_, payable(srcSender_), address(0x0), extraData_, msg.value); } /// @inheritdoc IAmbImplementation @@ -326,7 +331,7 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio { bytes memory trustedRemote = trustedRemoteLookup[dstChainId_]; if (trustedRemote.length == 0) { - revert Error.INVALID_SRC_CHAIN_ID(); + revert Error.INVALID_CHAIN_ID(); } lzEndpoint.send{ value: msgValue_ }( diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 90cf1da5c..2f98f5994 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -139,12 +139,16 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { override onlyValidStateRegistry { - uint16 dstChainId = ambChainId[dstChainId_]; + uint16 domain = ambChainId[dstChainId_]; + + if (domain == 0) { + revert Error.INVALID_CHAIN_ID(); + } (uint256 dstNativeAirdrop, uint256 dstGasLimit) = abi.decode(extraData_, (uint256, uint256)); relayer.sendPayloadToEvm{ value: msg.value }( - dstChainId, authorizedImpl[dstChainId], message_, dstNativeAirdrop, dstGasLimit + domain, authorizedImpl[domain], message_, dstNativeAirdrop, dstGasLimit ); } diff --git a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol index b2203e884..52930d097 100644 --- a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol @@ -191,7 +191,7 @@ contract WormholeSRImplementation is IBroadcastAmbImplementation { } if (wormholeMessage.emitterChainId == wormhole.chainId()) { - revert Error.INVALID_SRC_CHAIN_ID(); + revert Error.INVALID_CHAIN_ID(); } if (fromWormholeFormat(wormholeMessage.emitterAddress) != authorizedImpl[wormholeMessage.emitterChainId]) { diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index e183ac5aa..a8cf07649 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -167,7 +167,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev handles the asset token transfers. if (token.allowance(msg.sender, address(this)) < singleVaultData_.amount) { - revert Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); + revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); } /// @dev transfers input token, which is the same as vault asset, to the form @@ -187,7 +187,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { if (address(token) != NATIVE) { /// @dev checks the allowance before transfer from router if (token.allowance(msg.sender, address(this)) < vars.inputAmount) { - revert Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); + revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); } /// @dev transfers input token, which is different from the vault asset, to the form @@ -255,6 +255,10 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC4626 v = IERC4626(vaultLoc); + if (IERC20(asset).allowance(msg.sender, address(this)) < singleVaultData_.amount) { + revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); + } + /// @dev pulling from sender, to auto-send tokens back in case of failed deposits / reverts IERC20(asset).safeTransferFrom(msg.sender, address(this), singleVaultData_.amount); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..9aa32b533 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -221,7 +221,7 @@ library Error { /// @dev thrown if amb id is not valid leading to an address 0 of the implementation error INVALID_BRIDGE_ID(); - /// @dev thrown if chain id brought in the cross chain message is invalid + /// @dev thrown if chain id involved in xchain message is invalid error INVALID_CHAIN_ID(); /// @dev thrown if payload update amount isn't equal to dst swapper amount @@ -255,15 +255,15 @@ library Error { ///@notice errors thrown due to function execution logic /// COMMON EXECUTION ERRORS - /// @dev thrown if allowance in direct deposit is not correct - error DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); - /// @dev thrown if payload is not unique error DUPLICATE_PAYLOAD(); /// @dev thrown if native tokens fail to be sent to superform contracts error FAILED_TO_SEND_NATIVE(); + /// @dev thrown if allowance is not correct to deposit + error INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); + /// @dev thrown if native amount is not at least equal to the amount in the request error INSUFFICIENT_NATIVE_AMOUNT(); @@ -317,9 +317,6 @@ library Error { /// @dev thrown if update payload function was called on a wrong payload error INVALID_PAYLOAD_UPDATE_REQUEST(); - /// @dev thrown if src chain is blocked from messaging - error INVALID_SRC_CHAIN_ID(); - /// @dev thrown if trying to finalize the payload but the withdraw is still locked error LOCKED(); diff --git a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol index 3f5dc76b5..417612ece 100644 --- a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol @@ -330,7 +330,7 @@ contract LayerzeroImplementationTest is BaseSetup { users[userIndex], chainId, abi.encode(ambMessage), abi.encode(ambExtraData) ); - vm.expectRevert(Error.INVALID_SRC_CHAIN_ID.selector); + vm.expectRevert(Error.INVALID_CHAIN_ID.selector); vm.prank(coreStateRegistry); /// @dev notice the use of chainId, whose trustedRemote is not set layerzeroImplementation.dispatchPayload{ value: 0.1 ether }( diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index a11e5a81a..6a0f5da0d 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -121,7 +121,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li if (address(token) != NATIVE) { /// @dev handles the asset token transfers. if (token.allowance(msg.sender, address(this)) < singleVaultData_.amount) { - revert Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); + revert Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); } /// @dev transfers input token, which is the same as vault asset, to the form diff --git a/test/unit/crosschain-data/adapters/WormholeSRImplementation.t.sol b/test/unit/crosschain-data/adapters/WormholeSRImplementation.t.sol index 4324aec43..8617b260a 100644 --- a/test/unit/crosschain-data/adapters/WormholeSRImplementation.t.sol +++ b/test/unit/crosschain-data/adapters/WormholeSRImplementation.t.sol @@ -163,7 +163,7 @@ contract WormholeSRImplementationTest is BaseSetup { vm.prank(getContract(ETH, "WormholeBroadcastHelper")); - vm.expectRevert(Error.INVALID_SRC_CHAIN_ID.selector); + vm.expectRevert(Error.INVALID_CHAIN_ID.selector); wormholeSRImpl.receiveMessage(""); vm.clearMockedCalls(); diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index e45fc4d20..a08a6d242 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -383,7 +383,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); /// @dev no approval before call - vm.expectRevert(Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE.selector); + vm.expectRevert(Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT.selector); SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); } @@ -424,7 +424,7 @@ contract SuperformERC4626FormTest is ProtocolActions { MockERC20(getContract(ETH, "DAI")).transfer(superform, 3e18); MockERC20(getContract(ETH, "DAI")).approve(superform, 1e18); - vm.expectRevert(Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE.selector); + vm.expectRevert(Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT.selector); SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); } @@ -868,7 +868,7 @@ contract SuperformERC4626FormTest is ProtocolActions { ); /// @dev approves before call MockERC20(getContract(ETH, "DAI")).approve(router, 1e18); - vm.expectRevert(Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE.selector); + vm.expectRevert(Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT.selector); SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); data = SingleVaultSFData( @@ -903,7 +903,7 @@ contract SuperformERC4626FormTest is ProtocolActions { ); req = SingleDirectSingleVaultStateReq(data); MockERC20(getContract(ETH, "DAI")).approve(router, 1e18); - vm.expectRevert(Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE.selector); + vm.expectRevert(Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT.selector); SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); vm.clearMockedCalls(); diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 98afd6120..43cff3153 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -1885,7 +1885,7 @@ contract SuperformRouterTest is ProtocolActions { vm.stopPrank(); } - function test_multiVaultTokenForward_noTxData_withNormalApprove_DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE() public { + function test_multiVaultTokenForward_noTxData_withNormalApprove_INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT() public { MultiVaultDepositVars memory v; /// @dev in this test no tokens would be bridged (no txData) vm.selectFork(FORKS[ETH]); @@ -1980,7 +1980,7 @@ contract SuperformRouterTest is ProtocolActions { v.ambIds = new uint8[](1); v.ambIds[0] = 1; - vm.expectRevert(Error.DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE.selector); + vm.expectRevert(Error.INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT.selector); SuperformRouter(payable(v.superformRouter)).singleXChainMultiVaultDeposit{ value: 2 ether }( SingleXChainMultiVaultStateReq( v.ambIds, From 65b2236f74ef369c591e90c2cc4d7db6ea83ea43 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 19:39:04 -0500 Subject: [PATCH 017/210] chore: SUP-4678, hyperlane 0 checks --- .../adapters/hyperlane/HyperlaneImplementation.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index 45bc1f946..f8a614ca3 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -85,6 +85,7 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { /// @param mailbox_ is the address of hyperlane mailbox /// @param igp_ is the address of hyperlane gas paymaster function setHyperlaneConfig(IMailbox mailbox_, IInterchainGasPaymaster igp_) external onlyProtocolAdmin { + if (address(mailbox_) == address(0)) revert Error.ZERO_ADDRESS(); mailbox = mailbox_; igp = igp_; From d3715211e04ed9ba6b10155b01d33da1135b2013 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 19:52:32 -0500 Subject: [PATCH 018/210] SUP-4691,SUP-4696,SUP-4706 --- src/BaseForm.sol | 6 ++++-- src/settings/SuperRegistry.sol | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 05d3d9ecd..eb32c37fd 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -164,6 +164,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { /// @param superRegistry_ ISuperRegistry address deployed /// @param vault_ The vault address this form pertains to + /// @param asset_ The underlying asset address of the vault this form pertains to function initialize(address superRegistry_, address vault_, address asset_) external initializer { if (ISuperRegistry(superRegistry_) != superRegistry) revert Error.NOT_SUPER_REGISTRY(); if (vault_ == address(0) || asset_ == address(0)) revert Error.ZERO_ADDRESS(); @@ -308,13 +309,14 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { /// @dev returns if a form id is paused function _isPaused(uint256 superformId) internal view returns (bool) { - if (!ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(superformId)) { + address factory = superRegistry.getAddress(keccak256("SUPERFORM_FACTORY")); + if (!ISuperformFactory(factory).isSuperform(superformId)) { revert Error.SUPERFORM_ID_NONEXISTENT(); } (, uint32 formImplementationId_,) = superformId.getSuperform(); - return ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isFormImplementationPaused( + return ISuperformFactory(factory).isFormImplementationPaused( formImplementationId_ ); } diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 3d770ed23..c7516680f 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -230,10 +230,11 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { /// @inheritdoc ISuperRegistry function setVaultLimitPerTx(uint64 chainId_, uint256 vaultLimit_) external override onlyProtocolAdmin { - if (vaultLimit_ == 0) { + + if (chainId_ == 0 || vaultLimit_ == 0) { revert Error.ZERO_INPUT_VALUE(); } - + vaultLimitPerTx[chainId_] = vaultLimit_; emit SetVaultLimitPerTx(chainId_, vaultLimit_); } From 3e14c08b670b3f3501a62ad08546316a1cf62668 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 20:11:13 -0500 Subject: [PATCH 019/210] chore: SUP-4693, slippage naming --- src/crosschain-liquidity/DstSwapper.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 50c1c0f40..3cf335e59 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -27,6 +27,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; + uint256 private constant ENTIRE_SLIPPAGE = 10_000; ////////////////////////////////////////////////////////////// // STATE VARIABLES // @@ -356,7 +357,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { /// too low) /// @notice this doesn't mean that the keeper or the user can swap any amount, because of the 2nd slippage check /// in CoreStateRegistry - if (v.balanceDiff < ((v.expAmount * (10_000 - v.maxSlippage)) / 10_000)) { + if (v.balanceDiff < ((v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) / ENTIRE_SLIPPAGE)) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); } From 2333e8d8e3789c622d387057afa6fce16a6ae97a Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 20:34:20 -0500 Subject: [PATCH 020/210] chore: BridgeValidators + CSR informationals --- src/crosschain-data/extensions/CoreStateRegistry.sol | 4 ++-- src/crosschain-liquidity/lifi/LiFiValidator.sol | 7 ++++--- src/crosschain-liquidity/socket/SocketValidator.sol | 5 ++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 8b5e33daa..1a1d322f0 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -43,7 +43,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { ////////////////////////////////////////////////////////////// /// @dev just stores the superformIds that failed in a specific payload id - mapping(uint256 payloadId => FailedDeposit) internal failedDeposits; + mapping(uint256 payloadId => FailedDeposit) failedDeposits; ////////////////////////////////////////////////////////////// // MODIFIERS // @@ -215,7 +215,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { FailedDeposit storage failedDeposits_ = failedDeposits[payloadId_]; if ( - failedDeposits_.superformIds.length == 0 || proposedAmounts_.length == 0 + failedDeposits_.superformIds.length == 0 || failedDeposits_.superformIds.length != proposedAmounts_.length ) { revert Error.INVALID_RESCUE_DATA(); diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index a306a4f74..492d9d09f 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -133,16 +133,16 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { address, /*receiver*/ uint256 amount, uint256, /*minAmount*/ - uint256, /*destinationChainId*/ + uint256, /*destinationChainId*/0 bool, /*hasSourceSwaps*/ bool /*hasDestinationCall*/ ) { - /// @dev if there isn't a source swap, amountIn is minAmountOut from bridge data? + /// @dev if there isn't a source swap, amount_ is minAmountOut from bridge data amount_ = amount; } catch { if (genericSwapDisallowed_) revert Error.INVALID_ACTION(); - /// @dev in the case of a generic swap, amountIn is the from amount + /// @dev in the case of a generic swap, amount_ is the from amount (, amount_,,,) = extractGenericSwapParameters(txData_); } @@ -153,6 +153,7 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { (token_, amount_,,,) = extractGenericSwapParameters(txData_); } + /// @inheritdoc IBridgeValidator function decodeSwapOutputToken(bytes calldata txData_) external view override returns (address token_) { try this.extractMainParameters(txData_) returns ( string memory, /*bridge*/ diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index d27ae5cc8..5eb4a7ab3 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -91,10 +91,13 @@ contract SocketValidator is BridgeValidator { override returns (address, /*token_*/ uint256 /*amount_*/ ) { - revert(); + /// @dev SocketValidator cannot be used for just swaps, see SocketOneinchValidator + revert Error.CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN(); } + /// @inheritdoc IBridgeValidator function decodeSwapOutputToken(bytes calldata /*txData_*/ ) external pure override returns (address /*token_*/ ) { + /// @dev SocketValidator cannot be used for just swaps, see SocketOneinchValidator revert Error.CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN(); } From 915a24cd95f2bd695373e8643c959488d25380c7 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 20:39:21 -0500 Subject: [PATCH 021/210] chore: bridge comments and csr --- src/crosschain-liquidity/lifi/LiFiValidator.sol | 4 ++-- src/crosschain-liquidity/socket/SocketValidator.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index 492d9d09f..47d8e248a 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -133,7 +133,7 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { address, /*receiver*/ uint256 amount, uint256, /*minAmount*/ - uint256, /*destinationChainId*/0 + uint256, /*destinationChainId*/ bool, /*hasSourceSwaps*/ bool /*hasDestinationCall*/ ) { @@ -153,7 +153,7 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { (token_, amount_,,,) = extractGenericSwapParameters(txData_); } - /// @inheritdoc IBridgeValidator + /// @inheritdoc BridgeValidator function decodeSwapOutputToken(bytes calldata txData_) external view override returns (address token_) { try this.extractMainParameters(txData_) returns ( string memory, /*bridge*/ diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index 5eb4a7ab3..f1cb57125 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -95,7 +95,7 @@ contract SocketValidator is BridgeValidator { revert Error.CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN(); } - /// @inheritdoc IBridgeValidator + /// @inheritdoc BridgeValidator function decodeSwapOutputToken(bytes calldata /*txData_*/ ) external pure override returns (address /*token_*/ ) { /// @dev SocketValidator cannot be used for just swaps, see SocketOneinchValidator revert Error.CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN(); From f13edca949bc8b3d92308e15a217b38702899338 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 21:04:21 -0500 Subject: [PATCH 022/210] chore: payment helper optimizations, comments --- src/SuperformFactory.sol | 4 +- src/libraries/DataLib.sol | 1 - src/payments/PaymentHelper.sol | 130 +++++++++++++++++---------------- 3 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index d38e823ea..5089eee9e 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -24,9 +24,7 @@ contract SuperformFactory is ISuperformFactory { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - uint8 private constant NON_PAUSED = 1; - uint8 private constant PAUSED = 2; - + ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; bytes32 constant SYNC_IMPLEMENTATION_STATUS = keccak256("SYNC_IMPLEMENTATION_STATUS"); diff --git a/src/libraries/DataLib.sol b/src/libraries/DataLib.sol index bfaab9dce..63a82ab9c 100644 --- a/src/libraries/DataLib.sol +++ b/src/libraries/DataLib.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.23; import { Error } from "../libraries/Error.sol"; -/// @dev rationale for "memory-safe" assembly: https://docs.soliditylang.org/en/v0.8.20/assembly.html#memory-safety library DataLib { function packTxInfo( uint8 txType_, diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 9d87ed8d6..a7d95784b 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -251,56 +251,58 @@ contract PaymentHelper is IPaymentHelper { } /// @inheritdoc IPaymentHelper - function estimateSingleXChainMultiVault( - SingleXChainMultiVaultStateReq calldata req_, - bool isDeposit_ - ) - external - view - override - returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) - { - uint256 totalDstGas; - uint256 superformIdsLen = req_.superformsData.superformIds.length; - - /// @dev step 1: estimate amb costs - uint256 ambFees = - _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateMultiVaultMessage(req_.superformsData)); - - srcAmount += ambFees; - - /// @dev step 2: estimate update cost (only for deposit) - if (isDeposit_) totalDstGas += _estimateUpdateCost(req_.dstChainId, superformIdsLen); - - /// @dev step 3: estimate execution costs in dst - /// note: execution cost includes acknowledgement messaging cost - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, superformIdsLen); - - /// @dev step 4: estimation execution cost of acknowledgement - if (isDeposit_) srcAmount += _estimateAckProcessingCost(superformIdsLen); - - /// @dev step 5: estimate liq amount - if (isDeposit_) liqAmount += _estimateLiqAmount(req_.superformsData.liqRequests); +function estimateSingleXChainMultiVault( + SingleXChainMultiVaultStateReq calldata req_, + bool isDeposit_ +) + external + view + override + returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) +{ + uint256 totalDstGas; + uint256 superformIdsLen = req_.superformsData.superformIds.length; + + /// @dev step 1: estimate AMB costs + uint256 ambFees = + _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateMultiVaultMessage(req_.superformsData)); + srcAmount += ambFees; + + /// @dev step 2, 3, 4, 5: process deposit-specific logic + if (isDeposit_) { + + // estimate update cost + totalDstGas += _estimateUpdateCost(req_.dstChainId, superformIdsLen); + + // estimate execution cost of acknowledgement + srcAmount += _estimateAckProcessingCost(superformIdsLen); + + // estimate liquidity amount + liqAmount += _estimateLiqAmount(req_.superformsData.liqRequests); + + // estimate swap fees + totalDstGas += _estimateSwapFees(req_.dstChainId, req_.superformsData.hasDstSwaps); + } - /// @dev step 6: estimate if swap costs are involved - if (isDeposit_) totalDstGas += _estimateSwapFees(req_.dstChainId, req_.superformsData.hasDstSwaps); + /// @dev step 6: estimate execution costs in destination + totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, superformIdsLen); - /// @dev step 7: estimate if timelock form processing costs are involved - if (!isDeposit_) { - for (uint256 i; i < superformIdsLen; ++i) { - (, uint32 formId,) = req_.superformsData.superformIds[i].getSuperform(); - - if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[CHAIN_ID]; - } + /// @dev step 7: process non-deposit logic for timelock form processing costs + if (!isDeposit_) { + for (uint256 i; i < superformIdsLen; ++i) { + (, uint32 formId,) = req_.superformsData.superformIds[i].getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[CHAIN_ID]; } } + } - /// @dev step 8: convert all dst gas estimates to src chain estimate - dstAmount += _convertToNativeFee(req_.dstChainId, totalDstGas); + /// @dev step 8: convert all destination gas estimates to source chain estimate + dstAmount += _convertToNativeFee(req_.dstChainId, totalDstGas); + + totalAmount = srcAmount + dstAmount + liqAmount; +} - totalAmount = srcAmount + dstAmount + liqAmount; - } /// @inheritdoc IPaymentHelper function estimateSingleXChainSingleVault( @@ -313,42 +315,46 @@ contract PaymentHelper is IPaymentHelper { returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) { uint256 totalDstGas; - /// @dev step 1: estimate amb costs + + /// @dev step 1: Estimate AMB costs uint256 ambFees = _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateSingleVaultMessage(req_.superformData)); - srcAmount += ambFees; - /// @dev step 2: estimate update cost (only for deposit) - if (isDeposit_) totalDstGas += _estimateUpdateCost(req_.dstChainId, 1); + /// @dev step 2,3,4,5: Process deposit-specific logic + if (isDeposit_) { - /// @dev step 3: estimate execution costs in dst - /// note: execution cost includes acknowledgement messaging cost - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, 1); + // estimate update cost + totalDstGas += _estimateUpdateCost(req_.dstChainId, 1); - /// @dev step 4: estimation execution cost of acknowledgement - if (isDeposit_) srcAmount += _estimateAckProcessingCost(1); + // estimate execution cost of acknowledgement + srcAmount += _estimateAckProcessingCost(1); - /// @dev step 5: estimate the liq amount - if (isDeposit_) liqAmount += _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); + // estimate the liquidity amount + liqAmount += _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); - /// @dev step 6: estimate if swap costs are involved - if (isDeposit_) { + // estimate swap fees totalDstGas += _estimateSwapFees(req_.dstChainId, req_.superformData.hasDstSwap.castBoolToArray()); } - /// @dev step 7: estimate if timelock form processing costs are involved - (, uint32 formId,) = req_.superformData.superformId.getSuperform(); - if (!isDeposit_ && formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[CHAIN_ID]; + /// @dev step 6: estimate execution costs in destination + totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, 1); + + /// @dev step 7: process non-deposit logic for timelock form processing costs + if (!isDeposit_) { + (, uint32 formId,) = req_.superformData.superformId.getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[CHAIN_ID]; + } } - /// @dev step 8: convert all dst gas estimates to src chain estimate + /// @dev step 8: convert all destination gas estimates to source chain estimate dstAmount += _convertToNativeFee(req_.dstChainId, totalDstGas); totalAmount = srcAmount + dstAmount + liqAmount; } + /// @inheritdoc IPaymentHelper function estimateSingleDirectSingleVault( SingleDirectSingleVaultStateReq calldata req_, From f26ae8fcb4141419cd94d396e5acc0cceb6b578c Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 21:05:52 -0500 Subject: [PATCH 023/210] chore: fix tab --- src/payments/PaymentHelper.sol | 90 +++++++++++++++++----------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index a7d95784b..b797ffda6 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -251,57 +251,57 @@ contract PaymentHelper is IPaymentHelper { } /// @inheritdoc IPaymentHelper -function estimateSingleXChainMultiVault( - SingleXChainMultiVaultStateReq calldata req_, - bool isDeposit_ -) - external - view - override - returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) -{ - uint256 totalDstGas; - uint256 superformIdsLen = req_.superformsData.superformIds.length; - - /// @dev step 1: estimate AMB costs - uint256 ambFees = - _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateMultiVaultMessage(req_.superformsData)); - srcAmount += ambFees; - - /// @dev step 2, 3, 4, 5: process deposit-specific logic - if (isDeposit_) { - - // estimate update cost - totalDstGas += _estimateUpdateCost(req_.dstChainId, superformIdsLen); - - // estimate execution cost of acknowledgement - srcAmount += _estimateAckProcessingCost(superformIdsLen); - - // estimate liquidity amount - liqAmount += _estimateLiqAmount(req_.superformsData.liqRequests); - - // estimate swap fees - totalDstGas += _estimateSwapFees(req_.dstChainId, req_.superformsData.hasDstSwaps); - } + function estimateSingleXChainMultiVault( + SingleXChainMultiVaultStateReq calldata req_, + bool isDeposit_ + ) + external + view + override + returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) + { + uint256 totalDstGas; + uint256 superformIdsLen = req_.superformsData.superformIds.length; - /// @dev step 6: estimate execution costs in destination - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, superformIdsLen); + /// @dev step 1: estimate AMB costs + uint256 ambFees = + _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateMultiVaultMessage(req_.superformsData)); + srcAmount += ambFees; - /// @dev step 7: process non-deposit logic for timelock form processing costs - if (!isDeposit_) { - for (uint256 i; i < superformIdsLen; ++i) { - (, uint32 formId,) = req_.superformsData.superformIds[i].getSuperform(); - if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[CHAIN_ID]; + /// @dev step 2, 3, 4, 5: process deposit-specific logic + if (isDeposit_) { + + // estimate update cost + totalDstGas += _estimateUpdateCost(req_.dstChainId, superformIdsLen); + + // estimate execution cost of acknowledgement + srcAmount += _estimateAckProcessingCost(superformIdsLen); + + // estimate liquidity amount + liqAmount += _estimateLiqAmount(req_.superformsData.liqRequests); + + // estimate swap fees + totalDstGas += _estimateSwapFees(req_.dstChainId, req_.superformsData.hasDstSwaps); + } + + /// @dev step 6: estimate execution costs in destination + totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, superformIdsLen); + + /// @dev step 7: process non-deposit logic for timelock form processing costs + if (!isDeposit_) { + for (uint256 i; i < superformIdsLen; ++i) { + (, uint32 formId,) = req_.superformsData.superformIds[i].getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[CHAIN_ID]; + } } } - } - /// @dev step 8: convert all destination gas estimates to source chain estimate - dstAmount += _convertToNativeFee(req_.dstChainId, totalDstGas); + /// @dev step 8: convert all destination gas estimates to source chain estimate + dstAmount += _convertToNativeFee(req_.dstChainId, totalDstGas); - totalAmount = srcAmount + dstAmount + liqAmount; -} + totalAmount = srcAmount + dstAmount + liqAmount; + } /// @inheritdoc IPaymentHelper From c3202e5ceefcc2e85f4d9246cb8350d7a652e31e Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 11 Dec 2023 21:07:00 -0500 Subject: [PATCH 024/210] chore: cap EE --- src/payments/PaymentHelper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index b797ffda6..9820fc7e1 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -316,7 +316,7 @@ contract PaymentHelper is IPaymentHelper { { uint256 totalDstGas; - /// @dev step 1: Estimate AMB costs + /// @dev step 1: estimate AMB costs uint256 ambFees = _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateSingleVaultMessage(req_.superformData)); srcAmount += ambFees; From 423700905a173dc2b538e3d2e97b93826817ce16 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 09:45:00 +0000 Subject: [PATCH 025/210] Add renovate.json --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000..39a2b6e9a --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +} From 9d9a6622efabb528270335ef22cde5481c8e11fd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 09:50:47 +0000 Subject: [PATCH 026/210] chore(deps): update actions/checkout action to v4 --- .github/workflows/CI.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8cdb4bfdb..a25e66193 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -28,7 +28,7 @@ jobs: runs-on: SuperformCore2 steps: - name: "Check out the repo" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: submodules: "recursive" @@ -63,7 +63,7 @@ jobs: runs-on: SuperformCore2 steps: - name: "Check out the repo" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: submodules: "recursive" @@ -96,7 +96,7 @@ jobs: runs-on: SuperformCore2 steps: - name: "Check out the repo" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: submodules: "recursive" @@ -122,7 +122,7 @@ jobs: runs-on: SuperformCore2 steps: - name: "Check out the repo" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" with: submodules: "recursive" - name: "Install Foundry" From 7f68a92952ae353d0307f9b34b9317e0ee64eb96 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:35:04 +0000 Subject: [PATCH 027/210] fix: receiverAddress in direct withdraws --- .../extensions/TimelockStateRegistry.sol | 7 +++---- src/crosschain-data/utils/PayloadHelper.sol | 8 ++++++-- src/forms/ERC4626Form.sol | 10 +++++----- src/forms/ERC4626FormImplementation.sol | 15 ++++----------- src/forms/ERC4626KYCDaoForm.sol | 2 +- src/forms/ERC4626TimelockForm.sol | 15 +++++++-------- src/interfaces/IPayloadHelper.sol | 2 +- src/interfaces/ITimelockStateRegistry.sol | 2 -- src/types/DataTypes.sol | 1 - test/mocks/ERC4626FormExternal.sol | 10 +++++----- .../extensions/TwoStepsFormStateRegistry.t.sol | 2 -- .../superform-form.ERC4626Timelock.t.sol | 8 ++++---- .../superform-form.forwardDust.t.sol | 2 +- 13 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index ab1caf0af..6267da5ac 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -100,7 +100,6 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree /// @inheritdoc ITimelockStateRegistry function receivePayload( uint8 type_, - address srcSender_, uint64 srcChainId_, uint256 lockedTill_, InitSingleVaultData memory data_ @@ -112,7 +111,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree ++timelockPayloadCounter; timelockPayload[timelockPayloadCounter] = - TimelockPayload(type_, srcSender_, srcChainId_, lockedTill_, data_, TimelockStatus.PENDING); + TimelockPayload(type_, srcChainId_, lockedTill_, data_, TimelockStatus.PENDING); } /// @inheritdoc ITimelockStateRegistry @@ -182,14 +181,14 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree (uint256 payloadId,) = abi.decode(p.data.extraFormData, (uint256, uint256)); _dispatchAcknowledgement( - p.srcChainId, _getDeliveryAMB(payloadId), _constructSingleReturnData(p.srcSender, p.data) + p.srcChainId, _getDeliveryAMB(payloadId), _constructSingleReturnData(p.data.receiverAddress, p.data) ); } /// @dev for direct chain, superPositions are minted directly if (p.isXChain == 0) { ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintSingle( - p.srcSender, p.data.superformId, p.data.amount + p.data.receiverAddress, p.data.superformId, p.data.amount ); } } diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index e233c1d20..1081e5e0e 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -182,7 +182,7 @@ contract PayloadHelper is IPayloadHelper { external view override - returns (address srcSender, uint64 srcChainId, uint256 srcPayloadId, uint256 superformId, uint256 amount) + returns (address receiverAddress, uint64 srcChainId, uint256 srcPayloadId, uint256 superformId, uint256 amount) { ITimelockStateRegistry timelockStateRegistry = ITimelockStateRegistry(superRegistry.getAddress(keccak256("TIMELOCK_STATE_REGISTRY"))); @@ -194,7 +194,11 @@ contract PayloadHelper is IPayloadHelper { TimelockPayload memory payload = timelockStateRegistry.getTimelockPayload(timelockPayloadId_); return ( - payload.srcSender, payload.srcChainId, payload.data.payloadId, payload.data.superformId, payload.data.amount + payload.data.receiverAddress, + payload.srcChainId, + payload.data.payloadId, + payload.data.superformId, + payload.data.amount ); } diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index 1b62df457..ee22074d6 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -39,7 +39,7 @@ contract ERC4626Form is ERC4626FormImplementation { /// @inheritdoc BaseForm function _xChainDepositIntoVault( InitSingleVaultData memory singleVaultData_, - address, + address, /*srcSender_*/ uint64 srcChainId_ ) internal @@ -52,26 +52,26 @@ contract ERC4626Form is ERC4626FormImplementation { /// @inheritdoc BaseForm function _directWithdrawFromVault( InitSingleVaultData memory singleVaultData_, - address srcSender_ + address /*srcSender_*/ ) internal override returns (uint256 dstAmount) { - dstAmount = _processDirectWithdraw(singleVaultData_, srcSender_); + dstAmount = _processDirectWithdraw(singleVaultData_); } /// @inheritdoc BaseForm function _xChainWithdrawFromVault( InitSingleVaultData memory singleVaultData_, - address srcSender_, + address, /*srcSender_*/ uint64 srcChainId_ ) internal override returns (uint256 dstAmount) { - dstAmount = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); + dstAmount = _processXChainWithdraw(singleVaultData_, srcChainId_); } /// @inheritdoc BaseForm diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index e183ac5aa..101e99898 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -272,19 +272,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit Processed(srcChainId_, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); } - function _processDirectWithdraw( - InitSingleVaultData memory singleVaultData_, - address srcSender_ - ) - internal - returns (uint256 dstAmount) - { + function _processDirectWithdraw(InitSingleVaultData memory singleVaultData_) internal returns (uint256 dstAmount) { directWithdrawLocalVars memory v; v.len1 = singleVaultData_.liqData.txData.length; - /// @dev if there is no txData, on withdraws the receiver is the original beneficiary (srcSender_), otherwise it + /// @dev if there is no txData, on withdraws the receiver is receiverAddress, otherwise it /// is this contract (before swap) - v.receiver = v.len1 == 0 ? srcSender_ : address(this); + v.receiver = v.len1 == 0 ? singleVaultData_.receiverAddress : address(this); v.v = IERC4626(vault); v.asset = address(asset); @@ -314,7 +308,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { singleVaultData_.liqData.liqDstChainId, false, address(this), - srcSender_, + singleVaultData_.receiverAddress, singleVaultData_.liqData.token, address(0) ) @@ -332,7 +326,6 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { function _processXChainWithdraw( InitSingleVaultData memory singleVaultData_, - address, /*srcSender_*/ uint64 srcChainId_ ) internal diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index b02c999e1..bc57db6da 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -76,7 +76,7 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { onlyKYC(srcSender_) returns (uint256 dstAmount) { - dstAmount = _processDirectWithdraw(singleVaultData_, srcSender_); + dstAmount = _processDirectWithdraw(singleVaultData_); } /// @inheritdoc BaseForm diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 6f1e3e852..0ae2bfcd0 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -68,7 +68,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { { if (_isPaused(p_.data.superformId)) { IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( - p_.data, p_.srcSender + p_.data, p_.data.receiverAddress ); return 0; } @@ -145,7 +145,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @inheritdoc BaseForm function _xChainDepositIntoVault( InitSingleVaultData memory singleVaultData_, - address, + address, /*srcSender_*/ uint64 srcChainId_ ) internal @@ -162,7 +162,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @return dstAmount is always 0 function _directWithdrawFromVault( InitSingleVaultData memory singleVaultData_, - address srcSender_ + address /*srcSender_*/ ) internal virtual @@ -171,7 +171,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { { /// @dev after requesting the unlock, the information with the time of full unlock is saved and sent to timelock /// @dev state registry for re-processing at a later date - _storePayload(0, srcSender_, CHAIN_ID, _requestUnlock(singleVaultData_.amount), singleVaultData_); + _storePayload(0, CHAIN_ID, _requestUnlock(singleVaultData_.amount), singleVaultData_); return 0; } @@ -182,7 +182,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @return dstAmount is always 0 function _xChainWithdrawFromVault( InitSingleVaultData memory singleVaultData_, - address srcSender_, + address, /*srcSender_*/ uint64 srcChainId_ ) internal @@ -192,7 +192,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { { /// @dev after requesting the unlock, the information with the time of full unlock is saved and sent to timelock /// @dev state registry for re-processing at a later date - _storePayload(1, srcSender_, srcChainId_, _requestUnlock(singleVaultData_.amount), singleVaultData_); + _storePayload(1, srcChainId_, _requestUnlock(singleVaultData_.amount), singleVaultData_); return 0; } @@ -219,7 +219,6 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @dev stores the withdrawal payload function _storePayload( uint8 type_, - address srcSender_, uint64 srcChainId_, uint256 lockedTill_, InitSingleVaultData memory data_ @@ -227,7 +226,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { internal { ITimelockStateRegistry(superRegistry.getAddress(keccak256("TIMELOCK_STATE_REGISTRY"))).receivePayload( - type_, srcSender_, srcChainId_, lockedTill_, data_ + type_, srcChainId_, lockedTill_, data_ ); } } diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index 0f99b4a83..61d88f2d5 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -77,7 +77,7 @@ interface IPayloadHelper { function decodeTimeLockPayload(uint256 timelockPayloadId_) external view - returns (address srcSender, uint64 srcChainId, uint256 srcPayloadId, uint256 superformId, uint256 amount); + returns (address receiverAddress, uint64 srcChainId, uint256 srcPayloadId, uint256 superformId, uint256 amount); /// @dev returns decoded failed timelock form payloads /// @param timelockPayloadId_ is the unique identifier of payload in timelock state registry diff --git a/src/interfaces/ITimelockStateRegistry.sol b/src/interfaces/ITimelockStateRegistry.sol index a9c9aac2f..77d16df71 100644 --- a/src/interfaces/ITimelockStateRegistry.sol +++ b/src/interfaces/ITimelockStateRegistry.sol @@ -25,13 +25,11 @@ interface ITimelockStateRegistry { /// @notice Receives request (payload) from timelock form to process later /// @param type_ is the nature of transaction (xChain: 1 or same chain: 0) - /// @param srcSender_ is the address of the source chain caller /// @param srcChainId_ is the chainId of the source chain /// @param lockedTill_ is the deadline for timelock (after which we can call `finalizePayload`) /// @param data_ is the basic information of superformId, amount to withdraw of type InitSingleVaultData function receivePayload( uint8 type_, - address srcSender_, uint64 srcChainId_, uint256 lockedTill_, InitSingleVaultData memory data_ diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index a17e749fb..dc7f3ddb5 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -153,7 +153,6 @@ enum TimelockStatus { /// @dev holds information about the timelock payload struct TimelockPayload { uint8 isXChain; - address srcSender; uint64 srcChainId; uint256 lockedTill; InitSingleVaultData data; diff --git a/test/mocks/ERC4626FormExternal.sol b/test/mocks/ERC4626FormExternal.sol index b5f5495bf..3e3aab68d 100644 --- a/test/mocks/ERC4626FormExternal.sol +++ b/test/mocks/ERC4626FormExternal.sol @@ -32,19 +32,19 @@ contract ERC4626FormExternal is ERC4626FormImplementation { /// @inheritdoc BaseForm function _directWithdrawFromVault( InitSingleVaultData memory singleVaultData_, - address srcSender_ + address /*srcSender_*/ ) internal override returns (uint256 dstAmount) { - dstAmount = _processDirectWithdraw(singleVaultData_, srcSender_); + dstAmount = _processDirectWithdraw(singleVaultData_); } /// @inheritdoc BaseForm function _xChainDepositIntoVault( InitSingleVaultData memory singleVaultData_, - address, + address, /*srcSender_*/ uint64 srcChainId_ ) internal @@ -57,14 +57,14 @@ contract ERC4626FormExternal is ERC4626FormImplementation { /// @inheritdoc BaseForm function _xChainWithdrawFromVault( InitSingleVaultData memory singleVaultData_, - address srcSender_, + address, /*srcSender_*/ uint64 srcChainId_ ) internal override returns (uint256 dstAmount) { - dstAmount = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); + dstAmount = _processXChainWithdraw(singleVaultData_, srcChainId_); } /// @inheritdoc BaseForm diff --git a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol index 3ebc1bfeb..411d95c1c 100644 --- a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol @@ -54,7 +54,6 @@ contract TimelockStateRegistryTest is ProtocolActions { vm.prank(superform); timelockStateRegistry.receivePayload( 0, - deployer, ETH, block.timestamp - 5 seconds, InitSingleVaultData( @@ -88,7 +87,6 @@ contract TimelockStateRegistryTest is ProtocolActions { vm.prank(superform); timelockStateRegistry.receivePayload( 0, - deployer, ETH, block.timestamp - 5 seconds, InitSingleVaultData( diff --git a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol index 6ff33dad9..6f6d9323b 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol @@ -55,7 +55,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { vm.prank(getContract(ETH, "TimelockStateRegistry")); vm.expectRevert(Error.WITHDRAW_TX_DATA_NOT_UPDATED.selector); ERC4626TimelockForm(payable(superform)).withdrawAfterCoolDown( - TimelockPayload(1, deployer, ETH, block.timestamp, data, TimelockStatus.PENDING) + TimelockPayload(1, ETH, block.timestamp, data, TimelockStatus.PENDING) ); } @@ -96,7 +96,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { vm.prank(getContract(ETH, "TimelockStateRegistry")); vm.expectRevert(Error.WITHDRAW_TOKEN_NOT_UPDATED.selector); ERC4626TimelockForm(payable(superform)).withdrawAfterCoolDown( - TimelockPayload(1, deployer, ETH, block.timestamp, data, TimelockStatus.PENDING) + TimelockPayload(1, ETH, block.timestamp, data, TimelockStatus.PENDING) ); } @@ -133,7 +133,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { vm.prank(getContract(ETH, "TimelockStateRegistry")); ERC4626TimelockForm(payable(superform)).withdrawAfterCoolDown( - TimelockPayload(1, deployer, ETH, block.timestamp, data, TimelockStatus.PENDING) + TimelockPayload(1, ETH, block.timestamp, data, TimelockStatus.PENDING) ); } @@ -194,7 +194,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { vm.expectRevert(Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST.selector); vm.prank(getContract(ETH, "TimelockStateRegistry")); ERC4626TimelockForm(payable(superform)).withdrawAfterCoolDown( - TimelockPayload(1, deployer, ETH, block.timestamp, data, TimelockStatus.PENDING) + TimelockPayload(1, ETH, block.timestamp, data, TimelockStatus.PENDING) ); } diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index 56f244f18..c29e58470 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -145,7 +145,7 @@ contract ForwardDustFormTest is ProtocolActions { } else { vm.prank(getContract(ARBI, "TimelockStateRegistry")); IERC4626TimelockForm(superform).withdrawAfterCoolDown( - TimelockPayload(1, user, ETH, block.timestamp, data2, TimelockStatus.PENDING) + TimelockPayload(1, ETH, block.timestamp, data2, TimelockStatus.PENDING) ); } } From 58d9e9d44b711be8df28e88047904b6a5100764a Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:13:36 +0000 Subject: [PATCH 028/210] chore: change uri --- script/Abstract.Deploy.Single.s.sol | 2 +- test/utils/BaseSetup.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index afeb349c7..fab9a7266 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -499,7 +499,7 @@ abstract contract AbstractDeploySingle is Script { /// @dev 11 - Deploy SuperPositions vars.superPositions = - address(new SuperPositions{ salt: salt }("https://apiv2-dev.superform.xyz/", vars.superRegistry)); + address(new SuperPositions{ salt: salt }("https://ipfs-gateway.superform.xyz/ipns/k51qzi5uqu5dj8wup5t6yyj55o8rj4dx98g931fczrzcagp26hstv7ba7shfmc/Animations/", vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperPositions"))] = vars.superPositions; vars.superRegistryC.setAddress(vars.superRegistryC.SUPER_POSITIONS(), vars.superPositions, vars.chainId); diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index f235ec843..c7ab344e7 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -643,7 +643,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { /// @dev 13 - Deploy SuperPositions vars.superPositions = - address(new SuperPositions{ salt: salt }("https://apiv2-dev.superform.xyz/", vars.superRegistry)); + address(new SuperPositions{ salt: salt }("https://ipfs-gateway.superform.xyz/ipns/k51qzi5uqu5dj8wup5t6yyj55o8rj4dx98g931fczrzcagp26hstv7ba7shfmc/Animations/", vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperPositions"))] = vars.superPositions; vars.superRegistryC.setAddress(vars.superRegistryC.SUPER_POSITIONS(), vars.superPositions, vars.chainId); From 98366c049c41fa56fe3cca3fb1748980a33e2546 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:16:59 +0000 Subject: [PATCH 029/210] fix: sup-4669 sup-4668 --- src/BaseRouterImplementation.sol | 6 +++++ src/SuperformFactory.sol | 2 ++ src/libraries/Error.sol | 3 +++ .../01.024.08.TokenInputSlippageAMB12.sol | 12 ++++----- ....024.08.TokenInputSlippageAMB12.NewDst.sol | 12 ++++----- .../840.024.08.TokenInputSlippageAMB12.sol | 12 ++++----- .../840.024.08.TokenInputSlippageAMB13.sol | 12 ++++----- ...Direct.02.NativeInput.NoSlippage.AMB12.sol | 4 +-- ...erform-factory.changeFormPauseStatus.t.sol | 26 ++++++++++++++++--- 9 files changed, 60 insertions(+), 29 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 3e6416dc2..357951069 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -824,6 +824,12 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (len == 0 || liqRequestsLen == 0) return false; if (len != liqRequestsLen) return false; + /// @dev Additional length checks for hasDstSwaps and retain4626s + if (lenSuperforms != superformsData_.hasDstSwaps.length || lenSuperforms != superformsData_.retain4626s.length) + { + return false; + } + /// @dev deposits beyond max vaults per tx is blocked only for xchain if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { return false; diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index d38e823ea..4322b36de 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -258,6 +258,8 @@ contract SuperformFactory is ISuperformFactory { ); _broadcast(abi.encode(factoryPayload), extraData_); + } else if (msg.value != 0) { + revert Error.MSG_VALUE_NOT_ZERO(); } emit FormImplementationPaused(formImplementationId_, status_); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..2314068fa 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -249,6 +249,9 @@ library Error { /// @dev thrown if src tx types mismatch in state sync error SRC_TX_TYPE_MISMATCH(); + /// @dev error thrown when msg value should be zero in certain payable functions + error MSG_VALUE_NOT_ZERO(); + ////////////////////////////////////////////////////////////// // EXECUTION ERRORS // ////////////////////////////////////////////////////////////// diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/01.024.08.TokenInputSlippageAMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/01.024.08.TokenInputSlippageAMB12.sol index 149b7021a..b8aee88e8 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/01.024.08.TokenInputSlippageAMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/01.024.08.TokenInputSlippageAMB12.sol @@ -69,14 +69,14 @@ contract MDMVW0102408NativeInputSlippageAMB12 is ProtocolActions { LIQ_BRIDGES[AVAX][0] = [1, 1, 1, 1]; LIQ_BRIDGES[AVAX][1] = [1, 1, 1, 1]; - RECEIVE_4626[ETH][0] = [false, false, false, false]; - RECEIVE_4626[ETH][1] = [false, false, false, false]; + RECEIVE_4626[ETH][0] = [false, false]; + RECEIVE_4626[ETH][1] = [false, false]; - RECEIVE_4626[POLY][0] = [false, false, false, false]; - RECEIVE_4626[POLY][1] = [false, false, false, false]; + RECEIVE_4626[POLY][0] = [false, false, false]; + RECEIVE_4626[POLY][1] = [false, false, false]; - RECEIVE_4626[AVAX][0] = [false, false, false, false]; - RECEIVE_4626[AVAX][1] = [false, false, false, false]; + RECEIVE_4626[AVAX][0] = [false, false]; + RECEIVE_4626[AVAX][1] = [false, false]; FINAL_LIQ_DST_WITHDRAW[ETH] = [ETH, ETH, ETH, ETH]; FINAL_LIQ_DST_WITHDRAW[POLY] = [ETH, ETH, ETH, ETH]; diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.NewDst.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.NewDst.sol index ee4376b3b..e52fbfb8f 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.NewDst.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.NewDst.sol @@ -61,14 +61,14 @@ contract MDMVW84002408NativeInputSlipageAMB12NewDst is ProtocolActions { LIQ_BRIDGES[AVAX][0] = [1, 1, 1, 1]; LIQ_BRIDGES[AVAX][1] = [1, 1, 1, 1]; - RECEIVE_4626[ETH][0] = [false, false, false, false]; - RECEIVE_4626[ETH][1] = [false, false, false, false]; + RECEIVE_4626[ETH][0] = [false, false, false]; + RECEIVE_4626[ETH][1] = [false, false, false]; - RECEIVE_4626[POLY][0] = [false, false, false, false]; - RECEIVE_4626[POLY][1] = [false, false, false, false]; + RECEIVE_4626[POLY][0] = [false, false, false]; + RECEIVE_4626[POLY][1] = [false, false, false]; - RECEIVE_4626[AVAX][0] = [false, false, false, false]; - RECEIVE_4626[AVAX][1] = [false, false, false, false]; + RECEIVE_4626[AVAX][0] = [false, false]; + RECEIVE_4626[AVAX][1] = [false, false]; FINAL_LIQ_DST_WITHDRAW[ETH] = [ETH, ARBI, OP, POLY]; FINAL_LIQ_DST_WITHDRAW[POLY] = [POLY, ETH, ETH, ETH]; diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.sol index a9c0cfc45..b4862579a 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB12.sol @@ -69,14 +69,14 @@ contract MDMVW84002408NativeInputSlipageAMB12ABA is ProtocolActions { LIQ_BRIDGES[AVAX][0] = [1, 1, 1, 1]; LIQ_BRIDGES[AVAX][1] = [1, 1, 1, 1]; - RECEIVE_4626[ETH][0] = [false, false, false, false]; - RECEIVE_4626[ETH][1] = [false, false, false, false]; + RECEIVE_4626[ETH][0] = [false, false, false]; + RECEIVE_4626[ETH][1] = [false, false, false]; - RECEIVE_4626[POLY][0] = [false, false, false, false]; - RECEIVE_4626[POLY][1] = [false, false, false, false]; + RECEIVE_4626[POLY][0] = [false, false, false]; + RECEIVE_4626[POLY][1] = [false, false, false]; - RECEIVE_4626[AVAX][0] = [false, false, false, false]; - RECEIVE_4626[AVAX][1] = [false, false, false, false]; + RECEIVE_4626[AVAX][0] = [false, false]; + RECEIVE_4626[AVAX][1] = [false, false]; FINAL_LIQ_DST_WITHDRAW[ETH] = [ETH, ETH, ETH, ETH]; FINAL_LIQ_DST_WITHDRAW[POLY] = [ETH, ETH, ETH, ETH]; diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB13.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB13.sol index 6ec18e7c4..b398f8b70 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB13.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/840.024.08.TokenInputSlippageAMB13.sol @@ -78,14 +78,14 @@ contract MDMVW84002408NativeInputSlipageAMB14 is ProtocolActions { LIQ_BRIDGES[AVAX][0] = [1, 1, 1, 1]; LIQ_BRIDGES[AVAX][1] = [1, 1, 1, 1]; - RECEIVE_4626[ETH][0] = [false, false, false, false]; - RECEIVE_4626[ETH][1] = [false, false, false, false]; + RECEIVE_4626[ETH][0] = [false, false, false]; + RECEIVE_4626[ETH][1] = [false, false, false]; - RECEIVE_4626[POLY][0] = [false, false, false, false]; - RECEIVE_4626[POLY][1] = [false, false, false, false]; + RECEIVE_4626[POLY][0] = [false, false, false]; + RECEIVE_4626[POLY][1] = [false, false, false]; - RECEIVE_4626[AVAX][0] = [false, false, false, false]; - RECEIVE_4626[AVAX][1] = [false, false, false, false]; + RECEIVE_4626[AVAX][0] = [false, false]; + RECEIVE_4626[AVAX][1] = [false, false]; FINAL_LIQ_DST_WITHDRAW[ETH] = [ETH, ETH, ETH, ETH]; FINAL_LIQ_DST_WITHDRAW[POLY] = [ETH, ETH, ETH, ETH]; diff --git a/test/fuzz/scenarios/scenarios-withdraw-singleDirectMultiVaultWithdraw/Direct.02.NativeInput.NoSlippage.AMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-singleDirectMultiVaultWithdraw/Direct.02.NativeInput.NoSlippage.AMB12.sol index 37d4ff32c..04281159d 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-singleDirectMultiVaultWithdraw/Direct.02.NativeInput.NoSlippage.AMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-singleDirectMultiVaultWithdraw/Direct.02.NativeInput.NoSlippage.AMB12.sol @@ -34,8 +34,8 @@ contract SDiMVW02NativeInputNoSlippageAMB12 is ProtocolActions { LIQ_BRIDGES[OP][0] = [1, 1, 3]; LIQ_BRIDGES[OP][1] = [1, 3, 1]; - RECEIVE_4626[OP][0] = [false, false, false]; - RECEIVE_4626[OP][1] = [false, false, false]; + RECEIVE_4626[OP][0] = [false, false]; + RECEIVE_4626[OP][1] = [false, false]; FINAL_LIQ_DST_WITHDRAW[OP] = [OP, OP, OP]; diff --git a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol index e2a870e59..9eb6a0e9d 100644 --- a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol +++ b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol @@ -58,9 +58,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { formImplementation1, formImplementationId ); - SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus{ - value: 800 * 10 ** 18 - }(formImplementationId, ISuperformFactory.PauseStatus.PAUSED, ""); + SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus(formImplementationId, ISuperformFactory.PauseStatus.PAUSED, ""); bool status = SuperformFactory(payable(getContract(chainId, "SuperformFactory"))).isFormImplementationPaused( formImplementationId @@ -92,4 +90,26 @@ contract SuperformFactoryChangePauseTest is BaseSetup { value: 800 * 10 ** 18 }(formImplementationId_invalid, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(5, 2)); } + + function test_changeFormImplementationPauseZeroMsgValueNotSent() public { + vm.startPrank(deployer); + + vm.selectFork(FORKS[chainId]); + + address superRegistry = getContract(chainId, "SuperRegistry"); + + /// @dev Deploying Forms + address formImplementation1 = address(new ERC4626Form(superRegistry)); + uint32 formImplementationId = 0; + + // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested + SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( + formImplementation1, formImplementationId + ); + + vm.expectRevert(Error.MSG_VALUE_NOT_ZERO.selector); + SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus{ + value: 800 * 10 ** 18 + }(formImplementationId, ISuperformFactory.PauseStatus.PAUSED, ""); + } } From 594b7f289451876f63196270f4995838014bc93b Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 12 Dec 2023 19:04:38 -0500 Subject: [PATCH 030/210] fix: SUP-4734 --- src/settings/SuperRegistry.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 3d770ed23..4ebbcea70 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -343,6 +343,11 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { /// @inheritdoc QuorumManager function setRequiredMessagingQuorum(uint64 srcChainId_, uint256 quorum_) external override onlyProtocolAdmin { + + if (srcChainId_ == 0) { + revert Error.INVALID_CHAIN_ID(); + } + requiredQuorum[srcChainId_] = quorum_; emit QuorumSet(srcChainId_, quorum_); From 271c805038770c644850313fa730f4af7f2dab22 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 12 Dec 2023 19:06:38 -0500 Subject: [PATCH 031/210] fix: SUP-4738 --- .../adapters/layerzero/LayerzeroImplementation.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index 8a69db1f3..a4ae5b0a2 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -156,6 +156,9 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio ////////////////////////////////////////////////////////////// function isTrustedRemote(uint16 srcChainId_, bytes calldata srcAddress_) external view returns (bool) { + if (srcChainId_ == 0) { + revert Error.INVALID_CHAIN_ID(); + } return keccak256(trustedRemoteLookup[srcChainId_]) == keccak256(srcAddress_); } From e250fc9022eda8dc773ba4dfc1ec9f4ec7d567a4 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 12 Dec 2023 19:11:44 -0500 Subject: [PATCH 032/210] fix: SUP-4739 --- src/settings/SuperRegistry.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 4ebbcea70..b9a0553db 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -276,6 +276,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { address bridgeAddress = bridgeAddress_[i]; address bridgeValidatorT = bridgeValidator_[i]; if (bridgeAddress == address(0)) revert Error.ZERO_ADDRESS(); + if (bridgeId == 0) revert Error.ZERO_INPUT_VALUE(); if (bridgeValidatorT == address(0)) revert Error.ZERO_ADDRESS(); if (bridgeAddresses[bridgeId] != address(0)) revert Error.DISABLED(); @@ -306,6 +307,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { bool broadcastAMB = isBroadcastAMB_[i]; if (ambAddress == address(0)) revert Error.ZERO_ADDRESS(); + if (ambId == 0) revert Error.ZERO_INPUT_VALUE(); if (ambAddresses[ambId] != address(0) || ambIds[ambAddress] != 0) revert Error.DISABLED(); ambAddresses[ambId] = ambAddress; @@ -331,6 +333,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { address registryAddress = registryAddress_[i]; uint8 registryId = registryId_[i]; if (registryAddress == address(0)) revert Error.ZERO_ADDRESS(); + if (registryId == 0) revert Error.ZERO_INPUT_VALUE();(); if (registryAddresses[registryId] != address(0) || stateRegistryIds[registryAddress] != 0) { revert Error.DISABLED(); } From 0d19833ec79c9bbfe875d44ae3b560e22621be5d Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 12 Dec 2023 19:13:54 -0500 Subject: [PATCH 033/210] fix: SUP-4743 --- src/SuperformFactory.sol | 16 ---------------- src/interfaces/ISuperformFactory.sol | 5 ----- .../superform-factory.createSuperforms.t.sol | 13 ------------- 3 files changed, 34 deletions(-) diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index d38e823ea..9e35c361f 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -147,22 +147,6 @@ contract SuperformFactory is ISuperformFactory { } } - /// @inheritdoc ISuperformFactory - function getAllSuperforms() - external - view - override - returns (uint256[] memory superformIds_, address[] memory superforms_) - { - superformIds_ = superforms; - uint256 len = superformIds_.length; - superforms_ = new address[](len); - - for (uint256 i; i < len; ++i) { - (superforms_[i],,) = superformIds_[i].getSuperform(); - } - } - ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ISuperformFactory.sol b/src/interfaces/ISuperformFactory.sol index aa0479c9f..661463178 100644 --- a/src/interfaces/ISuperformFactory.sol +++ b/src/interfaces/ISuperformFactory.sol @@ -87,11 +87,6 @@ interface ISuperformFactory { view returns (uint256[] memory superformIds_, address[] memory superforms_); - /// @dev Returns all Superforms - /// @return superformIds_ is the id of the superform - /// @return vaults_ is the address of the vault - function getAllSuperforms() external view returns (uint256[] memory superformIds_, address[] memory vaults_); - ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol index 4b86f8511..01882b313 100644 --- a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol +++ b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol @@ -61,12 +61,6 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { vm.selectFork(FORKS[chainId]); - /// @dev testing the getAllSuperforms function - (vars.superformIds_, vars.superforms_) = - SuperformFactory(getContract(chainId, "SuperformFactory")).getAllSuperforms(); - - assertEq(vars.superformIds_.length, vars.superforms_.length); - /// @dev Testing Coss Chain Superform Deployments vars.transformedChainIds_ = new uint256[](vars.chainIds_.length); @@ -106,13 +100,6 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { (uint256 superformIdCreated, address superformCreated) = SuperformFactory(getContract(chainId, "SuperformFactory")).createSuperform(formImplementationId, vault); - (uint256[] memory superformIds_, address[] memory superforms_) = - SuperformFactory(getContract(chainId, "SuperformFactory")).getAllSuperformsFromVault(vault); - - assertEq(superformIdCreated, superformIds_[superformIds_.length - 1]); - - assertEq(superformCreated, superforms_[superforms_.length - 1]); - uint256 totalSuperformsAfter = SuperformFactory(getContract(chainId, "SuperformFactory")).getSuperformCount(); assertEq(totalSuperformsAfter, totalSuperformsBefore + 1); From 62509a07c271f3cefc44fda1152e1253cd5f3665 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 12 Dec 2023 19:22:50 -0500 Subject: [PATCH 034/210] fix: SUP-4721 --- src/interfaces/IPaymentHelper.sol | 1 + src/payments/PaymentHelper.sol | 1 + src/settings/SuperRegistry.sol | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/interfaces/IPaymentHelper.sol b/src/interfaces/IPaymentHelper.sol index 29fcda798..9fbdd483f 100644 --- a/src/interfaces/IPaymentHelper.sol +++ b/src/interfaces/IPaymentHelper.sol @@ -47,6 +47,7 @@ interface IPaymentHelper { // EVENTS // ////////////////////////////////////////////////////////////// + event ChainConfigAdded(uint64 chainId_, PaymentHelperConfig config_); event ChainConfigUpdated(uint64 chainId_, uint256 configType_, bytes config_); ////////////////////////////////////////////////////////////// diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 9d87ed8d6..8194df03a 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -455,6 +455,7 @@ contract PaymentHelper is IPaymentHelper { gasPerByte[chainId_] = config_.dstGasPerByte; ackGasCost[chainId_] = config_.ackGasCost; timelockCost[chainId_] = config_.timelockCost; + emit ChainConfigAdded(chainId_, config_); } /// @inheritdoc IPaymentHelper diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index b9a0553db..e4e34ad28 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -333,7 +333,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { address registryAddress = registryAddress_[i]; uint8 registryId = registryId_[i]; if (registryAddress == address(0)) revert Error.ZERO_ADDRESS(); - if (registryId == 0) revert Error.ZERO_INPUT_VALUE();(); + if (registryId == 0) revert Error.ZERO_INPUT_VALUE(); if (registryAddresses[registryId] != address(0) || stateRegistryIds[registryAddress] != 0) { revert Error.DISABLED(); } From 71d0d1a0b3e563ee418709a74299ff36ca3068df Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:06:43 +0000 Subject: [PATCH 035/210] fix: sup-4736 --- src/SuperformFactory.sol | 9 ++++++++- src/libraries/Error.sol | 7 +++++-- .../superform-factory.addImplementation.sol | 9 ++++++--- .../superform-factory.changeFormPauseStatus.t.sol | 4 +++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 4322b36de..40c7b7ada 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -46,7 +46,10 @@ contract SuperformFactory is ISuperformFactory { mapping(uint256 superformId => bool superformIdExists) public isSuperform; /// @notice If formImplementationId is 0, formImplementation is not part of the protocol - mapping(uint32 formImplementationId => address formBeaconAddress) public formImplementation; + mapping(uint32 formImplementationId => address formImplementationAddress) public formImplementation; + + /// @dev each form implementation address can correspond only to a single formImplementationId + mapping(address formImplementationAddress => uint32 formImplementationId) public formImplementationIds; mapping(uint32 formImplementationId => PauseStatus) public formImplementationPaused; @@ -179,6 +182,9 @@ contract SuperformFactory is ISuperformFactory { if (formImplementation_ == address(0)) revert Error.ZERO_ADDRESS(); if (!ERC165Checker.supportsERC165(formImplementation_)) revert Error.ERC165_UNSUPPORTED(); if (formImplementation[formImplementationId_] != address(0)) { + revert Error.FORM_IMPLEMENTATION_ALREADY_EXISTS(); + } + if (formImplementationIds[formImplementation_] != 0) { revert Error.FORM_IMPLEMENTATION_ID_ALREADY_EXISTS(); } if (!ERC165Checker.supportsInterface(formImplementation_, type(IBaseForm).interfaceId)) { @@ -187,6 +193,7 @@ contract SuperformFactory is ISuperformFactory { /// @dev save the newly added address in the mapping and array registry formImplementation[formImplementationId_] = formImplementation_; + formImplementationIds[formImplementation_] = formImplementationId_; formImplementations.push(formImplementation_); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 2314068fa..18db8b507 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -148,7 +148,10 @@ library Error { /// @dev thrown if a form is not form interface compatible error FORM_INTERFACE_UNSUPPORTED(); - /// @dev error thrown if beacon id already exists + /// @dev error thrown if form implementation address already exists + error FORM_IMPLEMENTATION_ALREADY_EXISTS(); + + /// @dev error thrown if form implementation id already exists error FORM_IMPLEMENTATION_ID_ALREADY_EXISTS(); /// @dev thrown if a form does not exist @@ -160,7 +163,7 @@ library Error { /// @dev thrown if superform not on factory error SUPERFORM_ID_NONEXISTENT(); - /// @dev thrown if same vault and beacon is used to create new superform + /// @dev thrown if same vault and form implementation is used to create new superform error VAULT_FORM_IMPLEMENTATION_COMBINATION_EXISTS(); /// FORM INPUT VALIDATION ERRORS diff --git a/test/unit/superform-factory/superform-factory.addImplementation.sol b/test/unit/superform-factory/superform-factory.addImplementation.sol index 38041a1d0..99538fb31 100644 --- a/test/unit/superform-factory/superform-factory.addImplementation.sol +++ b/test/unit/superform-factory/superform-factory.addImplementation.sol @@ -23,7 +23,7 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { vm.selectFork(FORKS[chainId]); address formImplementation = address(new ERC4626Form(getContract(chainId, "SuperRegistry"))); - uint32 formImplementationId = 0; + uint32 formImplementationId = 44; vm.startPrank(deployer); /// @dev Event With Implementation @@ -42,7 +42,7 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { address formImplementation1 = address(new ERC4626Form(getContract(chainId, "SuperRegistry"))); address formImplementation2 = address(new ERC4626Form(getContract(chainId, "SuperRegistry"))); - uint32 formImplementationId = 0; + uint32 formImplementationId = 44; vm.startPrank(deployer); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( @@ -51,10 +51,13 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { address imp = SuperformFactory(getContract(chainId, "SuperformFactory")).getFormImplementation(formImplementationId); assertEq(imp, formImplementation1); - vm.expectRevert(Error.FORM_IMPLEMENTATION_ID_ALREADY_EXISTS.selector); + vm.expectRevert(Error.FORM_IMPLEMENTATION_ALREADY_EXISTS.selector); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( formImplementation2, formImplementationId ); + + vm.expectRevert(Error.FORM_IMPLEMENTATION_ID_ALREADY_EXISTS.selector); + SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(formImplementation1, 555); } /// @dev Testing adding form with form address 0 diff --git a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol index 9eb6a0e9d..96a9796e2 100644 --- a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol +++ b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol @@ -58,7 +58,9 @@ contract SuperformFactoryChangePauseTest is BaseSetup { formImplementation1, formImplementationId ); - SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus(formImplementationId, ISuperformFactory.PauseStatus.PAUSED, ""); + SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus( + formImplementationId, ISuperformFactory.PauseStatus.PAUSED, "" + ); bool status = SuperformFactory(payable(getContract(chainId, "SuperformFactory"))).isFormImplementationPaused( formImplementationId From 6775006f1692bbc7d2e0b2f5f77e1569a735294a Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:33:41 +0000 Subject: [PATCH 036/210] fix: sup-4736 --- src/crosschain-data/extensions/CoreStateRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 8b5e33daa..7a0cd9d33 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -616,7 +616,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { multiVaultData = _updateTxData(txData_, multiVaultData, srcSender_, srcChainId_, CHAIN_ID); if (multi == 0) { - singleVaultData.liqData.txData = txData_[0]; + singleVaultData.liqData.txData = multiVaultData.liqData[0].txData; return abi.encode(singleVaultData); } From fb8e765b6f9beca9d9028d0647dd04fff10af3bc Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:44:47 +0000 Subject: [PATCH 037/210] fix: sup 4735 --- src/crosschain-data/extensions/CoreStateRegistry.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 7a0cd9d33..7c31fda7e 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -127,7 +127,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { , uint8 isMulti, , - address srcSender, + , uint64 srcChainId ) = _getPayload(payloadId_); @@ -135,7 +135,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { PayloadUpdaterLib.validatePayloadUpdate( prevPayloadHeader, uint8(TransactionType.WITHDRAW), payloadTracking[payloadId_], isMulti ); - prevPayloadBody = _updateWithdrawPayload(prevPayloadBody, srcSender, srcChainId, txData_, isMulti); + prevPayloadBody = _updateWithdrawPayload(prevPayloadBody, srcChainId, txData_, isMulti); /// @dev updates the payload proof _updatePayload(payloadId_, prevPayloadProof, prevPayloadBody, prevPayloadHeader, PayloadState.UPDATED); @@ -591,7 +591,6 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev helper function to update multi vault withdraw payload function _updateWithdrawPayload( bytes memory prevPayloadBody_, - address srcSender_, uint64 srcChainId_, bytes[] calldata txData_, uint8 multi @@ -613,7 +612,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { revert Error.DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH(); } - multiVaultData = _updateTxData(txData_, multiVaultData, srcSender_, srcChainId_, CHAIN_ID); + multiVaultData = _updateTxData(txData_, multiVaultData, srcChainId_, CHAIN_ID); if (multi == 0) { singleVaultData.liqData.txData = multiVaultData.liqData[0].txData; @@ -627,7 +626,6 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { function _updateTxData( bytes[] calldata txData_, InitMultiVaultData memory multiVaultData_, - address srcSender_, uint64 srcChainId_, uint64 dstChainId_ ) @@ -660,7 +658,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { multiVaultData_.liqData[i].liqDstChainId, false, superform, - srcSender_, + multiVaultData_.receiverAddress, multiVaultData_.liqData[i].token, address(0) ) From 0e4aa9c402615060e0da37e819fbea1a5079a879 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 13 Dec 2023 12:09:03 +0000 Subject: [PATCH 038/210] fix: amend test case --- src/crosschain-liquidity/lifi/LiFiValidator.sol | 8 ++++---- .../socket/SocketOneInchValidator.sol | 4 ++-- src/crosschain-liquidity/socket/SocketValidator.sol | 4 ++-- src/interfaces/IBridgeValidator.sol | 2 +- .../crosschain-data/extensions/CoreStateRegistry.t.sol | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index a306a4f74..8838611ac 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -81,8 +81,8 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { } } } else { - /// @dev if withdraws, then receiver address must be the srcSender - if (receiver != args_.srcSender) revert Error.INVALID_TXDATA_RECEIVER(); + /// @dev if withdraws, then receiver address must be the receiverAddress + if (receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } /// @dev remap of address 0 to NATIVE because of how LiFi produces txData @@ -104,8 +104,8 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { /// @dev If same chain deposits then receiver address must be the superform if (receiver != args_.superform) revert Error.INVALID_TXDATA_RECEIVER(); } else { - /// @dev if withdraws, then receiver address must be the srcSender - if (receiver != args_.srcSender) revert Error.INVALID_TXDATA_RECEIVER(); + /// @dev if withdraws, then receiver address must be the receiverAddress + if (receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } /// @dev remap of address 0 to NATIVE because of how LiFi produces txData diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index 787824ddb..01bc81753 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -38,8 +38,8 @@ contract SocketOneInchValidator is BridgeValidator { /// @dev If same chain deposits then receiver address must be the superform if (decodedReq.receiver != args_.superform) revert Error.INVALID_TXDATA_RECEIVER(); } else { - /// @dev if withdraws, then receiver address must be the srcSender - if (decodedReq.receiver != args_.srcSender) revert Error.INVALID_TXDATA_RECEIVER(); + /// @dev if withdraws, then receiver address must be the receiverAddress + if (decodedReq.receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } /// @dev FIXME: add 3. token validations diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index d27ae5cc8..62e18a228 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -60,8 +60,8 @@ contract SocketValidator is BridgeValidator { } } } else { - /// @dev if withdraws, then receiver address must be the srcSender - if (decodedReq.receiverAddress != args_.srcSender) revert Error.INVALID_TXDATA_RECEIVER(); + /// @dev if withdraws, then receiver address must be the receiverAddress + if (decodedReq.receiverAddress != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } /// @dev FIXME: add 3. token validations diff --git a/src/interfaces/IBridgeValidator.sol b/src/interfaces/IBridgeValidator.sol index 88c749fb1..6a9c97100 100644 --- a/src/interfaces/IBridgeValidator.sol +++ b/src/interfaces/IBridgeValidator.sol @@ -15,7 +15,7 @@ interface IBridgeValidator { uint64 liqDstChainId; bool deposit; address superform; - address srcSender; + address receiverAddress; address liqDataToken; address liqDataInterimToken; } diff --git a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol index 892df6a39..070749ae0 100644 --- a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol @@ -374,7 +374,7 @@ contract CoreStateRegistryTest is ProtocolActions { ETH, ETH, false, - deployer, + receiverAddress, uint256(ETH), /// @dev amount is 1 less than (actualWithdrawAmount * 0.9) => slippage > 10% => should revert ((actualWithdrawAmount * 9) / 10) - 1, From e3c436f863be3331cf437ba592e0670bd0a8967a Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:14:08 +0000 Subject: [PATCH 039/210] fix: return excess eth in broadcasting --- script/Abstract.Deploy.Single.s.sol | 2 +- src/SuperPositions.sol | 25 +++++++++++----- src/SuperformFactory.sol | 26 +++++++++++++---- src/crosschain-data/BroadcastRegistry.sol | 5 ++-- src/interfaces/IBroadcastRegistry.sol | 2 ++ src/interfaces/IPaymentHelper.sol | 6 ++-- src/payments/PaymentHelper.sol | 19 ++---------- src/settings/SuperRBAC.sol | 24 ++++++++++++--- test/unit/roles/SuperRBAC.t.sol | 29 ++++++++----------- ...erform-factory.changeFormPauseStatus.t.sol | 4 +-- .../superform-factory.stateSync.sol | 4 +-- .../superform-router/SuperformRouter.t.sol | 2 +- test/utils/AmbParams.sol | 4 +-- test/utils/BaseSetup.sol | 4 +-- 14 files changed, 90 insertions(+), 66 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index afeb349c7..bc518a704 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -835,7 +835,7 @@ abstract contract AbstractDeploySingle is Script { ) ); - PaymentHelper(payable(vars.paymentHelper)).updateRegisterAERC20Params(0, generateBroadcastParams(5, 1)); + PaymentHelper(payable(vars.paymentHelper)).updateRegisterAERC20Params(abi.encode(4, abi.encode(0, ""))); vars.superRegistryC.setAddress( vars.superRegistryC.SUPERFORM_ROUTER(), diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index b5891b974..3988c2b6e 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -369,20 +369,31 @@ contract SuperPositions is ISuperPositions, ERC1155A { /// @dev interacts with broadcast state registry to broadcasting state changes to all connected remote chains /// @param message_ is the crosschain message to be sent. function _broadcast(bytes memory message_) internal { - (uint256 totalFees, bytes memory extraData) = + bytes memory registerTransmuterAMBData = IPaymentHelper(superRegistry.getAddress(keccak256("PAYMENT_HELPER"))).getRegisterTransmuterAMBData(); - (uint8 ambId, bytes memory broadcastParams) = abi.decode(extraData, (uint8, bytes)); + (uint8 ambId, bytes memory broadcastParams) = abi.decode(registerTransmuterAMBData, (uint8, bytes)); - if (msg.value < totalFees) { + /// @dev if the broadcastParams are wrong this will revert + (uint256 gasFee, bytes memory extraData) = abi.decode(broadcastParams, (uint256, bytes)); + + if (msg.value < gasFee) { revert Error.INVALID_BROADCAST_FEE(); } /// @dev ambIds are validated inside the broadcast state registry - /// @dev broadcastParams if wrong will revert in the amb implementation - IBroadcastRegistry(superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))).broadcastPayload{ - value: msg.value - }(msg.sender, ambId, message_, broadcastParams); + IBroadcastRegistry(superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))).broadcastPayload{ value: gasFee }( + msg.sender, ambId, gasFee, message_, extraData + ); + + if (msg.value > gasFee) { + /// @dev forwards the rest to msg.sender + (bool success,) = payable(msg.sender).call{ value: msg.value - gasFee }(""); + + if (!success) { + revert Error.FAILED_TO_SEND_NATIVE(); + } + } } /// @dev deploys new transmuter on broadcasting diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index d38e823ea..f214b3cd4 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -177,6 +177,7 @@ contract SuperformFactory is ISuperformFactory { onlyProtocolAdmin { if (formImplementation_ == address(0)) revert Error.ZERO_ADDRESS(); + if (!ERC165Checker.supportsERC165(formImplementation_)) revert Error.ERC165_UNSUPPORTED(); if (formImplementation[formImplementationId_] != address(0)) { revert Error.FORM_IMPLEMENTATION_ID_ALREADY_EXISTS(); @@ -279,14 +280,29 @@ contract SuperformFactory is ISuperformFactory { /// @dev interacts with broadcast state registry to broadcasting state changes to all connected remote chains /// @param message_ is the crosschain message to be sent. /// @param extraData_ is the amb override information. - function _broadcast(bytes memory message_, bytes memory extraData_) internal { + function _broadcast(bytes memory message_, bytes memory extraData_) internal returns (uint256) { (uint8 ambId, bytes memory broadcastParams) = abi.decode(extraData_, (uint8, bytes)); + /// @dev if the broadcastParams are wrong this will revert + (uint256 gasFee, bytes memory extraData) = abi.decode(broadcastParams, (uint256, bytes)); + + if (msg.value < gasFee) { + revert Error.INVALID_BROADCAST_FEE(); + } + /// @dev ambIds are validated inside the broadcast state registry - /// @dev broadcastParams if wrong will revert in the amb implementation - IBroadcastRegistry(superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))).broadcastPayload{ - value: msg.value - }(msg.sender, ambId, message_, broadcastParams); + IBroadcastRegistry(superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))).broadcastPayload{ value: gasFee }( + msg.sender, ambId, gasFee, message_, extraData + ); + + if (msg.value > gasFee) { + /// @dev forwards the rest to msg.sender + (bool success,) = payable(msg.sender).call{ value: msg.value - gasFee }(""); + + if (!success) { + revert Error.FAILED_TO_SEND_NATIVE(); + } + } } /// @dev synchronize paused status update message from remote chain diff --git a/src/crosschain-data/BroadcastRegistry.sol b/src/crosschain-data/BroadcastRegistry.sol index ee5de1b55..62a45439b 100644 --- a/src/crosschain-data/BroadcastRegistry.sol +++ b/src/crosschain-data/BroadcastRegistry.sol @@ -89,6 +89,7 @@ contract BroadcastRegistry is IBroadcastRegistry { function broadcastPayload( address srcSender_, uint8 ambId_, + uint256 gasFee_, bytes memory message_, bytes memory extraData_ ) @@ -97,9 +98,7 @@ contract BroadcastRegistry is IBroadcastRegistry { override onlySender { - (uint256 gasFee, bytes memory extraData) = abi.decode(extraData_, (uint256, bytes)); - - _broadcastPayload(srcSender_, ambId_, gasFee, message_, extraData); + _broadcastPayload(srcSender_, ambId_, gasFee_, message_, extraData_); } /// @inheritdoc IBroadcastRegistry diff --git a/src/interfaces/IBroadcastRegistry.sol b/src/interfaces/IBroadcastRegistry.sol index 4c53e37cf..1eb6ab438 100644 --- a/src/interfaces/IBroadcastRegistry.sol +++ b/src/interfaces/IBroadcastRegistry.sol @@ -12,11 +12,13 @@ interface IBroadcastRegistry { /// @dev allows core contracts to send payload to all configured destination chain. /// @param srcSender_ is the caller of the function (used for gas refunds). /// @param ambId_ is the identifier of the arbitrary message bridge to be used + /// @param gasFee_ is the gas fee to be used for broadcasting /// @param message_ is the crosschain payload to be broadcasted /// @param extraData_ defines all the message bridge related overrides function broadcastPayload( address srcSender_, uint8 ambId_, + uint256 gasFee_, bytes memory message_, bytes memory extraData_ ) diff --git a/src/interfaces/IPaymentHelper.sol b/src/interfaces/IPaymentHelper.sol index 29fcda798..67dec6ea8 100644 --- a/src/interfaces/IPaymentHelper.sol +++ b/src/interfaces/IPaymentHelper.sol @@ -67,9 +67,8 @@ interface IPaymentHelper { returns (uint256 totalFees, bytes memory extraData); /// @dev returns the amb overrides & gas to be used - /// @return totalFees the msg.value to be sent along the transaction /// @return extraData the amb specific override information - function getRegisterTransmuterAMBData() external view returns (uint256 totalFees, bytes memory extraData); + function getRegisterTransmuterAMBData() external view returns (bytes memory extraData); /// @dev returns the gas fees estimation in native tokens if we send message through a combination of AMBs /// @param ambIds_ is the identifier of different AMBs @@ -191,7 +190,6 @@ interface IPaymentHelper { function updateRemoteChain(uint64 chainId_, uint256 configType_, bytes memory config_) external; /// @dev admin updates config for register transmuter amb params - /// @param totalTransmuterFees_ is the native value fees for registering transmuter on all supported chains /// @param extraDataForTransmuter_ is the broadcast extra data - function updateRegisterAERC20Params(uint256 totalTransmuterFees_, bytes memory extraDataForTransmuter_) external; + function updateRegisterAERC20Params(bytes memory extraDataForTransmuter_) external; } diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 9d87ed8d6..6050b5e53 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -54,7 +54,6 @@ contract PaymentHelper is IPaymentHelper { mapping(uint64 chainId => uint256 gasForOps) public timelockCost; /// @dev register transmuter params - uint256 public totalTransmuterFees; bytes public extraDataForTransmuter; ////////////////////////////////////////////////////////////// @@ -126,13 +125,8 @@ contract PaymentHelper is IPaymentHelper { } /// @inheritdoc IPaymentHelper - function getRegisterTransmuterAMBData() - external - view - override - returns (uint256 totalFees, bytes memory extraData) - { - return (totalTransmuterFees, extraDataForTransmuter); + function getRegisterTransmuterAMBData() external view override returns (bytes memory) { + return extraDataForTransmuter; } /// @inheritdoc IPaymentHelper @@ -526,14 +520,7 @@ contract PaymentHelper is IPaymentHelper { } /// @inheritdoc IPaymentHelper - function updateRegisterAERC20Params( - uint256 totalTransmuterFees_, - bytes memory extraDataForTransmuter_ - ) - external - onlyEmergencyAdmin - { - totalTransmuterFees = totalTransmuterFees_; + function updateRegisterAERC20Params(bytes memory extraDataForTransmuter_) external onlyEmergencyAdmin { extraDataForTransmuter = extraDataForTransmuter_; } diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 73f3aecde..8c6fe9782 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -216,10 +216,26 @@ contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { /// @param extraData_ is the amb override information. function _broadcast(bytes memory message_, bytes memory extraData_) internal { (uint8 ambId, bytes memory broadcastParams) = abi.decode(extraData_, (uint8, bytes)); + + /// @dev if the broadcastParams are wrong this will revert + (uint256 gasFee, bytes memory extraData) = abi.decode(broadcastParams, (uint256, bytes)); + + if (msg.value < gasFee) { + revert Error.INVALID_BROADCAST_FEE(); + } + /// @dev ambIds are validated inside the factory state registry - /// @dev if the broadcastParams are wrong, this will revert in the amb implementation - IBroadcastRegistry(superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))).broadcastPayload{ - value: msg.value - }(msg.sender, ambId, message_, broadcastParams); + IBroadcastRegistry(superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))).broadcastPayload{ value: gasFee }( + msg.sender, ambId, gasFee, message_, extraData + ); + + if (msg.value > gasFee) { + /// @dev forwards the rest to msg.sender + (bool success,) = payable(msg.sender).call{ value: msg.value - gasFee }(""); + + if (!success) { + revert Error.FAILED_TO_SEND_NATIVE(); + } + } } } diff --git a/test/unit/roles/SuperRBAC.t.sol b/test/unit/roles/SuperRBAC.t.sol index 8bff8f248..3c8bc0b71 100644 --- a/test/unit/roles/SuperRBAC.t.sol +++ b/test/unit/roles/SuperRBAC.t.sol @@ -87,12 +87,7 @@ contract SuperRBACTest is BaseSetup { function test_revokePaymentAdminRole() public { _revokeAndCheck( - superRBAC.PAYMENT_ADMIN_ROLE(), - superRegistry.PAYMENT_ADMIN(), - deployer, - "", - generateBroadcastParams(5, 1), - 0 + superRBAC.PAYMENT_ADMIN_ROLE(), superRegistry.PAYMENT_ADMIN(), deployer, "", generateBroadcastParams(0), 0 ); } @@ -137,7 +132,7 @@ contract SuperRBACTest is BaseSetup { superRegistry.CORE_REGISTRY_PROCESSOR(), deployer, "", - generateBroadcastParams(5, 1), + generateBroadcastParams(0), 0 ); } @@ -156,7 +151,7 @@ contract SuperRBACTest is BaseSetup { superRegistry.BROADCAST_REGISTRY_PROCESSOR(), deployer, "", - generateBroadcastParams(5, 1), + generateBroadcastParams(0), 0 ); } @@ -175,7 +170,7 @@ contract SuperRBACTest is BaseSetup { superRegistry.TIMELOCK_REGISTRY_PROCESSOR(), deployer, "", - generateBroadcastParams(5, 1), + generateBroadcastParams(0), 0 ); } @@ -194,7 +189,7 @@ contract SuperRBACTest is BaseSetup { superRegistry.CORE_REGISTRY_UPDATER(), deployer, "", - generateBroadcastParams(5, 1), + generateBroadcastParams(0), 0 ); } @@ -205,7 +200,7 @@ contract SuperRBACTest is BaseSetup { superRegistry.CORE_REGISTRY_RESCUER(), deployer, "", - generateBroadcastParams(5, 1), + generateBroadcastParams(0), 0 ); } @@ -216,7 +211,7 @@ contract SuperRBACTest is BaseSetup { superRegistry.CORE_REGISTRY_DISPUTER(), deployer, "", - generateBroadcastParams(5, 1), + generateBroadcastParams(0), 0 ); } @@ -227,7 +222,7 @@ contract SuperRBACTest is BaseSetup { superRegistry.DST_SWAPPER_PROCESSOR(), deployer, "", - generateBroadcastParams(5, 1), + generateBroadcastParams(0), 0 ); } @@ -278,22 +273,22 @@ contract SuperRBACTest is BaseSetup { vm.expectRevert(Error.CANNOT_REVOKE_NON_BROADCASTABLE_ROLES.selector); /// @dev setting the status as false in chain id = ETH superRBAC.revokeRoleSuperBroadcast{ value: 1 ether }( - keccak256("BROADCASTER_ROLE"), generateBroadcastParams(5, 1), id + keccak256("BROADCASTER_ROLE"), generateBroadcastParams(0), id ); vm.expectRevert(Error.CANNOT_REVOKE_NON_BROADCASTABLE_ROLES.selector); /// @dev setting the status as false in chain id = ETH superRBAC.revokeRoleSuperBroadcast{ value: 1 ether }( - keccak256("PROTOCOL_ADMIN_ROLE"), generateBroadcastParams(5, 1), id + keccak256("PROTOCOL_ADMIN_ROLE"), generateBroadcastParams(0), id ); vm.expectRevert(Error.CANNOT_REVOKE_NON_BROADCASTABLE_ROLES.selector); /// @dev setting the status as false in chain id = ETH superRBAC.revokeRoleSuperBroadcast{ value: 1 ether }( - keccak256("EMERGENCY_ADMIN_ROLE"), generateBroadcastParams(5, 1), id + keccak256("EMERGENCY_ADMIN_ROLE"), generateBroadcastParams(0), id ); vm.expectRevert(Error.CANNOT_REVOKE_NON_BROADCASTABLE_ROLES.selector); /// @dev setting the status as false in chain id = ETH superRBAC.revokeRoleSuperBroadcast{ value: 1 ether }( - keccak256("WORMHOLE_VAA_RELAYER_ROLE"), generateBroadcastParams(5, 1), id + keccak256("WORMHOLE_VAA_RELAYER_ROLE"), generateBroadcastParams(0), id ); } diff --git a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol index e2a870e59..51e30e7bb 100644 --- a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol +++ b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol @@ -32,7 +32,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { ); SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus( - formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(5, 1) + formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(0) ); bool status = SuperformFactory(payable(getContract(chainId, "SuperformFactory"))).isFormImplementationPaused( @@ -90,6 +90,6 @@ contract SuperformFactoryChangePauseTest is BaseSetup { vm.expectRevert(Error.INVALID_FORM_ID.selector); SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus{ value: 800 * 10 ** 18 - }(formImplementationId_invalid, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(5, 2)); + }(formImplementationId_invalid, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(0)); } } diff --git a/test/unit/superform-factory/superform-factory.stateSync.sol b/test/unit/superform-factory/superform-factory.stateSync.sol index ed91f6faf..e71f1942f 100644 --- a/test/unit/superform-factory/superform-factory.stateSync.sol +++ b/test/unit/superform-factory/superform-factory.stateSync.sol @@ -18,7 +18,7 @@ contract SuperformFactoryStateSyncTest is BaseSetup { vm.recordLogs(); SuperformFactory(getContract(ETH, "SuperformFactory")).changeFormImplementationPauseStatus( - formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(5, 1) + formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(0) ); _broadcastPayloadHelper(ETH, vm.getRecordedLogs()); @@ -70,7 +70,7 @@ contract SuperformFactoryStateSyncTest is BaseSetup { /// @dev checks if proof for this next one is diff vm.recordLogs(); SuperformFactory(getContract(ETH, "SuperformFactory")).changeFormImplementationPauseStatus( - formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(5, 1) + formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(0) ); _broadcastPayloadHelper(ETH, vm.getRecordedLogs()); diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 02d716b09..5f266cc44 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -2573,7 +2573,7 @@ contract SuperformRouterTest is ProtocolActions { vm.recordLogs(); SuperformFactory(getContract(ARBI, "SuperformFactory")).changeFormImplementationPauseStatus{ value: 800 ether }( - formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(5, 1) + formImplementationId, ISuperformFactory.PauseStatus.PAUSED, generateBroadcastParams(0) ); _broadcastPayloadHelper(ARBI, vm.getRecordedLogs()); diff --git a/test/utils/AmbParams.sol b/test/utils/AmbParams.sol index 49407ca31..ba4180ec0 100644 --- a/test/utils/AmbParams.sol +++ b/test/utils/AmbParams.sol @@ -3,10 +3,10 @@ import { AMBExtraData, BroadCastAMBExtraData } from "src/types/DataTypes.sol"; pragma solidity ^0.8.23; -function generateBroadcastParams(uint256, uint256) pure returns (bytes memory) { +function generateBroadcastParams(uint256 gasFee_) pure returns (bytes memory) { uint8 ambId = 4; - uint256 gasFee = 0; + uint256 gasFee = gasFee_; bytes memory extraData; return abi.encode(ambId, abi.encode(gasFee, extraData)); diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index f235ec843..aed87ab5e 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -789,9 +789,9 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { 10_000 ) ); - /// @dev 0.01 ether is just a mock value. Wormhole fees are currently 0 + /// @dev 0.01 ether is just a mock value. Wormhole fees are currently 0 on mainnet PaymentHelper(payable(vars.paymentHelper)).updateRegisterAERC20Params( - 0.01 ether, generateBroadcastParams(5, 1) + generateBroadcastParams(0.01 ether) ); vars.superRegistryC.setAddress( From 76d4d2e9c4c1ca36f721964111038ca6218fa800 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 13 Dec 2023 17:32:54 +0000 Subject: [PATCH 040/210] fix: sup-4663 sup-4659 --- src/crosschain-data/extensions/CoreStateRegistry.sol | 4 ++++ src/crosschain-liquidity/LiquidityHandler.sol | 4 ++++ test/unit/crosschain-liquidity/DstSwapper.t.sol | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 8b5e33daa..543b092a6 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -431,6 +431,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { uint256[] memory finalAmounts = new uint256[](validLen); uint256[] memory maxSlippage = new uint256[](validLen); bool[] memory hasDstSwaps = new bool[](validLen); + bool[] memory finalRetain4626s = new bool[](validLen); uint256 currLen; for (uint256 i; i < arrLen; ++i) { @@ -439,6 +440,8 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { finalAmounts[currLen] = multiVaultData.amounts[i]; maxSlippage[currLen] = multiVaultData.maxSlippages[i]; hasDstSwaps[currLen] = multiVaultData.hasDstSwaps[i]; + finalRetain4626s[currLen] = multiVaultData.retain4626s[i]; + ++currLen; } } @@ -447,6 +450,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { multiVaultData.superformIds = finalSuperformIds; multiVaultData.maxSlippages = maxSlippage; multiVaultData.hasDstSwaps = hasDstSwaps; + multiVaultData.retain4626s = finalRetain4626s; finalState_ = PayloadState.UPDATED; } else { finalState_ = PayloadState.PROCESSED; diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index 9b8cc3d6f..b23324457 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -40,6 +40,10 @@ abstract contract LiquidityHandler { internal virtual { + if (amount_ == 0) { + revert Error.ZERO_AMOUNT(); + } + if (bridge_ == address(0)) { revert Error.ZERO_ADDRESS(); } diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index 2fdaf3d78..71dd93061 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -512,7 +512,7 @@ contract DstSwapperTest is ProtocolActions { DstSwapper(dstSwapper).batchProcessTx(1, indices, bridgeId, txData); } - function test_failed_INVALID_SWAP_OUTPUT() public { + function test_failed_ZERO_AMOUNT() public { address payable dstSwapper = payable(getContract(ETH, "DstSwapper")); address payable coreStateRegistry = payable(getContract(ETH, "CoreStateRegistry")); @@ -524,7 +524,7 @@ contract DstSwapperTest is ProtocolActions { bytes memory txData = _buildLiqBridgeTxDataDstSwap(1, getContract(ETH, "WETH"), getContract(ETH, "DAI"), dstSwapper, ETH, 0, 0); /// @dev txData with amount 0 should revert - vm.expectRevert(Error.INVALID_SWAP_OUTPUT.selector); + vm.expectRevert(Error.ZERO_AMOUNT.selector); DstSwapper(dstSwapper).processTx(1, 0, 1, txData); } From 00a7f9be438ca052cbc614caacd2ed34cb4d0135 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 13 Dec 2023 18:26:21 -0500 Subject: [PATCH 041/210] chore: direct deposit, vault limit cleanup, superregistry --- src/BaseRouterImplementation.sol | 4 +-- src/forms/ERC4626FormImplementation.sol | 5 +-- src/interfaces/ISuperRegistry.sol | 4 +-- src/libraries/Error.sol | 6 ++-- src/settings/SuperRegistry.sol | 35 +++++++++++-------- ...626ImplementationInterfaceNotSupported.sol | 2 +- .../superform-form.ERC4626Form.t.sol | 2 +- 7 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 3e6416dc2..4cdaa5932 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -791,8 +791,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev amount can't be 0 if (amount_ == 0) return false; - if (isDeposit_ && factory_.isFormImplementationPaused(formImplementationId)) return false; - /// @dev ensure that receiver address is set always /// @dev in deposits, this is important for receive4626 (on destination). It is also important for refunds on /// destination @@ -824,7 +822,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (len == 0 || liqRequestsLen == 0) return false; if (len != liqRequestsLen) return false; - /// @dev deposits beyond max vaults per tx is blocked only for xchain + /// @dev deposits beyond multi vault limit for a given destination chain blocked if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { return false; } diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index e183ac5aa..df269796d 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -24,6 +24,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ////////////////////////////////////////////////////////////// uint8 internal immutable STATE_REGISTRY_ID; + uint256 private constant ENTIRE_SLIPPAGE = 10_000; ////////////////////////////////////////////////////////////// // STRUCTS // @@ -228,8 +229,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev the difference in vault tokens, ready to be deposited, is compared with the amount inscribed in the /// superform data - if (vars.assetDifference < singleVaultData_.amount) { - revert Error.DIRECT_DEPOSIT_INVALID_DATA(); + if (vars.assetDifference < ((singleVaultData_.amount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) { + revert Error.DIRECT_DEPOSIT_SWAP_FAILED(); } /// @dev notice that vars.assetDifference is deposited regardless if txData exists or not diff --git a/src/interfaces/ISuperRegistry.sol b/src/interfaces/ISuperRegistry.sol index a082b05c5..9f21a2bb8 100644 --- a/src/interfaces/ISuperRegistry.sol +++ b/src/interfaces/ISuperRegistry.sol @@ -150,9 +150,9 @@ interface ISuperRegistry { /// @dev gets the safe vault limit /// @param chainId_ is the id of the remote chain - /// @return vaultLimitPerTx_ is the safe number of vaults to deposit + /// @return vaultLimitPerDestination_ is the safe number of vaults to deposit /// without hitting out of gas error - function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerTx_); + function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerDestination_); /// @dev helps validate if an address is a valid state registry /// @param registryAddress_ is the address of the state registry diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..085c68c44 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -168,9 +168,6 @@ library Error { /// in case of txData, if token output of swap != vault.asset() error DIFFERENT_TOKENS(); - /// @dev thrown if the amount in direct deposit is not correct - error DIRECT_DEPOSIT_INVALID_DATA(); - /// @dev thrown if the token in direct withdraw is not correct error DIRECT_WITHDRAW_INVALID_TOKEN(); @@ -258,6 +255,9 @@ library Error { /// @dev thrown if allowance in direct deposit is not correct error DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); + /// @dev thrown if the swap in a direct deposit resulted in insufficient tokens + error DIRECT_DEPOSIT_SWAP_FAILED(); + /// @dev thrown if payload is not unique error DUPLICATE_PAYLOAD(); diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 81c0a58d9..6d28f1880 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -14,7 +14,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { // CONSTANTS // ////////////////////////////////////////////////////////////// - uint256 private constant MIN_DELAY = 1 hours; + uint256 private constant MIN_DELAY = 15 minutes; uint256 private constant MAX_DELAY = 24 hours; uint64 public immutable CHAIN_ID; @@ -87,7 +87,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { mapping(uint8 ambId => address ambAddresses) public ambAddresses; mapping(uint8 ambId => bool isBroadcastAMB) public isBroadcastAMB; - mapping(uint64 chainId => uint256 vaultLimitPerTx) public vaultLimitPerTx; + mapping(uint64 chainId => uint256 vaultLimitPerDestination) public vaultLimitPerDestination; mapping(uint8 registryId => address registryAddress) public registryAddresses; /// @dev is the reverse mapping of registryAddresses @@ -99,6 +99,13 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { // MODIFIERS // ////////////////////////////////////////////////////////////// + modifier onlyEmergencyAdmin() { + if (!ISuperRBAC(registry[SUPER_RBAC][CHAIN_ID]).hasEmergencyAdminRole(msg.sender)) { + revert Error.NOT_EMERGENCY_ADMIN(); + } + _; + } + modifier onlyProtocolAdmin() { if (!ISuperRBAC(registry[SUPER_RBAC][CHAIN_ID]).hasProtocolAdminRole(msg.sender)) { revert Error.NOT_PROTOCOL_ADMIN(); @@ -170,8 +177,8 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { } /// @inheritdoc ISuperRegistry - function getVaultLimitPerDestination(uint64 chainId_) external view override returns (uint256 vaultLimitPerTx_) { - vaultLimitPerTx_ = vaultLimitPerTx[chainId_]; + function getVaultLimitPerDestination(uint64 chainId_) external view override returns (uint256 vaultLimitPerDestination_) { + vaultLimitPerDestination_ = vaultLimitPerDestination[chainId_]; } /// @inheritdoc ISuperRegistry @@ -206,6 +213,16 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// + /// @inheritdoc ISuperRegistry + function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external override onlyEmergencyAdmin { + if (vaultLimit_ == 0) { + revert Error.ZERO_INPUT_VALUE(); + } + + vaultLimitPerDestination[chainId_] = vaultLimit_; + emit SetVaultLimitPerDestination(chainId_, vaultLimit_); + } + /// @inheritdoc ISuperRegistry function setDelay(uint256 delay_) external override onlyProtocolAdmin { if (delay_ < MIN_DELAY || delay_ > MAX_DELAY) { @@ -228,16 +245,6 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { emit SetPermit2(permit2_); } - /// @inheritdoc ISuperRegistry - function setVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_) external override onlyProtocolAdmin { - if (vaultLimit_ == 0) { - revert Error.ZERO_INPUT_VALUE(); - } - - vaultLimitPerTx[chainId_] = vaultLimit_; - emit SetVaultLimitPerDestination(chainId_, vaultLimit_); - } - /// @inheritdoc ISuperRegistry function setAddress(bytes32 id_, address newAddress_, uint64 chainId_) external override onlyProtocolAdmin { address oldAddress = registry[id_][chainId_]; diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index a11e5a81a..dfae46085 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -164,7 +164,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li /// @dev the balance of vault tokens, ready to be deposited is compared with the previous balance if (vars.balanceAfter - vars.balanceBefore < singleVaultData_.amount) { - revert Error.DIRECT_DEPOSIT_INVALID_DATA(); + revert Error.DIRECT_DEPOSIT_SWAP_FAILED(); } /// @dev the vault asset is approved and deposited to the vault diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index e45fc4d20..1c698613d 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -484,7 +484,7 @@ contract SuperformERC4626FormTest is ProtocolActions { MockERC20(getContract(ETH, "DAI")).approve(router, 1e18); MockERC20(getContract(ETH, "DAI")).approve(router, 1e18); - vm.expectRevert(Error.DIRECT_DEPOSIT_INVALID_DATA.selector); + vm.expectRevert(Error.DIRECT_DEPOSIT_SWAP_FAILED.selector); SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); } From e13c15f074b811a28610efb12eb21753da518334 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 13 Dec 2023 17:32:54 +0000 Subject: [PATCH 042/210] fix: scenario --- .../142.TokenInput.Slippage.AMB12.sol | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/142.TokenInput.Slippage.AMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/142.TokenInput.Slippage.AMB12.sol index 1194aa063..7a92c7165 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/142.TokenInput.Slippage.AMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/142.TokenInput.Slippage.AMB12.sol @@ -25,12 +25,12 @@ contract SDMVW142TokenInputSlippageAMB12 is ProtocolActions { TARGET_VAULTS[AVAX][1] = [1, 4, 1]; TARGET_FORM_KINDS[AVAX][1] = [1, 1, 1]; - PARTIAL[AVAX][1] = [true, false, true]; + PARTIAL[AVAX][1] = [true, false, false]; MAX_SLIPPAGE = 1000; - LIQ_BRIDGES[AVAX][0] = [1, 1, 2]; - LIQ_BRIDGES[AVAX][1] = [1, 2, 1]; + LIQ_BRIDGES[AVAX][0] = [1, 1, 1]; + LIQ_BRIDGES[AVAX][1] = [1, 1, 1]; RECEIVE_4626[AVAX][0] = [false, false, false]; RECEIVE_4626[AVAX][1] = [false, false, false]; @@ -75,8 +75,7 @@ contract SDMVW142TokenInputSlippageAMB12 is ProtocolActions { uint128 amountOne_, uint128 amountOneWithdraw_, uint128 amountTwo_, - uint128 amountThree_, - uint128 amountThreeWithdraw_ + uint128 amountThree_ ) public { @@ -106,9 +105,8 @@ contract SDMVW142TokenInputSlippageAMB12 is ProtocolActions { /// @dev bound to 1 less as partial is true for first vault /// @dev amount = 1 after slippage will become 0, hence starting with 2 amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 2, superPositions[0] - 1)); - /// @dev bound to 1 less as partial is true for third vault - amountThreeWithdraw_ = uint128(bound(amountThreeWithdraw_, 2, superPositions[2] - 1)); - AMOUNTS[AVAX][1] = [amountOneWithdraw_, superPositions[1], amountThreeWithdraw_]; + + AMOUNTS[AVAX][1] = [amountOneWithdraw_, superPositions[1], superPositions[2]]; } _runMainStages(action, act, multiSuperformsData, singleSuperformsData, aV, vars, success); From 8f35e8fe633c645f803c2fc09d5d24ad5e8b0265 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:18:23 +0000 Subject: [PATCH 043/210] fix sup.4776 --- src/payments/PaymentHelper.sol | 63 ++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 9d87ed8d6..2845ea359 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -150,35 +150,38 @@ contract PaymentHelper is IPaymentHelper { uint256 totalDstGas; for (uint256 i; i < len; ++i) { + bool xChain = req_.dstChainIds[i] != CHAIN_ID; + totalDstGas = 0; /// @dev step 1: estimate amb costs - uint256 ambFees = _estimateAMBFees( - req_.ambIds[i], req_.dstChainIds[i], _generateMultiVaultMessage(req_.superformsData[i]) - ); + uint256 ambFees = xChain + ? _estimateAMBFees(req_.ambIds[i], req_.dstChainIds[i], _generateMultiVaultMessage(req_.superformsData[i])) + : 0; superformIdsLen = req_.superformsData[i].superformIds.length; srcAmount += ambFees; if (isDeposit_) { - /// @dev step 2: estimate update cost (only for deposit) - totalDstGas += _estimateUpdateCost(req_.dstChainIds[i], superformIdsLen); - - /// @dev step 3: estimation processing cost of acknowledgement - /// @notice optimistically estimating. (Ideal case scenario: no failed deposits / withdrawals) - srcAmount += _estimateAckProcessingCost(superformIdsLen); - - /// @dev step 4: estimate liq amount + /// @dev step 2: estimate liq amount liqAmount += _estimateLiqAmount(req_.superformsData[i].liqRequests); + if (xChain) { + /// @dev step 3: estimate update cost (only for deposit) + totalDstGas += _estimateUpdateCost(req_.dstChainIds[i], superformIdsLen); + + /// @dev step 4: estimation processing cost of acknowledgement + /// @notice optimistically estimating. (Ideal case scenario: no failed deposits / withdrawals) + srcAmount += _estimateAckProcessingCost(superformIdsLen); - /// @dev step 5: estimate dst swap cost if it exists - totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); + /// @dev step 5: estimate dst swap cost if it exists + totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); + } } /// @dev step 6: estimate execution costs in dst (withdraw / deposit) /// note: execution cost includes acknowledgement messaging cost - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], superformIdsLen); + totalDstGas += xChain ? _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], superformIdsLen) : 0; /// @dev step 6: estimate if timelock form processing costs are involved if (!isDeposit_) { @@ -209,33 +212,35 @@ contract PaymentHelper is IPaymentHelper { { uint256 len = req_.dstChainIds.length; for (uint256 i; i < len; ++i) { + bool xChain = req_.dstChainIds[i] != CHAIN_ID; uint256 totalDstGas; /// @dev step 1: estimate amb costs - uint256 ambFees = _estimateAMBFees( - req_.ambIds[i], req_.dstChainIds[i], _generateSingleVaultMessage(req_.superformsData[i]) - ); + uint256 ambFees = xChain + ? _estimateAMBFees(req_.ambIds[i], req_.dstChainIds[i], _generateSingleVaultMessage(req_.superformsData[i])) + : 0; srcAmount += ambFees; if (isDeposit_) { - /// @dev step 2: estimate update cost (only for deposit) - totalDstGas += _estimateUpdateCost(req_.dstChainIds[i], 1); - - /// @dev step 3: estimation execution cost of acknowledgement - srcAmount += _estimateAckProcessingCost(1); - - /// @dev step 4: estimate the liqAmount + /// @dev step 2: estimate the liqAmount liqAmount += _estimateLiqAmount(req_.superformsData[i].liqRequest.castLiqRequestToArray()); + if (xChain) { + /// @dev step 3: estimate update cost (only for deposit) + totalDstGas += _estimateUpdateCost(req_.dstChainIds[i], 1); - /// @dev step 5: estimate if swap costs are involved - totalDstGas += - _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); + /// @dev step 4: estimation execution cost of acknowledgement + srcAmount += _estimateAckProcessingCost(1); + + /// @dev step 5: estimate if swap costs are involved + totalDstGas += + _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); + } } - /// @dev step 5: estimate execution costs in dst + /// @dev step 6: estimate execution costs in dst /// note: execution cost includes acknowledgement messaging cost - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], 1); + totalDstGas += xChain ? _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], 1) : 0; /// @dev step 6: estimate if timelock form processing costs are involved (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); From fdd655f7ce54896c9563043ebace134985f96d39 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:50:52 +0000 Subject: [PATCH 044/210] fix: sup-4754 --- src/crosschain-liquidity/DstSwapper.sol | 10 +++++++++- test/unit/crosschain-liquidity/DstSwapper.t.sol | 10 +++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 6050b1464..a7ebbb6c9 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -300,7 +300,15 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { if (userSuppliedInterimToken_ != v.approvalToken) { revert Error.INVALID_INTERIM_TOKEN(); } - + if (userSuppliedInterimToken_ == NATIVE) { + if (address(this).balance < v.amount) { + revert Error.INSUFFICIENT_BALANCE(); + } + } else { + if (IERC20(userSuppliedInterimToken_).balanceOf(address(this)) < v.amount) { + revert Error.INSUFFICIENT_BALANCE(); + } + } v.finalDst = address(coreStateRegistry_); /// @dev validates the bridge data diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index 71dd93061..b539f7ba7 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -65,18 +65,18 @@ contract DstSwapperTest is ProtocolActions { vm.expectRevert(Error.INVALID_PAYLOAD_ID.selector); DstSwapper(dstSwapper).processTx(1000, 0, 1, txData); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); - /// @dev try with a non-existent index vm.expectRevert(Error.INVALID_INDEX.selector); DstSwapper(dstSwapper).processTx(1, 420, 1, txData); + DstSwapper(dstSwapper).processTx(1, 0, 1, txData); + /// @dev retry the same payload id and indices vm.expectRevert(Error.DST_SWAP_ALREADY_PROCESSED.selector); DstSwapper(dstSwapper).processTx(1, 0, 1, txData); /// @dev no funds in multi-tx processor at this point; should revert - vm.expectRevert(abi.encodeWithSelector(Error.FAILED_TO_EXECUTE_TXDATA.selector, native)); + vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); DstSwapper(dstSwapper).processTx(2, 0, 1, txData); } else { revert(); @@ -94,7 +94,7 @@ contract DstSwapperTest is ProtocolActions { bytes memory txData = _buildLiqBridgeTxDataDstSwap(1, getContract(ETH, "WETH"), getContract(ETH, "DAI"), dstSwapper, ETH, 1e18, 0); /// @dev no funds in multi-tx processor at this point; should revert - vm.expectRevert(abi.encodeWithSelector(Error.FAILED_TO_EXECUTE_TXDATA.selector, getContract(ETH, "WETH"))); + vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); DstSwapper(dstSwapper).processTx(1, 0, 1, txData); } @@ -466,7 +466,7 @@ contract DstSwapperTest is ProtocolActions { DstSwapper(dstSwapper).batchProcessTx(1, indices, bridgeId, txData); /// @dev no funds in multi-tx processor at this point; should revert - vm.expectRevert(abi.encodeWithSelector(Error.FAILED_TO_EXECUTE_TXDATA.selector, native)); + vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); DstSwapper(dstSwapper).batchProcessTx(2, indices, bridgeId, txData); } From 862f4be86047b95184cb7d7517f93e3ca439803d Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Thu, 14 Dec 2023 18:21:53 +0530 Subject: [PATCH 045/210] chore: add payable to hyperlane handle() --- .../adapters/hyperlane/HyperlaneImplementation.sol | 2 +- src/vendor/hyperlane/IMessageRecipient.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index f739ee970..185ba469f 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -192,7 +192,7 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { } /// @inheritdoc IMessageRecipient - function handle(uint32 origin_, bytes32 sender_, bytes calldata body_) external override onlyMailbox { + function handle(uint32 origin_, bytes32 sender_, bytes calldata body_) external payable override onlyMailbox { /// @dev 1. validate caller /// @dev 2. validate src chain sender /// @dev 3. validate message uniqueness diff --git a/src/vendor/hyperlane/IMessageRecipient.sol b/src/vendor/hyperlane/IMessageRecipient.sol index 339d5dc0c..4e8784e96 100644 --- a/src/vendor/hyperlane/IMessageRecipient.sol +++ b/src/vendor/hyperlane/IMessageRecipient.sol @@ -7,5 +7,5 @@ interface IMessageRecipient { /// @param _origin Domain ID of the chain from which the message came /// @param _sender Address of the message sender on the origin chain as bytes32 /// @param _message Raw bytes content of message body - function handle(uint32 _origin, bytes32 _sender, bytes calldata _message) external; + function handle(uint32 _origin, bytes32 _sender, bytes calldata _message) external payable; } From c9857f63853402f7f3dfcff1bb3eaae16040376d Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:07:08 +0000 Subject: [PATCH 046/210] fix: sup 4737 --- src/BaseForm.sol | 2 -- .../extensions/CoreStateRegistry.sol | 28 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 04683b8d8..8e686b6ef 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -156,8 +156,6 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// - receive() external payable { } - /// @param superRegistry_ ISuperRegistry address deployed /// @param vault_ The vault address this form pertains to /// @dev sets caller as the admin of the contract. diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 543b092a6..32302302a 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -316,6 +316,16 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// + /// @dev returns vault asset from superform + function _getVaultAsset(address superform_) internal view returns (address) { + return IBaseForm(superform_).getVaultAsset(); + } + + /// @dev returns if superform is valid + function _isSuperform(uint256 superformId_) internal view returns (bool) { + return ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(superformId_); + } + /// @dev returns a superformAddress function _getSuperform(uint256 superformId_) internal pure returns (address superform) { (superform,,) = superformId_.getSuperform(); @@ -560,12 +570,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { finalState_ = PayloadState.UPDATED; } - if ( - !( - ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(superformId_) - && finalState_ == PayloadState.UPDATED - ) - ) { + if (!(_isSuperform(superformId_) && finalState_ == PayloadState.UPDATED)) { failedDeposits[payloadId_].superformIds.push(superformId_); address asset; @@ -773,7 +778,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev this means that this amount was already added to the failedDeposits state variable and should not /// be re-added (or processed here) if (multiVaultData.amounts[i] != 0) { - underlying = IERC20(IBaseForm(superforms[i]).getVaultAsset()); + underlying = IERC20(_getVaultAsset(superforms[i])); if (underlying.balanceOf(address(this)) >= multiVaultData.amounts[i]) { underlying.safeIncreaseAllowance(superforms[i], multiVaultData.amounts[i]); @@ -855,7 +860,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { InitSingleVaultData memory singleVaultData = abi.decode(payload_, (InitSingleVaultData)); singleVaultData.extraFormData = abi.encode(payloadId_, 0); - if (!ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(singleVaultData.superformId)) { + if (!_isSuperform(singleVaultData.superformId)) { revert Error.SUPERFORM_ID_NONEXISTENT(); } @@ -890,8 +895,9 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { { InitSingleVaultData memory singleVaultData = abi.decode(payload_, (InitSingleVaultData)); - (address superform_,,) = singleVaultData.superformId.getSuperform(); - IERC20 underlying = IERC20(IBaseForm(superform_).getVaultAsset()); + address superform_ = _getSuperform(singleVaultData.superformId); + address vaultAsset = _getVaultAsset(superform_); + IERC20 underlying = IERC20(vaultAsset); if (underlying.balanceOf(address(this)) >= singleVaultData.amount) { underlying.safeIncreaseAllowance(superform_, singleVaultData.amount); @@ -916,7 +922,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev if any deposit fails, add it to failedDepositSuperformIds mapping for future rescuing failedDeposits[payloadId_].superformIds.push(singleVaultData.superformId); - failedDeposits[payloadId_].settlementToken.push(IBaseForm(superform_).getVaultAsset()); + failedDeposits[payloadId_].settlementToken.push(vaultAsset); failedDeposits[payloadId_].settleFromDstSwapper.push(false); emit FailedXChainDeposits(payloadId_); From 272388f58430741093f85044344b2d47730df672 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:29:19 -0500 Subject: [PATCH 047/210] chore: base router fixes --- src/BaseRouterImplementation.sol | 13 ++++++++----- src/libraries/Error.sol | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index bf0e5acce..a25d91339 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -161,7 +161,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou (address superform,,) = req_.superformData.superformId.getSuperform(); (uint256 amountIn, uint8 bridgeId) = - _singleVaultTokenForward(msg.sender, address(0), req_.superformData.permit2data, ambData); + _singleVaultTokenForward(msg.sender, address(0), req_.superformData.permit2data, ambData, true); LiqRequest memory emptyRequest; @@ -602,7 +602,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev decode superforms (superform,,) = vaultData_.superformId.getSuperform(); - _singleVaultTokenForward(srcSender_, superform, permit2data_, vaultData_); + _singleVaultTokenForward(srcSender_, superform, permit2data_, vaultData_, false); /// @dev deposits token to a given vault and mint vault positions. dstAmount = _directDeposit( @@ -877,7 +877,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou address srcSender_, address target_, bytes memory permit2data_, - InitSingleVaultData memory vaultData_ + InitSingleVaultData memory vaultData_, + bool xChain ) internal virtual @@ -889,6 +890,10 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou v.txDataLength = vaultData_.liqData.txData.length; + if (v.txDataLength == 0 && xChain) { + revert Error.NO_TXDATA_PRESENT(); + } + if (v.txDataLength != 0) { v.amountIn = IBridgeValidator(superRegistry.getBridgeValidator(v.bridgeId)).decodeAmountIn( vaultData_.liqData.txData, false @@ -976,8 +981,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (token != NATIVE) { v.token = IERC20(token); - v.totalAmount; - v.permit2dataLen = permit2data_.length; for (uint256 i; i < v.len; ++i) { diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..a5ed517fd 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -286,7 +286,7 @@ library Error { /// @dev thrown if liquidity bridge fails for erc20 or native tokens error FAILED_TO_EXECUTE_TXDATA(address token); - /// @dev thrown if underlying asset mismatches + /// @dev thrown if asset being used for deposit mismatches in multivault deposits error INVALID_DEPOSIT_TOKEN(); /// STATE REGISTRY EXECUTION ERRORS From fa119f121475d1c2cee4fe81ca3a60f5c1d494ec Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:44:46 +0000 Subject: [PATCH 048/210] fix: requested areas --- src/crosschain-data/extensions/TimelockStateRegistry.sol | 6 ++++-- src/forms/ERC4626FormImplementation.sol | 2 ++ src/forms/ERC4626TimelockForm.sol | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index 6267da5ac..b75dba5bd 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -108,6 +108,8 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree override onlyTimelockSuperform(data_.superformId) { + if (data_.receiverAddress == address(0)) revert Error.RECEIVER_ADDRESS_NOT_SET(); + ++timelockPayloadCounter; timelockPayload[timelockPayloadCounter] = @@ -254,7 +256,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree /// xChainWithdraw succeeds. /// @dev Constructs return message in case of a FAILURE to perform redemption of already unlocked assets function _constructSingleReturnData( - address srcSender_, + address receiverAddress_, InitSingleVaultData memory singleVaultData_ ) internal @@ -269,7 +271,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree uint8(CallbackType.FAIL), 0, superRegistry.getStateRegistryId(address(this)), - srcSender_, + receiverAddress_, CHAIN_ID ), abi.encode( diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 101e99898..01d2b5955 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -398,6 +398,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { revert Error.INSUFFICIENT_BALANCE(); } + if (refundAddress_ == address(0)) revert Error.ZERO_ADDRESS(); + vaultContract.safeTransfer(refundAddress_, amount_); emit EmergencyWithdrawalProcessed(refundAddress_, amount_); } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 0ae2bfcd0..8937781f0 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -66,6 +66,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { onlyTimelockStateRegistry returns (uint256 dstAmount) { + if (p_.data.receiverAddress == address(0)) revert Error.RECEIVER_ADDRESS_NOT_SET(); + if (_isPaused(p_.data.superformId)) { IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( p_.data, p_.data.receiverAddress From 7174d570d19b0418fc86e29b1ed9a0795d50769b Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:46:59 +0000 Subject: [PATCH 049/210] fix: naming issues --- src/SuperPositions.sol | 8 ++++---- src/SuperformFactory.sol | 4 ++-- src/libraries/Error.sol | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index b5891b974..13188c8cd 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -71,10 +71,10 @@ contract SuperPositions is ISuperPositions, ERC1155A { /// if msg.sender isn't superformRouter then it must be state registry for that superform if (msg.sender != router) { - (, uint32 formBeaconId,) = DataLib.getSuperform(superformId); + (, uint32 formImplementationId,) = DataLib.getSuperform(superformId); uint8 registryId = superRegistry.getStateRegistryId(msg.sender); - if (uint32(registryId) != formBeaconId) { + if (uint32(registryId) != formImplementationId) { revert Error.NOT_MINTER(); } } @@ -96,10 +96,10 @@ contract SuperPositions is ISuperPositions, ERC1155A { if (msg.sender != router) { uint256 len = superformIds.length; for (uint256 i; i < len; ++i) { - (, uint32 formBeaconId,) = DataLib.getSuperform(superformIds[i]); + (, uint32 formImplementationId,) = DataLib.getSuperform(superformIds[i]); uint8 registryId = superRegistry.getStateRegistryId(msg.sender); - if (uint32(registryId) != formBeaconId) { + if (uint32(registryId) != formImplementationId) { revert Error.NOT_MINTER(); } } diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 40c7b7ada..93923f64d 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -38,7 +38,7 @@ contract SuperformFactory is ISuperformFactory { uint256 public xChainPayloadCounter; uint256 public superformCounter; - /// @dev all form beacon addresses + /// @dev all form implementation addresses address[] public formImplementations; /// @dev all superform ids @@ -214,7 +214,7 @@ contract SuperformFactory is ISuperformFactory { address tFormImplementation = formImplementation[formImplementationId_]; if (tFormImplementation == address(0)) revert Error.FORM_DOES_NOT_EXIST(); - /// @dev Same vault and beacon can be used only once to create superform + /// @dev Same vault and implementation can be used only once to create superform bytes32 vaultFormImplementationCombination = keccak256(abi.encode(tFormImplementation, vault_)); if (vaultFormImplCombinationToSuperforms[vaultFormImplementationCombination] != 0) { revert Error.VAULT_FORM_IMPLEMENTATION_COMBINATION_EXISTS(); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 18db8b507..f668e7fb2 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -383,7 +383,7 @@ library Error { /// @dev thrown in KYCDAO form if no KYC token is present error NO_VALID_KYC_TOKEN(); - /// @dev thrown if implementation formBeacon is PAUSED, users cannot perform any action + /// @dev thrown if form implementation is PAUSED, users cannot perform any action error PAUSED(); /// @dev thrown if withdrawal tx data is not updated From c7246abca98f0315333aebe015e2a3533e860c69 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:49:45 +0000 Subject: [PATCH 050/210] fix: comments --- src/settings/SuperRBAC.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 8c6fe9782..41bc0ff42 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -224,7 +224,7 @@ contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { revert Error.INVALID_BROADCAST_FEE(); } - /// @dev ambIds are validated inside the factory state registry + /// @dev ambIds are validated inside the broadcast state registry IBroadcastRegistry(superRegistry.getAddress(keccak256("BROADCAST_REGISTRY"))).broadcastPayload{ value: gasFee }( msg.sender, ambId, gasFee, message_, extraData ); From cf94b464b4b582e9b66d20f743ea9b64b66bee21 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:51:13 -0500 Subject: [PATCH 051/210] chore: more 0 checks in AMB impls --- .../adapters/hyperlane/HyperlaneImplementation.sol | 10 ++++++++-- .../adapters/layerzero/LayerzeroImplementation.sol | 8 +++++++- .../automatic-relayer/WormholeARImplementation.sol | 8 +++++++- .../specialized-relayer/WormholeSRImplementation.sol | 8 +++++++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index f8a614ca3..f8e32198c 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -85,7 +85,7 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { /// @param mailbox_ is the address of hyperlane mailbox /// @param igp_ is the address of hyperlane gas paymaster function setHyperlaneConfig(IMailbox mailbox_, IInterchainGasPaymaster igp_) external onlyProtocolAdmin { - if (address(mailbox_) == address(0)) revert Error.ZERO_ADDRESS(); + if (address(mailbox_) == address(0) || address(igp_) == address(0)) revert Error.ZERO_ADDRESS(); mailbox = mailbox_; igp = igp_; @@ -221,7 +221,13 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { (,,, uint8 registryId,,) = decoded.txInfo.decodeTxInfo(); IBaseStateRegistry targetRegistry = IBaseStateRegistry(superRegistry.getStateRegistry(registryId)); - targetRegistry.receivePayload(superChainId[origin_], body_); + uint64 origin = superChainId[origin_]; + + if (origin == 0) { + revert Error.INVALID_CHAIN_ID(); + } + + targetRegistry.receivePayload(origin, body_); } ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index 5b76415b4..b759a7eb5 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -316,7 +316,13 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio IBaseStateRegistry targetRegistry = IBaseStateRegistry(superRegistry.getStateRegistry(registryId)); - targetRegistry.receivePayload(superChainId[_srcChainId], _payload); + uint64 srcChainId = superChainId[_srcChainId]; + + if (srcChainId == 0) { + revert Error.INVALID_CHAIN_ID(); + } + + targetRegistry.receivePayload(srcChainId, _payload); } function _lzSend( diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 2f98f5994..5608f4420 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -202,7 +202,13 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { (,,, uint8 registryId,,) = decoded.txInfo.decodeTxInfo(); IBaseStateRegistry targetRegistry = IBaseStateRegistry(superRegistry.getStateRegistry(registryId)); - targetRegistry.receivePayload(superChainId[sourceChain_], payload_); + uint64 sourceChain = superChainId[sourceChain_]; + + if (sourceChain == 0) { + revert Error.INVALID_CHAIN_ID(); + } + + targetRegistry.receivePayload(sourceChain, payload_); } /// @dev allows protocol admin to add new chain ids in future diff --git a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol index 52930d097..8098ea383 100644 --- a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol @@ -205,8 +205,14 @@ contract WormholeSRImplementation is IBroadcastAmbImplementation { processedMessages[wormholeMessage.hash] = true; /// @dev decoding payload + uint64 emitterChainId = superChainId[wormholeMessage.emitterChainId]; + + if (emitterChainId == 0) { + revert Error.INVALID_CHAIN_ID(); + } + IBroadcastRegistry(superRegistry.getStateRegistry(BROADCAST_REGISTRY_ID)).receiveBroadcastPayload( - superChainId[wormholeMessage.emitterChainId], wormholeMessage.payload + emitterChainId, wormholeMessage.payload ); } From 612f9c9296476c7d460d23f6a350c7d930df953e Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:00:33 -0500 Subject: [PATCH 052/210] chore: bridgeValidator fixes --- src/crosschain-liquidity/socket/SocketOneInchValidator.sol | 6 ++++-- src/crosschain-liquidity/socket/SocketValidator.sol | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index 787824ddb..58961a9cf 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -13,7 +13,9 @@ contract SocketOneInchValidator is BridgeValidator { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BridgeValidator(superRegistry_) { } + constructor(address superRegistry_) BridgeValidator(superRegistry_) { + if (address(superRegistry_) == address(0)) revert Error.DISABLED(); + } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // @@ -91,7 +93,7 @@ contract SocketOneInchValidator is BridgeValidator { } /// @dev helps parsing socket calldata and return the socket request - function _parseCallData(bytes calldata callData) internal pure returns (bytes memory) { + function _parseCallData(bytes calldata callData) internal pure returns (bytes calldata) { return callData[4:]; } } diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index f1cb57125..8406c5ff3 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -12,7 +12,10 @@ contract SocketValidator is BridgeValidator { ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BridgeValidator(superRegistry_) { } + + constructor(address superRegistry_) BridgeValidator(superRegistry_) { + if (address(superRegistry_) == address(0)) revert Error.DISABLED(); + } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // @@ -116,7 +119,7 @@ contract SocketValidator is BridgeValidator { } /// @dev helps parsing socket calldata and return the socket request - function _parseCallData(bytes calldata callData) internal pure returns (bytes memory) { + function _parseCallData(bytes calldata callData) internal pure returns (bytes calldata) { return callData[4:]; } } From 3982a1da513bd7858dea391580083b722351fad4 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:00:53 -0500 Subject: [PATCH 053/210] chore: add to lifi too --- src/crosschain-liquidity/lifi/LiFiValidator.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index 47d8e248a..cbac2d4e5 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -16,7 +16,9 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BridgeValidator(superRegistry_) { } + constructor(address superRegistry_) BridgeValidator(superRegistry_) { + if (address(superRegistry_) == address(0)) revert Error.DISABLED(); + } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // From 7b571f899a52d46f172045f13bb9d12e41919367 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:50:06 +0000 Subject: [PATCH 054/210] fix: hash collision, naming fixes, validations, adding interimToken --- script/Abstract.Deploy.Single.s.sol | 2 +- src/BaseForm.sol | 20 +++++++++++++------ src/SuperPositions.sol | 12 +++++------ .../extensions/CoreStateRegistry.sol | 18 ++++++++--------- src/crosschain-data/utils/PayloadHelper.sol | 12 +++++++++-- src/interfaces/IPayloadHelper.sol | 2 ++ src/interfaces/ISuperRegistry.sol | 4 ++-- src/settings/SuperRegistry.sol | 13 ++++++++---- .../invariant/handlers/VaultSharesHandler.sol | 2 +- .../utils/PayloadHelper.multiVault.t.sol | 2 +- .../utils/PayloadHelper.singleVault.t.sol | 2 +- test/utils/BaseSetup.sol | 4 ++-- 12 files changed, 58 insertions(+), 35 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index afeb349c7..f4a2cb634 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -484,7 +484,7 @@ abstract contract AbstractDeploySingle is Script { vars.kycDao4626Form = address(new ERC4626KYCDaoForm{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; - /// @dev 9 - Add newly deployed form implementations to Factory, formBeaconId 1 + /// @dev 9 - Add newly deployed form implementations to Factory, formImplementationId 1 ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0]); ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1]); diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 04683b8d8..c8a66d621 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -214,7 +214,11 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { notPaused(singleVaultData_) returns (uint256 dstAmount) { - dstAmount = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_); + if (srcChainId_ > 0 && srcChainId_ != CHAIN_ID) { + dstAmount = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_); + } else { + revert Error.INVALID_CHAIN_ID(); + } } /// @inheritdoc IBaseForm @@ -228,12 +232,16 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { onlyCoreStateRegistry returns (uint256 dstAmount) { - if (!_isPaused(singleVaultData_.superformId)) { - dstAmount = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); + if (srcChainId_ > 0 && srcChainId_ != CHAIN_ID) { + if (!_isPaused(singleVaultData_.superformId)) { + dstAmount = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); + } else { + IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( + singleVaultData_, srcSender_ + ); + } } else { - IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( - singleVaultData_, srcSender_ - ); + revert Error.INVALID_CHAIN_ID(); } } diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index b5891b974..41a376a09 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -71,10 +71,10 @@ contract SuperPositions is ISuperPositions, ERC1155A { /// if msg.sender isn't superformRouter then it must be state registry for that superform if (msg.sender != router) { - (, uint32 formBeaconId,) = DataLib.getSuperform(superformId); + (, uint32 formImplementationId,) = DataLib.getSuperform(superformId); uint8 registryId = superRegistry.getStateRegistryId(msg.sender); - if (uint32(registryId) != formBeaconId) { + if (uint32(registryId) != formImplementationId) { revert Error.NOT_MINTER(); } } @@ -96,10 +96,10 @@ contract SuperPositions is ISuperPositions, ERC1155A { if (msg.sender != router) { uint256 len = superformIds.length; for (uint256 i; i < len; ++i) { - (, uint32 formBeaconId,) = DataLib.getSuperform(superformIds[i]); + (, uint32 formImplementationId,) = DataLib.getSuperform(superformIds[i]); uint8 registryId = superRegistry.getStateRegistryId(msg.sender); - if (uint32(registryId) != formBeaconId) { + if (uint32(registryId) != formImplementationId) { revert Error.NOT_MINTER(); } } @@ -348,8 +348,8 @@ contract SuperPositions is ISuperPositions, ERC1155A { (address superform,,) = id.getSuperform(); string memory name = - string(abi.encodePacked("SuperPositions AERC20 ", IBaseForm(superform).superformYieldTokenName())); - string memory symbol = string(abi.encodePacked("aERC20-", IBaseForm(superform).superformYieldTokenSymbol())); + string(abi.encode("SuperPositions AERC20 ", IBaseForm(superform).superformYieldTokenName())); + string memory symbol = string(abi.encode("aERC20-", IBaseForm(superform).superformYieldTokenSymbol())); uint8 decimal = uint8(IBaseForm(superform).getVaultDecimals()); aErc20Token = address(new aERC20(name, symbol, decimal)); /// @dev broadcast and deploy to the other destination chains diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 8b5e33daa..dd611590b 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -75,6 +75,15 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { amounts = failedDeposits[payloadId_].amounts; } + /// @dev used for try catching purposes + function validateSlippage(uint256 finalAmount_, uint256 amount_, uint256 maxSlippage_) public view returns (bool) { + // only internal transaction + if (msg.sender != address(this)) { + revert Error.INVALID_INTERNAL_CALL(); + } + + return PayloadUpdaterLib.validateSlippage(finalAmount_, amount_, maxSlippage_); + } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// @@ -487,15 +496,6 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { newPayloadBody_ = abi.encode(singleVaultData); } - function validateSlippage(uint256 finalAmount_, uint256 amount_, uint256 maxSlippage_) public view returns (bool) { - // only internal transaction - if (msg.sender != address(this)) { - revert Error.INVALID_INTERNAL_CALL(); - } - - return PayloadUpdaterLib.validateSlippage(finalAmount_, amount_, maxSlippage_); - } - function _updateAmount( IDstSwapper dstSwapper, bool hasDstSwap_, diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index e233c1d20..b4d5370fe 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -142,6 +142,7 @@ contract PayloadHelper is IPayloadHelper { uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, + address[] memory interimTokens, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts @@ -347,6 +348,7 @@ contract PayloadHelper is IPayloadHelper { uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, + address[] memory interimTokens, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts @@ -357,6 +359,7 @@ contract PayloadHelper is IPayloadHelper { bridgeIds = new uint8[](imvd.liqData.length); txDatas = new bytes[](imvd.liqData.length); tokens = new address[](imvd.liqData.length); + interimTokens = new address[](imvd.liqData.length); liqDstChainIds = new uint64[](imvd.liqData.length); amountsIn = new uint256[](imvd.liqData.length); nativeAmounts = new uint256[](imvd.liqData.length); @@ -367,6 +370,7 @@ contract PayloadHelper is IPayloadHelper { bridgeIds[i] = imvd.liqData[i].bridgeId; txDatas[i] = imvd.liqData[i].txData; tokens[i] = imvd.liqData[i].token; + interimTokens[i] = imvd.liqData[i].interimToken; liqDstChainIds[i] = imvd.liqData[i].liqDstChainId; /// @dev decodes amount from txdata only if its present @@ -378,7 +382,7 @@ contract PayloadHelper is IPayloadHelper { nativeAmounts[i] = imvd.liqData[i].nativeAmount; } - return (bridgeIds, txDatas, tokens, liqDstChainIds, amountsIn, nativeAmounts); + return (bridgeIds, txDatas, tokens, interimTokens, liqDstChainIds, amountsIn, nativeAmounts); } function _decodeSingleLiqData( @@ -391,6 +395,7 @@ contract PayloadHelper is IPayloadHelper { uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, + address[] memory interimTokens, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts @@ -408,6 +413,9 @@ contract PayloadHelper is IPayloadHelper { tokens = new address[](1); tokens[0] = isvd.liqData.token; + interimTokens = new address[](1); + interimTokens[0] = isvd.liqData.interimToken; + liqDstChainIds = new uint64[](1); liqDstChainIds[0] = isvd.liqData.liqDstChainId; @@ -422,6 +430,6 @@ contract PayloadHelper is IPayloadHelper { nativeAmounts = new uint256[](1); nativeAmounts[0] = isvd.liqData.nativeAmount; - return (bridgeIds, txDatas, tokens, liqDstChainIds, amountsIn, nativeAmounts); + return (bridgeIds, txDatas, tokens, interimTokens, liqDstChainIds, amountsIn, nativeAmounts); } } diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index 0f99b4a83..46915763f 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -44,6 +44,7 @@ interface IPayloadHelper { /// @return bridgeIds are the ids of the bridges to be used /// @return txDatas are the array of txData to be sent to the bridges /// @return tokens are the tokens to be used in the liqData + /// @return interimTokens are the interim tokens to be used in the liqData /// @return liqDstChainIds are the final destination chain id for the underlying token (can be arbitrary on /// withdraws) /// @return amountsIn are the from amounts to the liquidity bridge @@ -55,6 +56,7 @@ interface IPayloadHelper { uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, + address[] memory interimTokens, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts diff --git a/src/interfaces/ISuperRegistry.sol b/src/interfaces/ISuperRegistry.sol index a082b05c5..9f21a2bb8 100644 --- a/src/interfaces/ISuperRegistry.sol +++ b/src/interfaces/ISuperRegistry.sol @@ -150,9 +150,9 @@ interface ISuperRegistry { /// @dev gets the safe vault limit /// @param chainId_ is the id of the remote chain - /// @return vaultLimitPerTx_ is the safe number of vaults to deposit + /// @return vaultLimitPerDestination_ is the safe number of vaults to deposit /// without hitting out of gas error - function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerTx_); + function getVaultLimitPerDestination(uint64 chainId_) external view returns (uint256 vaultLimitPerDestination_); /// @dev helps validate if an address is a valid state registry /// @param registryAddress_ is the address of the state registry diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 81c0a58d9..158bf0fa6 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -87,7 +87,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { mapping(uint8 ambId => address ambAddresses) public ambAddresses; mapping(uint8 ambId => bool isBroadcastAMB) public isBroadcastAMB; - mapping(uint64 chainId => uint256 vaultLimitPerTx) public vaultLimitPerTx; + mapping(uint64 chainId => uint256 vaultLimitPerDestination) public vaultLimitPerDestination; mapping(uint8 registryId => address registryAddress) public registryAddresses; /// @dev is the reverse mapping of registryAddresses @@ -170,8 +170,13 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { } /// @inheritdoc ISuperRegistry - function getVaultLimitPerDestination(uint64 chainId_) external view override returns (uint256 vaultLimitPerTx_) { - vaultLimitPerTx_ = vaultLimitPerTx[chainId_]; + function getVaultLimitPerDestination(uint64 chainId_) + external + view + override + returns (uint256 vaultLimitPerDestination_) + { + vaultLimitPerDestination_ = vaultLimitPerDestination[chainId_]; } /// @inheritdoc ISuperRegistry @@ -234,7 +239,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { revert Error.ZERO_INPUT_VALUE(); } - vaultLimitPerTx[chainId_] = vaultLimit_; + vaultLimitPerDestination[chainId_] = vaultLimit_; emit SetVaultLimitPerDestination(chainId_, vaultLimit_); } diff --git a/test/invariant/handlers/VaultSharesHandler.sol b/test/invariant/handlers/VaultSharesHandler.sol index 5656ab774..ae527a8a1 100644 --- a/test/invariant/handlers/VaultSharesHandler.sol +++ b/test/invariant/handlers/VaultSharesHandler.sol @@ -523,7 +523,7 @@ contract VaultSharesHandler is InvariantProtocolActions { mapping( uint64 chainId => mapping( - uint32 formBeaconId + uint32 formImplementationId => mapping(string underlying => mapping(uint256 vaultKindIndex => address realVault)) ) ) storage existingVaults = REAL_VAULT_ADDRESS; diff --git a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol index 9e9ad823d..5a710c897 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol @@ -262,7 +262,7 @@ contract PayloadHelperMultiTest is ProtocolActions { vm.selectFork(FORKS[DST_CHAINS[0]]); CheckDstPayloadLiqDataInternalVars memory v; - (v.bridgeIds, v.txDatas, v.tokens, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( + (v.bridgeIds, v.txDatas, v.tokens,, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))] ).decodeCoreStateRegistryPayloadLiqData(2); diff --git a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol index 658868f06..131a57053 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol @@ -293,7 +293,7 @@ contract PayloadHelperSingleTest is ProtocolActions { vm.selectFork(FORKS[DST_CHAINS[0]]); CheckDstPayloadLiqDataInternalVars memory v; - (v.bridgeIds, v.txDatas, v.tokens, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( + (v.bridgeIds, v.txDatas, v.tokens,, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))] ).decodeCoreStateRegistryPayloadLiqData(2); diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index f235ec843..43b8e5ee5 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -298,7 +298,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { mapping( uint64 chainId => mapping( - uint32 formBeaconId + uint32 formImplementationId => mapping(string underlying => mapping(uint256 vaultKindIndex => address realVault)) ) ) public REAL_VAULT_ADDRESS; @@ -1170,7 +1170,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { mapping( uint64 chainId => mapping( - uint32 formBeaconId + uint32 formImplementationId => mapping(string underlying => mapping(uint256 vaultKindIndex => address realVault)) ) ) storage existingVaults = REAL_VAULT_ADDRESS; From f6a843ec5c26b193d78f296816f4884e656003eb Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 18:06:49 +0000 Subject: [PATCH 055/210] fix: comment --- src/crosschain-liquidity/LiquidityHandler.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index b23324457..be385c7b8 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -53,6 +53,7 @@ abstract contract LiquidityHandler { token.safeIncreaseAllowance(bridge_, amount_); } else { if (nativeAmount_ < amount_) revert Error.INSUFFICIENT_NATIVE_AMOUNT(); + if (nativeAmount_ > address(this).balance) revert Error.INSUFFICIENT_BALANCE(); } (bool success,) = payable(bridge_).call{ value: nativeAmount_ }(txData_); From db22d3bc7629c127714507254b2ee67b98688cec Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 14 Dec 2023 18:08:18 +0000 Subject: [PATCH 056/210] fix: uri --- script/Abstract.Deploy.Single.s.sol | 8 ++++++-- test/utils/BaseSetup.sol | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index fab9a7266..90ebeb577 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -498,8 +498,12 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_ROUTER(), vars.superformRouter, vars.chainId); /// @dev 11 - Deploy SuperPositions - vars.superPositions = - address(new SuperPositions{ salt: salt }("https://ipfs-gateway.superform.xyz/ipns/k51qzi5uqu5dj8wup5t6yyj55o8rj4dx98g931fczrzcagp26hstv7ba7shfmc/Animations/", vars.superRegistry)); + vars.superPositions = address( + new SuperPositions{ salt: salt }( + "https://ipfs-gateway.superform.xyz/ipns/k51qzi5uqu5dg90fqdo9j63m556wlddeux4mlgyythp30zousgh3huhyzouyq8/JSON/", + vars.superRegistry + ) + ); contracts[vars.chainId][bytes32(bytes("SuperPositions"))] = vars.superPositions; vars.superRegistryC.setAddress(vars.superRegistryC.SUPER_POSITIONS(), vars.superPositions, vars.chainId); diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index c7ab344e7..f8f1f7f62 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -642,8 +642,12 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_ROUTER(), vars.superformRouter, vars.chainId); /// @dev 13 - Deploy SuperPositions - vars.superPositions = - address(new SuperPositions{ salt: salt }("https://ipfs-gateway.superform.xyz/ipns/k51qzi5uqu5dj8wup5t6yyj55o8rj4dx98g931fczrzcagp26hstv7ba7shfmc/Animations/", vars.superRegistry)); + vars.superPositions = address( + new SuperPositions{ salt: salt }( + "https://ipfs-gateway.superform.xyz/ipns/k51qzi5uqu5dg90fqdo9j63m556wlddeux4mlgyythp30zousgh3huhyzouyq8/JSON/", + vars.superRegistry + ) + ); contracts[vars.chainId][bytes32(bytes("SuperPositions"))] = vars.superPositions; vars.superRegistryC.setAddress(vars.superRegistryC.SUPER_POSITIONS(), vars.superPositions, vars.chainId); From d0f32b936a787addde89af2d58bee819ba61e373 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:02:59 -0500 Subject: [PATCH 057/210] chore: len assignments --- src/crosschain-liquidity/DstSwapper.sol | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 3cf335e59..606e0c592 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -170,7 +170,9 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { onlySwapper nonReentrant { - if (indices_.length != bridgeIds_.length || bridgeIds_.length != txData_.length) { + + uint256 len = indices_.length; + if (len != bridgeIds_.length || len != txData_.length) { revert Error.ARRAY_LENGTH_MISMATCH(); } @@ -183,7 +185,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { InitMultiVaultData memory data = abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitMultiVaultData)); - uint256 len = indices_.length; + for (uint256 i; i < len; ++i) { _processTx( payloadId_, indices_[i], bridgeIds_[i], txData_[i], data.liqData[i].interimToken, coreStateRegistry @@ -231,8 +233,9 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { override onlySwapper { + uint256 len = indices_.length; - if (indices_.length != interimTokens_.length || interimTokens_.length != amounts_.length) { + if (len != interimTokens_.length || len != amounts_.length) { revert Error.ARRAY_LENGTH_MISMATCH(); } @@ -245,7 +248,6 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { InitMultiVaultData memory data = abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitMultiVaultData)); - uint256 len = indices_.length; for (uint256 i; i < len; ++i) { _updateFailedTx( payloadId_, indices_[i], interimTokens_[i], data.liqData[i].interimToken, amounts_[i], coreStateRegistry From 6405a4a6198ab297eb70f3f20425c4864ce4d67b Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:55:03 -0500 Subject: [PATCH 058/210] chore: updates + tests --- src/BaseRouterImplementation.sol | 3 +++ test/unit/super-registry/SuperRegistry.t.sol | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 4cdaa5932..1ddedbf7b 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -791,6 +791,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev amount can't be 0 if (amount_ == 0) return false; + /// @dev redudant check on same chain, but helpful on xchain actions to halt deposits earlier + if (isDeposit_ && factory_.isFormImplementationPaused(formImplementationId)) return false; + /// @dev ensure that receiver address is set always /// @dev in deposits, this is important for receive4626 (on destination). It is also important for refunds on /// destination diff --git a/test/unit/super-registry/SuperRegistry.t.sol b/test/unit/super-registry/SuperRegistry.t.sol index 1cd484776..e08075084 100644 --- a/test/unit/super-registry/SuperRegistry.t.sol +++ b/test/unit/super-registry/SuperRegistry.t.sol @@ -332,7 +332,7 @@ contract SuperRegistryTest is BaseSetup { superRegistry.setVaultLimitPerDestination(1, 0); vm.prank(address(420)); - vm.expectRevert(Error.NOT_PROTOCOL_ADMIN.selector); + vm.expectRevert(Error.NOT_EMERGENCY_ADMIN.selector); superRegistry.setVaultLimitPerDestination(1, 100); } @@ -349,7 +349,7 @@ contract SuperRegistryTest is BaseSetup { function test_set_delay() public { vm.prank(deployer); vm.expectRevert(Error.INVALID_TIMELOCK_DELAY.selector); - superRegistry.setDelay(30 minutes); + superRegistry.setDelay(5 minutes); vm.prank(deployer); vm.expectRevert(Error.INVALID_TIMELOCK_DELAY.selector); From 0b12ae1a515fc56f1c06bc470c1156d90c52fa3a Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 15 Dec 2023 16:58:29 +0530 Subject: [PATCH 059/210] chore: fix dst swapper index --- src/crosschain-liquidity/DstSwapper.sol | 15 +- src/libraries/Error.sol | 3 + .../crosschain-liquidity/DstSwapper.t.sol | 141 +++++++++++++++++- 3 files changed, 154 insertions(+), 5 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 6050b1464..543587139 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -160,7 +160,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { /// @inheritdoc IDstSwapper function batchProcessTx( uint256 payloadId_, - uint256[] calldata indices, + uint256[] calldata indices_, uint8[] calldata bridgeIds_, bytes[] calldata txData_ ) @@ -169,8 +169,10 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { onlySwapper nonReentrant { - IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); + uint256 len = txData_.length; + if (len != bridgeIds_.length && len != txData_.length) revert Error.ARRAY_LENGTH_MISMATCH(); + IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); _isValidPayloadId(payloadId_, coreStateRegistry); (,, uint8 multi,,,) = DataLib.decodeTxInfo(coreStateRegistry.payloadHeader(payloadId_)); @@ -178,10 +180,15 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { InitMultiVaultData memory data = abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitMultiVaultData)); - uint256 len = txData_.length; + uint256 maxIndex = data.liqData.length; + uint256 index; + for (uint256 i; i < len; ++i) { + index = indices_[i]; + if (index >= maxIndex) revert Error.INDEX_OUT_OF_BOUNDS(); + _processTx( - payloadId_, indices[i], bridgeIds_[i], txData_[i], data.liqData[i].interimToken, coreStateRegistry + payloadId_, index, bridgeIds_[i], txData_[i], data.liqData[index].interimToken, coreStateRegistry ); } } diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..7414d717f 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -28,6 +28,9 @@ library Error { /// @dev thrown if wormhole relayer is not set error RELAYER_NOT_SET(); + /// @dev thrown if indices are out of bounds + error INDEX_OUT_OF_BOUNDS(); + ////////////////////////////////////////////////////////////// // AUTHORIZATION ERRORS // ////////////////////////////////////////////////////////////// diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index 2fdaf3d78..dd8f6c1cb 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -98,6 +98,82 @@ contract DstSwapperTest is ProtocolActions { DstSwapper(dstSwapper).processTx(1, 0, 1, txData); } + function test_partial_multi_vault_dstSwap() public { + address payable dstSwapper = payable(getContract(ETH, "DstSwapper")); + address payable coreStateRegistry = payable(getContract(ETH, "CoreStateRegistry")); + + vm.selectFork(FORKS[ETH]); + + /// simulate an existing payload in csr + address superform = getContract(ETH, string.concat("DAI", "VaultMock", "Superform", "1")); + uint256 superformId = DataLib.packSuperform(superform, 1, ETH); + + uint256[] memory superformIds = new uint256[](2); + superformIds[0] = superformId; + superformIds[1] = superformId; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1e18; + amounts[1] = 1e18; + + uint256[] memory slippages = new uint256[](2); + slippages[0] = 1000; + slippages[1] = 1000; + + LiqRequest memory liq; + liq.interimToken = getContract(ETH, "WETH"); + + LiqRequest[] memory liqs = new LiqRequest[](2); + liqs[1] = liq; + + bool[] memory hasDstSwaps = new bool[](2); + hasDstSwaps[1] = true; + + vm.prank(getContract(ETH, "LayerzeroImplementation")); + CoreStateRegistry(coreStateRegistry).receivePayload( + 137, + abi.encode( + AMBMessage( + DataLib.packTxInfo(1, 1, 1, 1, address(0), 1), + abi.encode( + new uint8[](0), + abi.encode( + InitMultiVaultData( + 1, + superformIds, + amounts, + new uint256[](2), + liqs, + hasDstSwaps, + new bool[](2), + receiverAddress, + bytes("") + ) + ) + ) + ) + ) + ); + + vm.startPrank(deployer); + deal(getContract(ETH, "WETH"), dstSwapper, 1e18); + + bytes memory txData = _buildLiqBridgeTxDataDstSwap( + 1, getContract(ETH, "WETH"), getContract(ETH, "DAI"), dstSwapper, ETH, 1e17, 1001 + ); + + uint256[] memory indices = new uint256[](1); + indices[0] = 1; + + uint8[] memory bridgeIds = new uint8[](1); + bridgeIds[0] = 1; + + bytes[] memory txDataArr = new bytes[](1); + txDataArr[0] = txData; + + DstSwapper(dstSwapper).batchProcessTx(1, indices, bridgeIds, txDataArr); + } + function test_single_non_native_updateFailedTx() public { address payable dstSwapper = payable(getContract(OP, "DstSwapper")); address payable coreStateRegistry = payable(getContract(OP, "CoreStateRegistry")); @@ -449,7 +525,7 @@ contract DstSwapperTest is ProtocolActions { (bool success,) = payable(dstSwapper).call{ value: 2e18 }(""); if (!success) revert(); - vm.expectRevert(Error.INVALID_INDEX.selector); + vm.expectRevert(Error.INDEX_OUT_OF_BOUNDS.selector); DstSwapper(dstSwapper).batchProcessTx(1, indices, bridgeId, txData); indices[0] = 0; indices[1] = 1; @@ -748,6 +824,69 @@ contract DstSwapperTest is ProtocolActions { ); } + function _simulatePartialMultiVaultExistingPayloadOnOP( + address payable coreStateRegistry, + address interimToken_ + ) + internal + returns (uint256[] memory superformIds) + { + /// simulate an existing payload in csr + address superform = getContract(OP, string.concat("WETH", "VaultMock", "Superform", "1")); + uint256 superformId1 = DataLib.packSuperform(superform, 1, OP); + uint256 superformId2 = DataLib.packSuperform( + getContract(OP, string.concat("WETH", "VaultMockRevertDeposit", "Superform", "1")), 1, OP + ); + + vm.prank(getContract(OP, "LayerzeroImplementation")); + + superformIds = new uint256[](2); + superformIds[0] = superformId1; + superformIds[1] = superformId2; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1e18; + amounts[1] = 1e18; + + bool[] memory hasDstSwaps = new bool[](2); + hasDstSwaps[0] = false; + hasDstSwaps[1] = true; + + uint256[] memory maxSlippages = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 1000; + + LiqRequest[] memory liq = new LiqRequest[](2); + liq[0] = LiqRequest("", getContract(OP, "DAI"), interimToken_, 1, OP, 0); + liq[1] = LiqRequest("", getContract(OP, "DAI"), interimToken_, 1, OP, 0); + CoreStateRegistry(coreStateRegistry).receivePayload( + ETH, + abi.encode( + AMBMessage( + DataLib.packTxInfo( + uint8(TransactionType.DEPOSIT), uint8(CallbackType.INIT), uint8(1), 1, users[0], ETH + ), + abi.encode( + new uint8[](1), + abi.encode( + InitMultiVaultData( + 1, + superformIds, + amounts, + maxSlippages, + liq, + hasDstSwaps, + new bool[](2), + users[0], + bytes("") + ) + ) + ) + ) + ) + ); + } + function _simulateMultiVaultExistingPayload(address payable coreStateRegistry) internal { /// simulate an existing payload in csr address superform = getContract(ETH, string.concat("DAI", "VaultMock", "Superform", "1")); From c3832da6399b27f97de57bdbc5464e6d15787666 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 15 Dec 2023 17:40:23 +0530 Subject: [PATCH 060/210] fix: retry payload fee check --- .../hyperlane/HyperlaneImplementation.sol | 6 ++++++ .../WormholeARImplementation.sol | 6 ++++++ src/libraries/Error.sol | 3 +++ .../adapters/HyperlaneImplementation.t.sol | 3 ++- .../adapters/WormholeARImplementation.t.sol | 16 ++++++++++------ test/unit/payments/PayMaster.t.sol | 4 +++- 6 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index 185ba469f..44e775129 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -145,6 +145,12 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { /// @inheritdoc IAmbImplementation function retryPayload(bytes memory data_) external payable override { (bytes32 messageId, uint32 destinationDomain, uint256 gasAmount) = abi.decode(data_, (bytes32, uint32, uint256)); + uint256 fees = igp.quoteGasPayment(destinationDomain, gasAmount); + + if (msg.value != fees) { + revert Error.INVALID_RETRY_FEE(); + } + igp.payForGas{ value: msg.value }(messageId, destinationDomain, gasAmount, msg.sender); } diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 90cf1da5c..587094b64 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -158,6 +158,12 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { address newDeliveryProviderAddress ) = abi.decode(data_, (VaaKey, uint16, uint256, uint256, address)); + (uint256 fees,) = relayer.quoteEVMDeliveryPrice(targetChain, 0, newGasLimit); + + if (fees != msg.value) { + revert Error.INVALID_RETRY_FEE(); + } + if (newDeliveryProviderAddress == address(0)) { revert Error.ZERO_ADDRESS(); } diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..5e09a7128 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -308,6 +308,9 @@ library Error { /// @dev thrown if broadcast fee is invalid error INVALID_BROADCAST_FEE(); + /// @dev thrown if retry fees is less than required + error INVALID_RETRY_FEE(); + /// @dev thrown if broadcast message type is wrong error INVALID_MESSAGE_TYPE(); diff --git a/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol b/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol index c5a3d6a42..7b583fc8e 100644 --- a/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol @@ -132,7 +132,8 @@ contract HyperlaneImplementationTest is CommonProtocolActions { vm.prank(deployer); /// @dev note these values don't make sense, should be estimated properly - hyperlaneImplementation.retryPayload{ value: 10 ether }(abi.encode(messageId, destination, 1_500_000)); + uint256 fees = hyperlaneImplementation.igp().quoteGasPayment(destination, 1_500_000); + hyperlaneImplementation.retryPayload{ value: fees }(abi.encode(messageId, destination, 1_500_000)); } function test_revert_handle_duplicatePayload_invalidSrcChainSender_invalidCaller(address malice_) public { diff --git a/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol b/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol index 68f05e996..90cf47750 100644 --- a/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol +++ b/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol @@ -29,18 +29,20 @@ contract WormholeARImplementationTest is BaseSetup { function test_retryPayload() public { VaaKey memory vaaKey = VaaKey(1, keccak256("test"), 1); - bytes memory data = abi.encode(vaaKey, 2, 3, 4, deployer); + bytes memory data = abi.encode(vaaKey, 5, 3, 4, deployer); vm.mockCall( address(wormholeARImpl.relayer()), abi.encodeWithSelector( - IWormholeRelayer(wormholeARImpl.relayer()).resendToEvm.selector, vaaKey, 2, 3, 4, deployer + IWormholeRelayer(wormholeARImpl.relayer()).resendToEvm.selector, vaaKey, 5, 3, 4, deployer ), abi.encode("") ); + uint256 fee = wormholeARImpl.estimateFees(uint64(137), bytes(""), abi.encode(uint256(0), uint256(4))); + vm.prank(deployer); - wormholeARImpl.retryPayload(data); + wormholeARImpl.retryPayload{ value: fee }(data); vm.clearMockedCalls(); } @@ -48,19 +50,21 @@ contract WormholeARImplementationTest is BaseSetup { function test_retryPayloadWithZeroAddress() public { VaaKey memory vaaKey = VaaKey(1, keccak256("test"), 1); - bytes memory data = abi.encode(vaaKey, 2, 3, 4, address(0)); + bytes memory data = abi.encode(vaaKey, 5, 3, 4, address(0)); vm.mockCall( address(wormholeARImpl.relayer()), abi.encodeWithSelector( - IWormholeRelayer(wormholeARImpl.relayer()).resendToEvm.selector, vaaKey, 2, 3, 4, address(0) + IWormholeRelayer(wormholeARImpl.relayer()).resendToEvm.selector, vaaKey, 5, 3, 4, address(0) ), abi.encode("") ); + uint256 fee = wormholeARImpl.estimateFees(uint64(137), bytes(""), abi.encode(uint256(0), uint256(4))); + vm.expectRevert(Error.ZERO_ADDRESS.selector); vm.prank(deployer); - wormholeARImpl.retryPayload(data); + wormholeARImpl.retryPayload{ value: fee }(data); vm.clearMockedCalls(); } diff --git a/test/unit/payments/PayMaster.t.sol b/test/unit/payments/PayMaster.t.sol index 7960f5b9a..619ef3273 100644 --- a/test/unit/payments/PayMaster.t.sol +++ b/test/unit/payments/PayMaster.t.sol @@ -300,9 +300,11 @@ contract PayMasterTest is ProtocolActions { bytes memory data = abi.encode(messageId, destination, 1_500_000); + uint256 fees = HyperlaneImplementation(hyperlane).igp().quoteGasPayment(destination, 1_500_000); + vm.prank(deployer); vm.deal(feeCollector, 10 ether); - PayMaster(payable(feeCollector)).treatAMB(2, 10 ether, data); + PayMaster(payable(feeCollector)).treatAMB(2, fees, data); } function _successfulDeposit() internal { From 7d2ea3924fb8dd982751ea7d5cf4a8c8f2ead8ed Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 15 Dec 2023 12:32:20 +0000 Subject: [PATCH 061/210] fix: test, remove unused return --- src/SuperformFactory.sol | 2 +- .../adapters/HyperlaneImplementation.t.sol | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 960e7e19d..004f0f5ac 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -289,7 +289,7 @@ contract SuperformFactory is ISuperformFactory { /// @dev interacts with broadcast state registry to broadcasting state changes to all connected remote chains /// @param message_ is the crosschain message to be sent. /// @param extraData_ is the amb override information. - function _broadcast(bytes memory message_, bytes memory extraData_) internal returns (uint256) { + function _broadcast(bytes memory message_, bytes memory extraData_) internal { (uint8 ambId, bytes memory broadcastParams) = abi.decode(extraData_, (uint8, bytes)); /// @dev if the broadcastParams are wrong this will revert diff --git a/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol b/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol index c5a3d6a42..1bf5bda32 100644 --- a/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol @@ -10,15 +10,24 @@ import { Error } from "src/libraries/Error.sol"; contract HyperlaneImplementationTest is CommonProtocolActions { address public constant MAILBOX = 0xc005dc82818d67AF737725bD4bf75435d065D239; + ISuperRegistry public superRegistry; HyperlaneImplementation hyperlaneImplementation; + HyperlaneImplementation hyperlaneImplementation_arbi; function setUp() public override { super.setUp(); vm.selectFork(FORKS[ETH]); superRegistry = ISuperRegistry(getContract(ETH, "SuperRegistry")); + hyperlaneImplementation = HyperlaneImplementation(payable(superRegistry.getAmbAddress(2))); + vm.selectFork(FORKS[ARBI]); + + hyperlaneImplementation_arbi = + HyperlaneImplementation(payable(ISuperRegistry(getContract(ARBI, "SuperRegistry")).getAmbAddress(2))); + + vm.selectFork(FORKS[ETH]); } function test_setReceiver(uint256 chainIdSeed_) public { @@ -148,7 +157,7 @@ contract HyperlaneImplementationTest is CommonProtocolActions { vm.prank(MAILBOX); hyperlaneImplementation.handle( - uint32(ETH), bytes32(uint256(uint160(address(hyperlaneImplementation)))), abi.encode(ambMessage) + uint32(ARBI), bytes32(uint256(uint160(address(hyperlaneImplementation_arbi)))), abi.encode(ambMessage) ); vm.expectRevert(Error.DUPLICATE_PAYLOAD.selector); From 959addf924eeaab963f07a7dcb4b09f5387e5051 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 15 Dec 2023 18:10:24 +0530 Subject: [PATCH 062/210] feat: add refunds for wormhole ar implementation --- .../WormholeARImplementation.sol | 22 ++++++++++++++----- test/utils/BaseSetup.sol | 3 +++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 587094b64..9cb7027c9 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -22,7 +22,6 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - ISuperRegistry public immutable superRegistry; ////////////////////////////////////////////////////////////// @@ -30,6 +29,7 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { ////////////////////////////////////////////////////////////// IWormholeRelayer public relayer; + uint16 public refundChainId; mapping(uint64 => uint16) public ambChainId; mapping(uint16 => uint64) public superChainId; @@ -41,7 +41,10 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { ////////////////////////////////////////////////////////////// /// @dev emitted when wormhole relayer is set - event WormholeRelayerSet(address wormholeRelayer); + event WormholeRelayerSet(address indexed wormholeRelayer); + + /// @dev emitted when refund chain id is set + event WormholeRefundChainIdSet(uint16 indexed refundChainId); ////////////////////////////////////////////////////////////// // MODIFIERS // @@ -128,7 +131,7 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { /// @inheritdoc IAmbImplementation function dispatchPayload( - address, /*srcSender_*/ + address srcSender_, uint64 dstChainId_, bytes memory message_, bytes memory extraData_ @@ -140,11 +143,11 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { onlyValidStateRegistry { uint16 dstChainId = ambChainId[dstChainId_]; - (uint256 dstNativeAirdrop, uint256 dstGasLimit) = abi.decode(extraData_, (uint256, uint256)); + /// @dev refunds any excess on this chain back to srcSender_ relayer.sendPayloadToEvm{ value: msg.value }( - dstChainId, authorizedImpl[dstChainId], message_, dstNativeAirdrop, dstGasLimit + dstChainId, authorizedImpl[dstChainId], message_, dstNativeAirdrop, dstGasLimit, refundChainId, srcSender_ ); } @@ -234,6 +237,15 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { emit ChainAdded(superChainId_); } + /// @dev allows protocol admin to set wormhole chain id for refunds + /// @param refundChainId_ is the wormhole chain id of current chain + function setRefundChainId(uint16 refundChainId_) external onlyProtocolAdmin { + if (refundChainId_ == 0) revert Error.INVALID_CHAIN_ID(); + refundChainId = refundChainId_; + + emit WormholeRefundChainIdSet(refundChainId_); + } + /// @dev allows protocol admin to set receiver implementation on a new chain id /// @param chainId_ is the identifier of the destination chain within wormhole /// @param authorizedImpl_ is the implementation of the wormhole message bridge on the specified destination diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index f235ec843..cb07e66e6 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -885,6 +885,9 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.DST_SWAPPER_PROCESSOR(), deployer, vars.dstChainId ); } else { + /// set refund chain id to wormhole chain id + WormholeARImplementation(vars.WormholeARImplementation).setRefundChainId(wormhole_chainIds[j]); + /// ack gas cost: 40000 /// timelock step form cost: 50000 /// default gas price: 50 Gwei From a6e8373447d7a63a90aa296e1b801ce6d0d282ff Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 15 Dec 2023 18:17:42 +0530 Subject: [PATCH 063/210] chore: add refund chain id for wormhole ar --- script/Abstract.Deploy.Single.s.sol | 1 + test/utils/BaseSetup.sol | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index afeb349c7..2e678a0fb 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -434,6 +434,7 @@ abstract contract AbstractDeploySingle is Script { contracts[vars.chainId][bytes32(bytes("WormholeARImplementation"))] = vars.wormholeImplementation; WormholeARImplementation(vars.wormholeImplementation).setWormholeRelayer(wormholeRelayer); + WormholeARImplementation(vars.wormholeImplementation).setRefundChainId(wormhole_chainIds[i]); /// @dev 6.5- deploy Wormhole Specialized Relayer Implementation vars.wormholeSRImplementation = address(new WormholeSRImplementation{ salt: salt }(vars.superRegistryC)); diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index cb07e66e6..c57280d24 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -491,6 +491,8 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { contracts[vars.chainId][bytes32(bytes("WormholeARImplementation"))] = vars.wormholeImplementation; WormholeARImplementation(vars.wormholeImplementation).setWormholeRelayer(wormholeRelayer); + /// set refund chain id to wormhole chain id + WormholeARImplementation(vars.wormholeImplementation).setRefundChainId(wormhole_chainIds[i]); /// @dev 6.5- deploy Wormhole Specialized Relayer Implementation vars.wormholeSRImplementation = address(new WormholeSRImplementation{ salt: salt }(vars.superRegistryC)); @@ -885,9 +887,6 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.DST_SWAPPER_PROCESSOR(), deployer, vars.dstChainId ); } else { - /// set refund chain id to wormhole chain id - WormholeARImplementation(vars.WormholeARImplementation).setRefundChainId(wormhole_chainIds[j]); - /// ack gas cost: 40000 /// timelock step form cost: 50000 /// default gas price: 50 Gwei From a8521fabcc84f8d9b0c7f54efbd3d6b06f57eb28 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 15 Dec 2023 18:39:56 +0530 Subject: [PATCH 064/210] chore: fix payment helper estimates for retain4626 case --- src/payments/PaymentHelper.sol | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 6050b5e53..b234374d0 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -152,7 +152,6 @@ contract PaymentHelper is IPaymentHelper { ); superformIdsLen = req_.superformsData[i].superformIds.length; - srcAmount += ambFees; if (isDeposit_) { @@ -161,7 +160,13 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 3: estimation processing cost of acknowledgement /// @notice optimistically estimating. (Ideal case scenario: no failed deposits / withdrawals) - srcAmount += _estimateAckProcessingCost(superformIdsLen); + uint256 arrLen = req_.superformsData[i].retain4626s.length; + uint256 ackLen; + for (uint256 j; j < arrLen; ++j) { + if (!req_.superformsData[i].retain4626s[j]) ++ackLen; + } + + srcAmount += _estimateAckProcessingCost(ackLen); /// @dev step 4: estimate liq amount liqAmount += _estimateLiqAmount(req_.superformsData[i].liqRequests); @@ -217,7 +222,9 @@ contract PaymentHelper is IPaymentHelper { totalDstGas += _estimateUpdateCost(req_.dstChainIds[i], 1); /// @dev step 3: estimation execution cost of acknowledgement - srcAmount += _estimateAckProcessingCost(1); + if (!req_.superformsData[i].retain4626) { + srcAmount += _estimateAckProcessingCost(1); + } /// @dev step 4: estimate the liqAmount liqAmount += _estimateLiqAmount(req_.superformsData[i].liqRequest.castLiqRequestToArray()); @@ -271,7 +278,14 @@ contract PaymentHelper is IPaymentHelper { totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, superformIdsLen); /// @dev step 4: estimation execution cost of acknowledgement - if (isDeposit_) srcAmount += _estimateAckProcessingCost(superformIdsLen); + if (isDeposit_) { + uint256 arrLen = req_.superformsData.retain4626s.length; + uint256 ackLen; + for (uint256 j; j < arrLen; ++j) { + if (!req_.superformsData.retain4626s[j]) ++ackLen; + } + srcAmount += _estimateAckProcessingCost(ackLen); + } /// @dev step 5: estimate liq amount if (isDeposit_) liqAmount += _estimateLiqAmount(req_.superformsData.liqRequests); @@ -321,7 +335,7 @@ contract PaymentHelper is IPaymentHelper { totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, 1); /// @dev step 4: estimation execution cost of acknowledgement - if (isDeposit_) srcAmount += _estimateAckProcessingCost(1); + if (isDeposit_ && req_.superformData.hasDstSwap) srcAmount += _estimateAckProcessingCost(1); /// @dev step 5: estimate the liq amount if (isDeposit_) liqAmount += _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); From 8974d1a88f6bb2d67e0023423189664ed05ef2d1 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:23:57 +0000 Subject: [PATCH 065/210] fix: comment --- src/BaseForm.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index c8a66d621..42c35a58c 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -214,7 +214,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { notPaused(singleVaultData_) returns (uint256 dstAmount) { - if (srcChainId_ > 0 && srcChainId_ != CHAIN_ID) { + if (srcChainId_ != 0 && srcChainId_ != CHAIN_ID) { dstAmount = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_); } else { revert Error.INVALID_CHAIN_ID(); @@ -232,7 +232,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { onlyCoreStateRegistry returns (uint256 dstAmount) { - if (srcChainId_ > 0 && srcChainId_ != CHAIN_ID) { + if (srcChainId_ != 0 && srcChainId_ != CHAIN_ID) { if (!_isPaused(singleVaultData_.superformId)) { dstAmount = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); } else { From c4789e945e1dd24e915994059e1e9119c0855ff5 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 15 Dec 2023 19:15:11 +0530 Subject: [PATCH 066/210] feat: add missing indexed fields --- src/BaseRouterImplementation.sol | 5 +---- .../adapters/hyperlane/HyperlaneImplementation.sol | 4 ++-- .../adapters/layerzero/LayerzeroImplementation.sol | 6 +++--- .../automatic-relayer/WormholeARImplementation.sol | 2 +- .../specialized-relayer/WormholeSRImplementation.sol | 6 +++--- src/interfaces/IAmbImplementation.sol | 4 ++-- src/interfaces/IBaseForm.sol | 12 +++++++++--- src/interfaces/IBaseStateRegistry.sol | 8 ++++---- src/interfaces/IBroadcastAmbImplementation.sol | 4 ++-- src/interfaces/ICoreStateRegistry.sol | 5 ++++- src/interfaces/IDstSwapper.sol | 8 ++++++-- src/interfaces/IEmergencyQueue.sol | 4 +++- src/interfaces/IPayMaster.sol | 4 ++-- src/interfaces/IPaymentHelper.sol | 2 +- src/interfaces/IQuorumManager.sol | 2 +- src/interfaces/ISuperPositions.sol | 4 ++-- src/interfaces/ISuperRegistry.sol | 8 ++++---- src/interfaces/ISuperformFactory.sol | 2 +- .../adapters/LayerzeroImplementation.t.sol | 2 +- 19 files changed, 52 insertions(+), 40 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 2e94b5ec6..2debbabac 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -300,9 +300,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev handles same-chain single vault withdraw function _singleDirectSingleVaultWithdraw(SingleDirectSingleVaultStateReq memory req_) internal virtual { - ActionLocalVars memory vars; - vars.srcChainId = CHAIN_ID; - /// @dev validate Superform data if ( !_validateSuperformData( @@ -310,7 +307,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippage, req_.superformData.amount, req_.superformData.receiverAddress, - vars.srcChainId, + CHAIN_ID, false, ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))) ) diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index f8e32198c..96d2a8ded 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -41,8 +41,8 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { // EVENTS // ////////////////////////////////////////////////////////////// - event MailboxAdded(address _newMailbox); - event GasPayMasterAdded(address _igp); + event MailboxAdded(address indexed _newMailbox); + event GasPayMasterAdded(address indexed _igp); ////////////////////////////////////////////////////////////// // MODIFIERS // diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index b759a7eb5..d656f62a5 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -41,9 +41,9 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio // EVENTS // ////////////////////////////////////////////////////////////// - event EndpointUpdated(address oldEndpoint_, address newEndpoint_); - event MessageFailed(uint16 srcChainId_, bytes srcAddress_, uint64 nonce_, bytes payload_); - event SetTrustedRemote(uint16 srcChainId_, bytes srcAddress_); + event EndpointUpdated(address indexed oldEndpoint_, address indexed newEndpoint_); + event MessageFailed(uint16 indexed srcChainId_, bytes indexed srcAddress_, uint64 indexed nonce_, bytes payload_); + event SetTrustedRemote(uint16 indexed srcChainId_, bytes indexed srcAddress_); ////////////////////////////////////////////////////////////// // MODIFIERS // diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 5608f4420..cc0a285c6 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -41,7 +41,7 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { ////////////////////////////////////////////////////////////// /// @dev emitted when wormhole relayer is set - event WormholeRelayerSet(address wormholeRelayer); + event WormholeRelayerSet(address indexed wormholeRelayer); ////////////////////////////////////////////////////////////// // MODIFIERS // diff --git a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol index 8098ea383..b0d544e9c 100644 --- a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol @@ -43,11 +43,11 @@ contract WormholeSRImplementation is IBroadcastAmbImplementation { ////////////////////////////////////////////////////////////// /// @dev emitted when wormhole core is set - event WormholeCoreSet(address wormholeCore); + event WormholeCoreSet(address indexed wormholeCore); /// @dev emitted when wormhole relyaer is set - event WormholeRelayerSet(address wormholeRelayer); + event WormholeRelayerSet(address indexed wormholeRelayer); /// @dev emitted when broadcast finality is set - event BroadcastFinalitySet(uint8 finality); + event BroadcastFinalitySet(uint8 indexed finality); ////////////////////////////////////////////////////////////// // MODIFIERS // diff --git a/src/interfaces/IAmbImplementation.sol b/src/interfaces/IAmbImplementation.sol index 006bbe015..bd56af57a 100644 --- a/src/interfaces/IAmbImplementation.sol +++ b/src/interfaces/IAmbImplementation.sol @@ -9,8 +9,8 @@ interface IAmbImplementation { // EVENTS // ////////////////////////////////////////////////////////////// - event ChainAdded(uint64 superChainId); - event AuthorizedImplAdded(uint64 superChainId, address authImpl); + event ChainAdded(uint64 indexed superChainId); + event AuthorizedImplAdded(uint64 indexed superChainId, address indexed authImpl); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/IBaseForm.sol b/src/interfaces/IBaseForm.sol index ee34f726e..2382005b0 100644 --- a/src/interfaces/IBaseForm.sol +++ b/src/interfaces/IBaseForm.sol @@ -14,13 +14,19 @@ interface IBaseForm is IERC165 { ////////////////////////////////////////////////////////////// /// @dev is emitted when a new vault is added by the admin. - event VaultAdded(uint256 id, IERC4626 vault); + event VaultAdded(uint256 indexed id, IERC4626 indexed vault); /// @dev is emitted when a payload is processed by the destination contract. - event Processed(uint64 srcChainID, uint64 dstChainId, uint256 srcPayloadId, uint256 amount, address vault); + event Processed( + uint64 indexed srcChainID, + uint64 indexed dstChainId, + uint256 indexed srcPayloadId, + uint256 amount, + address vault + ); /// @dev is emitted when an emergency withdrawal is processed - event EmergencyWithdrawalProcessed(address refundAddress, uint256 amount); + event EmergencyWithdrawalProcessed(address indexed refundAddress, uint256 indexed amount); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/IBaseStateRegistry.sol b/src/interfaces/IBaseStateRegistry.sol index 34b73c572..49b79bae2 100644 --- a/src/interfaces/IBaseStateRegistry.sol +++ b/src/interfaces/IBaseStateRegistry.sol @@ -12,17 +12,17 @@ interface IBaseStateRegistry { ////////////////////////////////////////////////////////////// /// @dev is emitted when a cross-chain payload is received in the state registry - event PayloadReceived(uint64 srcChainId, uint64 dstChainId, uint256 payloadId); + event PayloadReceived(uint64 indexed srcChainId, uint64 indexed dstChainId, uint256 indexed payloadId); /// @dev is emitted when a cross-chain proof is received in the state registry /// NOTE: comes handy if quorum required is more than 0 - event ProofReceived(bytes proof); + event ProofReceived(bytes indexed proof); /// @dev is emitted when a payload id gets updated - event PayloadUpdated(uint256 payloadId); + event PayloadUpdated(uint256 indexed payloadId); /// @dev is emitted when a payload id gets processed - event PayloadProcessed(uint256 payloadId); + event PayloadProcessed(uint256 indexed payloadId); /// @dev is emitted when the super registry address is updated event SuperRegistryUpdated(address indexed superRegistry); diff --git a/src/interfaces/IBroadcastAmbImplementation.sol b/src/interfaces/IBroadcastAmbImplementation.sol index 72eb463cf..d9a3b1507 100644 --- a/src/interfaces/IBroadcastAmbImplementation.sol +++ b/src/interfaces/IBroadcastAmbImplementation.sol @@ -9,8 +9,8 @@ interface IBroadcastAmbImplementation { // EVENTS // ////////////////////////////////////////////////////////////// - event ChainAdded(uint64 superChainId); - event AuthorizedImplAdded(uint64 superChainId, address authImpl); + event ChainAdded(uint64 indexed superChainId); + event AuthorizedImplAdded(uint64 indexed superChainId, address indexed authImpl); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/ICoreStateRegistry.sol b/src/interfaces/ICoreStateRegistry.sol index 7a9fb3781..9f717c777 100644 --- a/src/interfaces/ICoreStateRegistry.sol +++ b/src/interfaces/ICoreStateRegistry.sol @@ -33,7 +33,10 @@ interface ICoreStateRegistry { /// @dev is emitted when a rescue is proposed for failed deposits in a payload event RescueProposed( - uint256 indexed payloadId, uint256[] superformIds, uint256[] proposedAmount, uint256 proposedTime + uint256 indexed payloadId, + uint256[] indexed superformIds, + uint256[] indexed proposedAmount, + uint256 proposedTime ); /// @dev is emitted when an user disputed his refund amounts diff --git a/src/interfaces/IDstSwapper.sol b/src/interfaces/IDstSwapper.sol index faba85946..f4406938f 100644 --- a/src/interfaces/IDstSwapper.sol +++ b/src/interfaces/IDstSwapper.sol @@ -23,10 +23,14 @@ interface IDstSwapper { event SuperRegistryUpdated(address indexed superRegistry); /// @dev is emitted when a dst swap transaction is processed - event SwapProcessed(uint256 payloadId, uint256 index, uint256 bridgeId, uint256 finalAmount); + event SwapProcessed( + uint256 indexed payloadId, uint256 indexed index, uint256 indexed bridgeId, uint256 finalAmount + ); /// @dev is emitted when a dst swap fails and intermediary tokens are sent to CoreStateRegistry for rescue - event SwapFailed(uint256 payloadId, uint256 index, address intermediaryToken, uint256 amount); + event SwapFailed( + uint256 indexed payloadId, uint256 indexed index, address indexed intermediaryToken, uint256 amount + ); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/IEmergencyQueue.sol b/src/interfaces/IEmergencyQueue.sol index 6892ae626..1d3dd460e 100644 --- a/src/interfaces/IEmergencyQueue.sol +++ b/src/interfaces/IEmergencyQueue.sol @@ -17,7 +17,9 @@ interface IEmergencyQueue { uint256 srcPayloadId ); - event WithdrawalProcessed(address indexed refundAddress, uint256 indexed id, uint256 superformId, uint256 amount); + event WithdrawalProcessed( + address indexed refundAddress, uint256 indexed id, uint256 indexed superformId, uint256 amount + ); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/IPayMaster.sol b/src/interfaces/IPayMaster.sol index 743229ce7..65d8baab9 100644 --- a/src/interfaces/IPayMaster.sol +++ b/src/interfaces/IPayMaster.sol @@ -12,10 +12,10 @@ interface IPayMaster { ////////////////////////////////////////////////////////////// /// @dev is emitted when a new payment is made - event Payment(address indexed user, uint256 amount); + event Payment(address indexed user, uint256 indexed amount); /// @dev is emitted when payments are moved out of collector - event PaymentWithdrawn(address indexed receiver, uint256 amount); + event PaymentWithdrawn(address indexed receiver, uint256 indexed amount); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // diff --git a/src/interfaces/IPaymentHelper.sol b/src/interfaces/IPaymentHelper.sol index 67dec6ea8..4a2363401 100644 --- a/src/interfaces/IPaymentHelper.sol +++ b/src/interfaces/IPaymentHelper.sol @@ -47,7 +47,7 @@ interface IPaymentHelper { // EVENTS // ////////////////////////////////////////////////////////////// - event ChainConfigUpdated(uint64 chainId_, uint256 configType_, bytes config_); + event ChainConfigUpdated(uint64 indexed chainId_, uint256 indexed configType_, bytes indexed config_); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/IQuorumManager.sol b/src/interfaces/IQuorumManager.sol index aa5e0d6db..53a6460c1 100644 --- a/src/interfaces/IQuorumManager.sol +++ b/src/interfaces/IQuorumManager.sol @@ -9,7 +9,7 @@ interface IQuorumManager { /// @dev emitted when a new quorum is set for a specific chain /// @param srcChainId the chain id from which the message (payload) is sent /// @param quorum the minimum number of message bridges required for processing - event QuorumSet(uint64 indexed srcChainId, uint256 quorum); + event QuorumSet(uint64 indexed srcChainId, uint256 indexed quorum); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/ISuperPositions.sol b/src/interfaces/ISuperPositions.sol index d7855a453..3ac0499c8 100644 --- a/src/interfaces/ISuperPositions.sol +++ b/src/interfaces/ISuperPositions.sol @@ -13,10 +13,10 @@ interface ISuperPositions is IERC1155A { ////////////////////////////////////////////////////////////// /// @dev is emitted when a dynamic uri is updated - event DynamicURIUpdated(string oldURI, string newURI, bool frozen); + event DynamicURIUpdated(string indexed oldURI, string indexed newURI, bool indexed frozen); /// @dev is emitted when a cross-chain transaction is completed. - event Completed(uint256 txId); + event Completed(uint256 indexed txId); /// @dev is emitted when a aErc20 token is registered event AERC20TokenRegistered(uint256 indexed tokenId, address indexed tokenAddress); diff --git a/src/interfaces/ISuperRegistry.sol b/src/interfaces/ISuperRegistry.sol index a082b05c5..0f57546ed 100644 --- a/src/interfaces/ISuperRegistry.sol +++ b/src/interfaces/ISuperRegistry.sol @@ -24,16 +24,16 @@ interface ISuperRegistry { event SetBridgeValidator(uint256 indexed bridgeId, address indexed bridgeValidator); /// @dev is emitted when a new amb is configured. - event SetAmbAddress(uint8 ambId_, address ambAddress_, bool isBroadcastAMB_); + event SetAmbAddress(uint8 indexed ambId_, address indexed ambAddress_, bool indexed isBroadcastAMB_); /// @dev is emitted when a new state registry is configured. - event SetStateRegistryAddress(uint8 registryId_, address registryAddress_); + event SetStateRegistryAddress(uint8 indexed registryId_, address indexed registryAddress_); /// @dev is emitted when a new delay is configured. - event SetDelay(uint256 oldDelay_, uint256 newDelay_); + event SetDelay(uint256 indexed oldDelay_, uint256 indexed newDelay_); /// @dev is emitted when a new vault limit is configured - event SetVaultLimitPerDestination(uint64 chainId_, uint256 vaultLimit_); + event SetVaultLimitPerDestination(uint64 indexed chainId_, uint256 indexed vaultLimit_); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/interfaces/ISuperformFactory.sol b/src/interfaces/ISuperformFactory.sol index aa0479c9f..deab36a42 100644 --- a/src/interfaces/ISuperformFactory.sol +++ b/src/interfaces/ISuperformFactory.sol @@ -39,7 +39,7 @@ interface ISuperformFactory { /// @dev emitted when a form implementation is paused /// @param formImplementationId is the id of the form implementation /// @param paused is the new paused status - event FormImplementationPaused(uint256 indexed formImplementationId, PauseStatus paused); + event FormImplementationPaused(uint256 indexed formImplementationId, PauseStatus indexed paused); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol index 417612ece..b1f755ebd 100644 --- a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol @@ -21,7 +21,7 @@ contract LayerzeroImplementationTest is BaseSetup { event UaSendVersionSet(address ua, uint16 version); event UaReceiveVersionSet(address ua, uint16 version); event UaForceResumeReceive(uint16 chainId, bytes srcAddress); - event PayloadReceived(uint64 srcChainId, uint64 dstChainId, uint256 payloadId); + event PayloadReceived(uint64 indexed srcChainId, uint64 indexed dstChainId, uint256 indexed payloadId); address public constant LZ_ENDPOINT_ETH = 0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675; address public constant LZ_ENDPOINT_OP = 0x3c2269811836af69497E5F486A85D7316753cf62; From 6515742865f6fc1a0f999816965bb831313df96e Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:50:26 +0000 Subject: [PATCH 067/210] feat: add explicit check --- src/forms/ERC4626FormImplementation.sol | 4 ++++ src/forms/ERC4626TimelockForm.sol | 3 +++ src/libraries/Error.sol | 3 +++ 3 files changed, 10 insertions(+) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index a8cf07649..d94c52821 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -296,6 +296,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev redeem the underlying dstAmount = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); + if (dstAmount == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + if (v.len1 != 0) { /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same /// as the vault asset @@ -364,6 +366,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev redeem vault positions (we operate only on positions, not assets) dstAmount = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + if (dstAmount == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + if (len != 0) { /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same /// as the vault asset diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 6f1e3e852..556402f01 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -90,6 +90,9 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { vars.receiver = vars.len1 == 0 ? p_.data.receiverAddress : address(this); dstAmount = v.redeem(p_.data.amount, vars.receiver, address(this)); + + if (dstAmount == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + /// @dev validate and dispatches the tokens if (vars.len1 != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(vars.liqData.bridgeId); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 6cfe69c73..ec2a2d46e 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -347,6 +347,9 @@ library Error { /// @dev thrown in forms where a certain functionality is not allowed or implemented error NOT_IMPLEMENTED(); + /// @dev thrown when redeeming from vault yields zero collateral + error WITHDRAW_ZERO_COLLATERAL(); + /*/////////////////////////////////////////////////////////////// PAYMASTER ERRORS //////////////////////////////////////////////////////////////*/ From 2568769c4e6e0d2aa86b3cdfd5aebcf524803247 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:44:52 +0000 Subject: [PATCH 068/210] fix: revert abi encode add registry id check --- src/SuperPositions.sol | 5 ++--- src/libraries/Error.sol | 3 +++ src/settings/SuperRegistry.sol | 1 + test/unit/super-positions/super-positions.t.sol | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index 41a376a09..9f9fa606c 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -347,9 +347,8 @@ contract SuperPositions is ISuperPositions, ERC1155A { } (address superform,,) = id.getSuperform(); - string memory name = - string(abi.encode("SuperPositions AERC20 ", IBaseForm(superform).superformYieldTokenName())); - string memory symbol = string(abi.encode("aERC20-", IBaseForm(superform).superformYieldTokenSymbol())); + string memory name = string.concat("SuperPositions AERC20 ", IBaseForm(superform).superformYieldTokenName()); + string memory symbol = string.concat("aERC20-", IBaseForm(superform).superformYieldTokenSymbol()); uint8 decimal = uint8(IBaseForm(superform).getVaultDecimals()); aErc20Token = address(new aERC20(name, symbol, decimal)); /// @dev broadcast and deploy to the other destination chains diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..3fad664cc 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -344,6 +344,9 @@ library Error { /// @dev thrown in forms where a certain functionality is not allowed or implemented error NOT_IMPLEMENTED(); + /// @dev thrown if a state registry id is 0 + error INVALID_REGISTRY_ID(); + /*/////////////////////////////////////////////////////////////// PAYMASTER ERRORS //////////////////////////////////////////////////////////////*/ diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 158bf0fa6..c1b7fff0b 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -167,6 +167,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { /// @inheritdoc ISuperRegistry function getStateRegistryId(address registryAddress_) external view override returns (uint8 registryId_) { registryId_ = stateRegistryIds[registryAddress_]; + if (registryId_ == 0) revert Error.INVALID_REGISTRY_ID(); } /// @inheritdoc ISuperRegistry diff --git a/test/unit/super-positions/super-positions.t.sol b/test/unit/super-positions/super-positions.t.sol index a593b5d52..38c2f725d 100644 --- a/test/unit/super-positions/super-positions.t.sol +++ b/test/unit/super-positions/super-positions.t.sol @@ -87,14 +87,14 @@ contract SuperPositionsTest is BaseSetup { superPositions.stateSync(maliciousMessage); } - function test_revert_stateSync_NotMinterStateRegistry() public { + function test_revert_stateSync_INVALID_REGISTRY_ID() public { uint256 txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0), ETH); ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, 1, 100); AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); vm.broadcast(getContract(ETH, "SuperformRouter")); - vm.expectRevert(Error.NOT_MINTER_STATE_REGISTRY_ROLE.selector); + vm.expectRevert(Error.INVALID_REGISTRY_ID.selector); superPositions.stateSync(maliciousMessage); } From 848396930efa3fea8eec100d60b543d20f5de07e Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 15 Dec 2023 18:14:10 +0000 Subject: [PATCH 069/210] fix: tests, amend a comment --- src/crosschain-liquidity/DstSwapper.sol | 13 ++----- .../superform-router/SuperformRouter.t.sol | 35 +++++++++---------- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 606e0c592..23f963465 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -170,7 +170,6 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { onlySwapper nonReentrant { - uint256 len = indices_.length; if (len != bridgeIds_.length || len != txData_.length) { revert Error.ARRAY_LENGTH_MISMATCH(); @@ -185,7 +184,6 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { InitMultiVaultData memory data = abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitMultiVaultData)); - for (uint256 i; i < len; ++i) { _processTx( payloadId_, indices_[i], bridgeIds_[i], txData_[i], data.liqData[i].interimToken, coreStateRegistry @@ -351,19 +349,12 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { v.balanceDiff = v.balanceAfter - v.balanceBefore; - /// @dev if actual underlying is less than expAmount adjusted - /// with maxSlippage, invariant breaks - /// @notice that unlike in CoreStateRegistry slippage check inside updateDeposit, in here we don't check for - /// negative slippage - /// @notice this essentially allows any amount to be swapped, (the invariant will still break if the amount is - /// too low) - /// @notice this doesn't mean that the keeper or the user can swap any amount, because of the 2nd slippage check - /// in CoreStateRegistry + /// @dev if actual underlying is less than expAmount adjusted with maxSlippage, invariant breaks if (v.balanceDiff < ((v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) / ENTIRE_SLIPPAGE)) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); } - /// @dev updates swapped amount adjusting for + /// @dev updates swapped amount adjusting for /// @notice in this check, we check if there is negative slippage, for which case, the user is capped to receive /// the v.expAmount of tokens (originally defined) if (v.balanceDiff > v.expAmount) { diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 98afd6120..0712c6113 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -2220,28 +2220,27 @@ contract SuperformRouterTest is ProtocolActions { assertEq(MockERC20(getContract(ARBI, "DAI")).balanceOf(getContract(ARBI, "DstSwapper")), 1e18); } - function test_negativeDstSwapSlippageAndUpdateSwappedAmount() public { - /// case: where bridge 3 DAI, dst swapper swapped 3 DAI, updater updates 3 DAI - /// outcome: deposit goes through depositing 2 DAI and 1 DAI remains on CSR - uint256 superformId = _simulateXChainDepositWithNegativeSlippage(true, true, true); - - /// @dev assert that the minted amount is the amount sent in superformData.amount - vm.selectFork(FORKS[ETH]); - assertEq(SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(address(420), superformId), 2e18); + function test_negativeDstSwapSlippageAndUpdateSwappedAmount_RevertsInvalidKeeperCall() public { + /// case: where bridge 3 DAI, dst swapper swapped 3 DAI (capped to 2) updater updates 3 DAI + /// outcome: deposit should revert on update + _simulateXChainDepositWithNegativeSlippage(true, true, true); - /// @dev swapped tokens live on CSR + /// @dev swapped tokens remain on DstSwapper vm.selectFork(FORKS[ARBI]); - assertEq(MockERC20(getContract(ARBI, "DAI")).balanceOf(getContract(ARBI, "CoreStateRegistry")), 1e18); + assertEq(MockERC20(getContract(ARBI, "DAI")).balanceOf(getContract(ARBI, "CoreStateRegistry")), 3e18); } function test_negativeDstSwapSlippageAndUpdateSuperformDataAmount() public { - /// case: where bridge 3 DAI, dst swapper swapped 3 DAI, updater updates 2 DAI - /// outcome: deposit should revert on update - _simulateXChainDepositWithNegativeSlippage(true, true, false); + /// keeperUpdateExactAmount = false means keeper will update with the capped amount (2 DAI) + uint256 superformId = _simulateXChainDepositWithNegativeSlippage(true, true, false); - /// @dev swapped tokens live on CSR forever + /// @dev assert that the minted amount is the amount sent in superformData.amount + vm.selectFork(FORKS[ETH]); + assertEq(SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(address(420), superformId), 2e18); + + /// @dev swapped tokens (remainder of negative slippage) remain on dstSwapper vm.selectFork(FORKS[ARBI]); - assertEq(MockERC20(getContract(ARBI, "DAI")).balanceOf(getContract(ARBI, "CoreStateRegistry")), 3e18); + assertEq(MockERC20(getContract(ARBI, "DAI")).balanceOf(getContract(ARBI, "CoreStateRegistry")), 1e18); } struct SimulateUpdateTestLocalVars { @@ -2356,9 +2355,9 @@ contract SuperformRouterTest is ProtocolActions { vm.startPrank(deployer); v.amounts = new uint256[](1); - v.amounts[0] = keeperUpdateExactAmount ? 3e18 : 2e18; + v.amounts[0] = keeperUpdateExactAmount ? 3e18 : 2e18; // false -± 2e18 - v.swapAmount = swapperSwapExactBridgeAmount ? 3e18 : 2e18; + v.swapAmount = swapperSwapExactBridgeAmount ? 3e18 : 2e18; // true -± 3e18 if (hasDstSwap) { DstSwapper(payable(getContract(ARBI, "DstSwapper"))).processTx( @@ -2377,7 +2376,7 @@ contract SuperformRouterTest is ProtocolActions { ); } - if (hasDstSwap && !keeperUpdateExactAmount && swapperSwapExactBridgeAmount) { + if (hasDstSwap && keeperUpdateExactAmount && swapperSwapExactBridgeAmount) { vm.expectRevert(Error.INVALID_DST_SWAPPER_FAILED_SWAP.selector); CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload(1, v.amounts); } else { From 73e48c1dd912cb0c3acd988cf72f8b07a61ec8c1 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 15 Dec 2023 15:50:50 -0500 Subject: [PATCH 070/210] chore: fix typo --- src/BaseRouterImplementation.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 1ddedbf7b..e360325f9 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -791,7 +791,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev amount can't be 0 if (amount_ == 0) return false; - /// @dev redudant check on same chain, but helpful on xchain actions to halt deposits earlier + /// @dev redundant check on same chain, but helpful on xchain actions to halt deposits earlier if (isDeposit_ && factory_.isFormImplementationPaused(formImplementationId)) return false; /// @dev ensure that receiver address is set always From eef812ce97b694aa67c5f5c57498578cd310ecf6 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:45:39 -0500 Subject: [PATCH 071/210] chore: low fixes --- src/crosschain-data/extensions/CoreStateRegistry.sol | 2 +- src/libraries/ArrayCastLib.sol | 4 ++-- src/libraries/Error.sol | 6 +++--- src/payments/PaymentHelper.sol | 9 +++++---- test/unit/libraries/ArrayCastLib.t.sol | 5 ++++- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 4ca8a3fe8..535ba9d59 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -285,7 +285,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev the timelock is elapsed if ( failedDeposits_.lastProposedTimestamp == 0 - || block.timestamp < failedDeposits_.lastProposedTimestamp + _getDelay() + || block.timestamp <= failedDeposits_.lastProposedTimestamp + _getDelay() ) { revert Error.RESCUE_LOCKED(); } diff --git a/src/libraries/ArrayCastLib.sol b/src/libraries/ArrayCastLib.sol index bdcf9c118..e22427d83 100644 --- a/src/libraries/ArrayCastLib.sol +++ b/src/libraries/ArrayCastLib.sol @@ -41,8 +41,8 @@ library ArrayCastLib { amounts, maxSlippage, liqData, - new bool[](superformIds.length), - new bool[](superformIds.length), + castBoolToArray(data_.hasDstSwap), + castBoolToArray(data_.retain4626), data_.receiverAddress, data_.extraFormData ); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 6cfe69c73..1822b5b65 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -215,9 +215,6 @@ library Error { /// @dev thrown if payload is being updated with tx data length different than liq data length error DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH(); - /// @dev thrown if a duplicate proof amb is found - error DUPLICATE_PROOF_BRIDGE_ID(); - /// @dev thrown if broadcast finality for wormhole is invalid error INVALID_BROADCAST_FINALITY(); @@ -233,6 +230,9 @@ library Error { /// @dev thrown if message amb and proof amb are the same error INVALID_PROOF_BRIDGE_ID(); + /// @dev thrown if order of proof AMBs is incorrect, either duplicated or not incrementing + error INVALID_PROOF_BRIDGE_IDS(); + /// @dev thrown if rescue data lengths are invalid error INVALID_RESCUE_DATA(); diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index fb111386c..b2ff4bd81 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -35,6 +35,7 @@ contract PaymentHelper is IPaymentHelper { ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; uint32 private constant TIMELOCK_FORM_ID = 2; + uint256 private constant MAX_UINT256 = type(uint256).max; ////////////////////////////////////////////////////////////// // STATE VARIABLES // @@ -627,7 +628,7 @@ contract PaymentHelper is IPaymentHelper { AMBMessage memory ambIdEncodedMessage = abi.decode(message_, (AMBMessage)); ambIdEncodedMessage.params = abi.encode(ambIds_, ambIdEncodedMessage.params); - bytes memory proof_ = abi.encode(AMBMessage(type(uint256).max, abi.encode(keccak256(message_)))); + bytes memory proof_ = abi.encode(AMBMessage(MAX_UINT256, abi.encode(keccak256(message_)))); /// @dev just checks the estimate for sending message from src -> dst /// @dev only ambIds_[0] = primary amb (rest of the ambs send only the proof) @@ -661,7 +662,7 @@ contract PaymentHelper is IPaymentHelper { feeSplitUp = new uint256[](len); - bytes memory proof_ = abi.encode(AMBMessage(type(uint256).max, abi.encode(keccak256(message_)))); + bytes memory proof_ = abi.encode(AMBMessage(MAX_UINT256, abi.encode(keccak256(message_)))); /// @dev just checks the estimate for sending message from src -> dst for (uint256 i; i < len; ++i) { @@ -760,7 +761,7 @@ contract PaymentHelper is IPaymentHelper { sfData_.extraFormData ) ); - message_ = abi.encode(AMBMessage(type(uint256).max, ambData)); + message_ = abi.encode(AMBMessage(MAX_UINT256, ambData)); } /// @dev generates the amb message for multi vault data @@ -782,7 +783,7 @@ contract PaymentHelper is IPaymentHelper { sfData_.extraFormData ) ); - message_ = abi.encode(AMBMessage(type(uint256).max, ambData)); + message_ = abi.encode(AMBMessage(MAX_UINT256, ambData)); } /// @dev helps convert the dst gas fee into src chain native fee diff --git a/test/unit/libraries/ArrayCastLib.t.sol b/test/unit/libraries/ArrayCastLib.t.sol index ed6de2662..56e5a5635 100644 --- a/test/unit/libraries/ArrayCastLib.t.sol +++ b/test/unit/libraries/ArrayCastLib.t.sol @@ -46,9 +46,12 @@ contract ArrayCastLibTest is Test { function test_castToMultiVaultData() external { InitSingleVaultData memory data = InitSingleVaultData( - 1, 1, 1e18, 100, LiqRequest(bytes(""), address(0), address(0), 1, 1, 0), false, false, address(0), "" + 1, 1, 1e18, 100, LiqRequest(bytes(""), address(0), address(0), 1, 1, 0), true, true, address(0), "" ); InitMultiVaultData memory castedValue = arrayCastLib.castToMultiVaultData(data); assertEq(castedValue.superformIds.length, 1); + + assertEq(castedValue.hasDstSwaps[0], data.hasDstSwap); + assertEq(castedValue.retain4626s[0], data.retain4626); } } From b93ec97400022aeddef6f2364982dc36db517cee Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:50:27 -0500 Subject: [PATCH 072/210] chore: error --- src/crosschain-data/BaseStateRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crosschain-data/BaseStateRegistry.sol b/src/crosschain-data/BaseStateRegistry.sol index 31dfe8b98..a1a19930e 100644 --- a/src/crosschain-data/BaseStateRegistry.sol +++ b/src/crosschain-data/BaseStateRegistry.sol @@ -175,7 +175,7 @@ abstract contract BaseStateRegistry is IBaseStateRegistry { } if (i - 1 != 0 && ambIds_[i] <= ambIds_[i - 1]) { - revert Error.DUPLICATE_PROOF_BRIDGE_ID(); + revert Error.INVALID_PROOF_BRIDGE_IDS(); } /// @dev proof is dispatched in the form of a payload From 650c7022bb23bcd92666bac3487a4a1a80041fe3 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 15 Dec 2023 17:31:58 -0500 Subject: [PATCH 073/210] chore: tests --- test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol index 070749ae0..28c5f0d46 100644 --- a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol @@ -424,11 +424,11 @@ contract CoreStateRegistryTest is ProtocolActions { ambIds_[1] = 2; ambIds_[2] = 3; ambIds_[3] = 2; - _failingMultiDeposit(ambIds_, Error.DUPLICATE_PROOF_BRIDGE_ID.selector); + _failingMultiDeposit(ambIds_, Error.INVALID_PROOF_BRIDGE_IDS.selector); ambIds_[2] = 2; ambIds_[3] = 3; - _failingMultiDeposit(ambIds_, Error.DUPLICATE_PROOF_BRIDGE_ID.selector); + _failingMultiDeposit(ambIds_, Error.INVALID_PROOF_BRIDGE_IDS.selector); } function test_processPayload_reverts() public { From 717f3d91528667c8ef51888902097d3ffd89c982 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 15 Dec 2023 23:06:48 -0500 Subject: [PATCH 074/210] chore: medium fixes + 4626 conventions --- src/BaseForm.sol | 24 +++++----- src/BaseRouterImplementation.sol | 24 +++++----- .../extensions/CoreStateRegistry.sol | 20 ++++----- src/forms/ERC4626Form.sol | 16 +++---- src/forms/ERC4626FormImplementation.sol | 45 ++++++++++++------- src/forms/ERC4626KYCDaoForm.sol | 12 ++--- src/forms/ERC4626TimelockForm.sol | 19 ++++---- src/interfaces/IBaseForm.sol | 18 ++++---- src/libraries/Error.sol | 8 ++-- test/mocks/ERC4626FormExternal.sol | 16 +++---- .../BaseFormInterfaceNotSupported.sol | 24 +++++----- ...626ImplementationInterfaceNotSupported.sol | 28 ++++++------ .../ERC4626InterFaceNotSupported.sol | 16 +++---- 13 files changed, 142 insertions(+), 128 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index f365de3f6..568ff7c09 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -180,9 +180,9 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { override onlySuperRouter notPaused(singleVaultData_) - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _directDepositIntoVault(singleVaultData_, srcSender_); + shares = _directDepositIntoVault(singleVaultData_, srcSender_); } /// @inheritdoc IBaseForm @@ -193,10 +193,10 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { external override onlySuperRouter - returns (uint256 dstAmount) + returns (uint256 assets) { if (!_isPaused(singleVaultData_.superformId)) { - dstAmount = _directWithdrawFromVault(singleVaultData_, srcSender_); + assets = _directWithdrawFromVault(singleVaultData_, srcSender_); } else { IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( singleVaultData_, srcSender_ @@ -214,9 +214,9 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { override onlyCoreStateRegistry notPaused(singleVaultData_) - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_); + shares = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_); } /// @inheritdoc IBaseForm @@ -228,10 +228,10 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { external override onlyCoreStateRegistry - returns (uint256 dstAmount) + returns (uint256 assets) { if (!_isPaused(singleVaultData_.superformId)) { - dstAmount = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); + assets = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); } else { IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( singleVaultData_, srcSender_ @@ -268,7 +268,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount); + returns (uint256 shares); /// @dev Deposits underlying tokens into a vault function _xChainDepositIntoVault( @@ -278,7 +278,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount); + returns (uint256 shares); /// @dev Withdraws underlying tokens from a vault function _directWithdrawFromVault( @@ -287,7 +287,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount_); + returns (uint256 assets); /// @dev Withdraws underlying tokens from a vault function _xChainWithdrawFromVault( @@ -297,7 +297,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount); + returns (uint256 assets); /// @dev withdraws vault shares from form during emergency function _emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) internal virtual; diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 2e94b5ec6..e1350b4f6 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -48,7 +48,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou struct MultiDepositLocalVars { uint256 len; address[] superforms; - uint256[] dstAmounts; + uint256[] shares; bool[] mints; } @@ -566,10 +566,10 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ) internal virtual - returns (uint256 dstAmount) + returns (uint256 shares) { /// @dev deposits token to a given vault and mint vault positions directly through the form - dstAmount = IBaseForm(superform_).directDepositIntoVault{ value: msgValue_ }( + shares = IBaseForm(superform_).directDepositIntoVault{ value: msgValue_ }( InitSingleVaultData( payloadId_, superformId_, @@ -597,7 +597,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou virtual { address superform; - uint256 dstAmount; + uint256 shares; /// @dev decode superforms (superform,,) = vaultData_.superformId.getSuperform(); @@ -605,7 +605,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou _singleVaultTokenForward(srcSender_, superform, permit2data_, vaultData_, false); /// @dev deposits token to a given vault and mint vault positions. - dstAmount = _directDeposit( + shares = _directDeposit( superform, vaultData_.payloadId, vaultData_.superformId, @@ -619,10 +619,10 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou srcSender_ ); - if (dstAmount != 0 && !vaultData_.retain4626) { + if (shares != 0 && !vaultData_.retain4626) { /// @dev mint super positions at the end of the deposit action if user doesn't retain 4626 ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintSingle( - srcSender_, vaultData_.superformId, dstAmount + srcSender_, vaultData_.superformId, shares ); } } @@ -641,7 +641,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou v.len = vaultData_.superformIds.length; v.superforms = new address[](v.len); - v.dstAmounts = new uint256[](v.len); + v.shares = new uint256[](v.len); /// @dev decode superforms v.superforms = DataLib.getSuperforms(vaultData_.superformIds); @@ -650,7 +650,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou for (uint256 i; i < v.len; ++i) { /// @dev deposits token to a given vault and mint vault positions. - v.dstAmounts[i] = _directDeposit( + v.shares[i] = _directDeposit( v.superforms[i], vaultData_.payloadId, vaultData_.superformIds[i], @@ -665,14 +665,14 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); /// @dev if retain4626 is set to True, set the amount of SuperPositions to mint to 0 - if (v.dstAmounts[i] != 0 && vaultData_.retain4626s[i]) { - v.dstAmounts[i] = 0; + if (v.shares[i] != 0 && vaultData_.retain4626s[i]) { + v.shares[i] = 0; } } /// @dev in direct deposits, SuperPositions are minted right after depositing to vaults ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintBatch( - srcSender_, vaultData_.superformIds, v.dstAmounts + srcSender_, vaultData_.superformIds, v.shares ); } diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 4ca8a3fe8..fd11a4be7 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -797,11 +797,11 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { }), srcSender_, srcChainId_ - ) returns (uint256 dstAmount) { - if (dstAmount != 0 && !multiVaultData.retain4626s[i]) { + ) returns (uint256 shares) { + if (shares != 0 && !multiVaultData.retain4626s[i]) { fulfilment = true; /// @dev marks the indexes that require a callback mint of shares (successful) - multiVaultData.amounts[i] = dstAmount; + multiVaultData.amounts[i] = shares; } else { multiVaultData.amounts[i] = 0; } @@ -827,6 +827,10 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { } } + if (errors) { + emit FailedXChainDeposits(payloadId_); + } + /// @dev issue superPositions if at least one vault deposit passed if (fulfilment) { return _multiReturnData( @@ -839,10 +843,6 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { ); } - if (errors) { - emit FailedXChainDeposits(payloadId_); - } - return ""; } @@ -902,16 +902,16 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev deposit to superform try IBaseForm(superform_).xChainDepositIntoVault(singleVaultData, srcSender_, srcChainId_) returns ( - uint256 dstAmount + uint256 shares ) { - if (dstAmount != 0 && !singleVaultData.retain4626) { + if (shares != 0 && !singleVaultData.retain4626) { return _singleReturnData( srcSender_, singleVaultData.payloadId, TransactionType.DEPOSIT, CallbackType.RETURN, singleVaultData.superformId, - dstAmount + shares ); } } catch { diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index 1b62df457..8d74e51cf 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -31,9 +31,9 @@ contract ERC4626Form is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processDirectDeposit(singleVaultData_); + shares = _processDirectDeposit(singleVaultData_); } /// @inheritdoc BaseForm @@ -44,9 +44,9 @@ contract ERC4626Form is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processXChainDeposit(singleVaultData_, srcChainId_); + shares = _processXChainDeposit(singleVaultData_, srcChainId_); } /// @inheritdoc BaseForm @@ -56,9 +56,9 @@ contract ERC4626Form is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _processDirectWithdraw(singleVaultData_, srcSender_); + assets = _processDirectWithdraw(singleVaultData_, srcSender_); } /// @inheritdoc BaseForm @@ -69,9 +69,9 @@ contract ERC4626Form is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); + assets = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); } /// @inheritdoc BaseForm diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index a8cf07649..5c74d44b5 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -33,7 +33,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { uint64 chainId; address asset; address bridgeValidator; - uint256 dstAmount; + uint256 shares; uint256 balanceBefore; uint256 assetDifference; uint256 nonce; @@ -153,7 +153,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// - function _processDirectDeposit(InitSingleVaultData memory singleVaultData_) internal returns (uint256 dstAmount) { + function _processDirectDeposit(InitSingleVaultData memory singleVaultData_) internal returns (uint256 shares) { directDepositLocalVars memory vars; IERC4626 v = IERC4626(vault); @@ -237,9 +237,16 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC20(vars.asset).safeIncreaseAllowance(vault, vars.assetDifference); if (singleVaultData_.retain4626) { - dstAmount = v.deposit(vars.assetDifference, singleVaultData_.receiverAddress); + shares = v.deposit(vars.assetDifference, singleVaultData_.receiverAddress); } else { - dstAmount = v.deposit(vars.assetDifference, address(this)); + /// @dev This makes ERC4626Form (address(this)) owner of v.shares + /// @dev add extra validation check in minting SuperPositions to ensure accounting + uint256 sharesBalanceBefore = v.balanceOf(address(this)); + shares = v.deposit(vars.assetDifference, address(this)); + uint256 sharesBalanceAfter = v.balanceOf(address(this)); + if (sharesBalanceAfter - sharesBalanceBefore != shares) { + revert Error.INVALID_OUTPUT_AMOUNT(); + } } } @@ -248,7 +255,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { uint64 srcChainId_ ) internal - returns (uint256 dstAmount) + returns (uint256 shares) { (,, uint64 dstChainId) = singleVaultData_.superformId.getSuperform(); address vaultLoc = vault; @@ -267,10 +274,16 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev Deposit into vault if (singleVaultData_.retain4626) { - dstAmount = v.deposit(singleVaultData_.amount, singleVaultData_.receiverAddress); + shares = v.deposit(singleVaultData_.amount, singleVaultData_.receiverAddress); } else { - /// This makes ERC4626Form (address(this)) owner of v.shares - dstAmount = v.deposit(singleVaultData_.amount, address(this)); + /// @dev This makes ERC4626Form (address(this)) owner of v.shares + /// @dev add extra validation check in minting SuperPositions to ensure accounting + uint256 sharesBalanceBefore = v.balanceOf(address(this)); + shares = v.deposit(singleVaultData_.amount, address(this)); + uint256 sharesBalanceAfter = v.balanceOf(address(this)); + if (sharesBalanceAfter - sharesBalanceBefore != shares) { + revert Error.INVALID_OUTPUT_AMOUNT(); + } } emit Processed(srcChainId_, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); @@ -281,7 +294,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { address srcSender_ ) internal - returns (uint256 dstAmount) + returns (uint256 assets) { directWithdrawLocalVars memory v; v.len1 = singleVaultData_.liqData.txData.length; @@ -293,8 +306,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { v.v = IERC4626(vault); v.asset = address(asset); - /// @dev redeem the underlying - dstAmount = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); + /// @dev redeem shares for assets + assets = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); if (v.len1 != 0) { /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same @@ -305,7 +318,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { v.amount = IBridgeValidator(v.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (v.amount > dstAmount) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + if (v.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); v.chainId = CHAIN_ID; @@ -340,7 +353,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { uint64 srcChainId_ ) internal - returns (uint256 dstAmount) + returns (uint256 assets) { uint256 len = singleVaultData_.liqData.txData.length; @@ -361,8 +374,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC4626 v = IERC4626(vault); vars.asset = asset; - /// @dev redeem vault positions (we operate only on positions, not assets) - dstAmount = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + /// @dev redeem shares for assets + assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); if (len != 0) { /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same @@ -373,7 +386,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > dstAmount) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); + if (vars.amount > assets) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); /// @dev validate and perform the swap to desired output token and send to beneficiary IBridgeValidator(vars.bridgeValidator).validateTxData( diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index b02c999e1..c17453a03 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -48,9 +48,9 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { internal override onlyKYC(srcSender_) - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processDirectDeposit(singleVaultData_); + shares = _processDirectDeposit(singleVaultData_); } function _xChainDepositIntoVault( @@ -61,7 +61,7 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { internal pure override - returns (uint256 /*dstAmount*/ ) + returns (uint256 /*shares*/ ) { revert Error.NOT_IMPLEMENTED(); } @@ -74,9 +74,9 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { internal override onlyKYC(srcSender_) - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _processDirectWithdraw(singleVaultData_, srcSender_); + assets = _processDirectWithdraw(singleVaultData_, srcSender_); } /// @inheritdoc BaseForm @@ -88,7 +88,7 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { internal pure override - returns (uint256 /*dstAmount*/ ) + returns (uint256 /*assets*/ ) { revert Error.NOT_IMPLEMENTED(); } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 6f1e3e852..60d2ea9c3 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -64,7 +64,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { function withdrawAfterCoolDown(TimelockPayload memory p_) external onlyTimelockStateRegistry - returns (uint256 dstAmount) + returns (uint256 assets) { if (_isPaused(p_.data.superformId)) { IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( @@ -89,14 +89,15 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @dev if the txData is empty, the tokens are sent directly to the sender, otherwise sent first to this form vars.receiver = vars.len1 == 0 ? p_.data.receiverAddress : address(this); - dstAmount = v.redeem(p_.data.amount, vars.receiver, address(this)); + assets = v.redeem(p_.data.amount, vars.receiver, address(this)); + /// @dev validate and dispatches the tokens if (vars.len1 != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(vars.liqData.bridgeId); vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(vars.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > dstAmount) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); vars.chainId = CHAIN_ID; @@ -137,9 +138,9 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { internal virtual override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processDirectDeposit(singleVaultData_); + shares = _processDirectDeposit(singleVaultData_); } /// @inheritdoc BaseForm @@ -151,15 +152,15 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { internal virtual override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processXChainDeposit(singleVaultData_, srcChainId_); + shares = _processXChainDeposit(singleVaultData_, srcChainId_); } /// @inheritdoc BaseForm /// @dev this is the step-1 for timelock form withdrawal, direct case /// @dev will mandatorily process unlock - /// @return dstAmount is always 0 + /// @return shares is always 0 function _directWithdrawFromVault( InitSingleVaultData memory singleVaultData_, address srcSender_ @@ -179,7 +180,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @inheritdoc BaseForm /// @dev this is the step-1 for timelock form withdrawal, xchain case /// @dev will mandatorily process unlock - /// @return dstAmount is always 0 + /// @return shares is always 0 function _xChainWithdrawFromVault( InitSingleVaultData memory singleVaultData_, address srcSender_, diff --git a/src/interfaces/IBaseForm.sol b/src/interfaces/IBaseForm.sol index ee34f726e..20931e28b 100644 --- a/src/interfaces/IBaseForm.sol +++ b/src/interfaces/IBaseForm.sol @@ -92,52 +92,52 @@ interface IBaseForm is IERC165 { /// @dev process same chain id deposits /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction - /// @return dstAmount The amount of tokens deposited in same chain action + /// @return shares The amount of vault shares received function directDepositIntoVault( InitSingleVaultData memory singleVaultData_, address srcSender_ ) external payable - returns (uint256 dstAmount); + returns (uint256 shares); /// @dev process same chain id deposits /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction /// @param srcChainId_ The chain id of the source chain - /// @return dstAmount The amount of tokens deposited in same chain action - /// @dev is dstAmoutn is `0` then no further action/acknowledgement needs to be sent + /// @return shares The amount of vault shares received + /// @dev is shares is `0` then no further action/acknowledgement needs to be sent function xChainDepositIntoVault( InitSingleVaultData memory singleVaultData_, address srcSender_, uint64 srcChainId_ ) external - returns (uint256 dstAmount); + returns (uint256 shares); /// @dev process withdrawal of asset from a vault /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction - /// @return dstAmount The amount of tokens withdrawn in same chain action + /// @return assets The amount of assets received function directWithdrawFromVault( InitSingleVaultData memory singleVaultData_, address srcSender_ ) external - returns (uint256 dstAmount); + returns (uint256 assets); /// @dev process withdrawal of asset from a vault /// @param singleVaultData_ A bytes representation containing all the data required to make a form action /// @param srcSender_ The address of the sender of the transaction /// @param srcChainId_ The chain id of the source chain - /// @return dstAmount The amount of tokens withdrawn + /// @return assets The amount of assets received function xChainWithdrawFromVault( InitSingleVaultData memory singleVaultData_, address srcSender_, uint64 srcChainId_ ) external - returns (uint256 dstAmount); + returns (uint256 assets); /// @dev process withdrawal of shares if form is paused /// @param srcSender_ The address of the sender of the transaction diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 6cfe69c73..358896a72 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -347,10 +347,6 @@ library Error { /// @dev thrown in forms where a certain functionality is not allowed or implemented error NOT_IMPLEMENTED(); - /*/////////////////////////////////////////////////////////////// - PAYMASTER ERRORS - //////////////////////////////////////////////////////////////*/ - /// DST SWAPPER EXECUTION ERRORS /// @dev forbid xChain deposits with destination swaps without interim token set (for user protection) error INVALID_INTERIM_TOKEN(); @@ -377,6 +373,10 @@ library Error { error INVALID_DST_SWAPPER_FAILED_SWAP_NO_NATIVE_BALANCE(); /// FORM EXECUTION ERRORS + + /// @dev thrown if shares != deposit output or assets != redeem output when minting SuperPositions + error INVALID_OUTPUT_AMOUNT(); + /// @dev thrown in KYCDAO form if no KYC token is present error NO_VALID_KYC_TOKEN(); diff --git a/test/mocks/ERC4626FormExternal.sol b/test/mocks/ERC4626FormExternal.sol index b5f5495bf..0a8de33e7 100644 --- a/test/mocks/ERC4626FormExternal.sol +++ b/test/mocks/ERC4626FormExternal.sol @@ -24,9 +24,9 @@ contract ERC4626FormExternal is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processDirectDeposit(singleVaultData_); + shares = _processDirectDeposit(singleVaultData_); } /// @inheritdoc BaseForm @@ -36,9 +36,9 @@ contract ERC4626FormExternal is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _processDirectWithdraw(singleVaultData_, srcSender_); + assets = _processDirectWithdraw(singleVaultData_, srcSender_); } /// @inheritdoc BaseForm @@ -49,9 +49,9 @@ contract ERC4626FormExternal is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processXChainDeposit(singleVaultData_, srcChainId_); + shares = _processXChainDeposit(singleVaultData_, srcChainId_); } /// @inheritdoc BaseForm @@ -62,9 +62,9 @@ contract ERC4626FormExternal is ERC4626FormImplementation { ) internal override - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); + assets = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); } /// @inheritdoc BaseForm diff --git a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol index 5ec8473a1..0b4c163b4 100644 --- a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol @@ -105,9 +105,9 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { override onlySuperRouter notPaused(singleVaultData_) - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _directDepositIntoVault(singleVaultData_, srcSender_); + shares = _directDepositIntoVault(singleVaultData_, srcSender_); } /// @inheritdoc IBaseForm @@ -119,9 +119,9 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { override onlySuperRouter notPaused(singleVaultData_) - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _directWithdrawFromVault(singleVaultData_, srcSender_); + assets = _directWithdrawFromVault(singleVaultData_, srcSender_); } /// @inheritdoc IBaseForm @@ -134,9 +134,9 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { override onlyCoreStateRegistry notPaused(singleVaultData_) - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_); + shares = _xChainDepositIntoVault(singleVaultData_, srcSender_, srcChainId_); } /// @inheritdoc IBaseForm @@ -149,9 +149,9 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { override onlyCoreStateRegistry notPaused(singleVaultData_) - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); + assets = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); } /// @inheritdoc IBaseForm @@ -236,7 +236,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount); + returns (uint256 shares); /// @dev Withdraws underlying tokens from a vault function _directWithdrawFromVault( @@ -245,7 +245,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount_); + returns (uint256 assets); /// @dev Deposits underlying tokens into a vault function _xChainDepositIntoVault( @@ -255,7 +255,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount); + returns (uint256 shares); /// @dev Withdraws underlying tokens from a vault function _xChainWithdrawFromVault( @@ -265,7 +265,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { ) internal virtual - returns (uint256 dstAmount); + returns (uint256 assets); /// @dev withdraws vault shares from form during emergency function _emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) internal virtual; diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index 6a0f5da0d..bfb69b713 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -101,7 +101,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li uint64 chainId; address asset; address bridgeValidator; - uint256 dstAmount; + uint256 shares; uint256 balanceBefore; uint256 balanceAfter; uint256 nonce; @@ -109,7 +109,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li bytes signature; } - function _processDirectDeposit(InitSingleVaultData memory singleVaultData_) internal returns (uint256 dstAmount) { + function _processDirectDeposit(InitSingleVaultData memory singleVaultData_) internal returns (uint256 shares) { directDepositLocalVars memory vars; IERC4626 v = IERC4626(vault); @@ -170,7 +170,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li /// @dev the vault asset is approved and deposited to the vault IERC20(vars.asset).safeIncreaseAllowance(vault, singleVaultData_.amount); - dstAmount = v.deposit(singleVaultData_.amount, address(this)); + shares = v.deposit(singleVaultData_.amount, address(this)); } struct ProcessDirectWithdrawLocalVars { @@ -188,7 +188,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li address srcSender ) internal - returns (uint256 dstAmount) + returns (uint256 assets) { ProcessDirectWithdrawLocalVars memory v; v.len1 = singleVaultData_.liqData.txData.length; @@ -203,15 +203,15 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li /// the vault asset if (singleVaultData_.liqData.token != v.asset) revert Error.DIRECT_WITHDRAW_INVALID_TOKEN(); - /// @dev redeem the underlying - dstAmount = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); + /// @dev redeem shares for assets + assets = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); if (v.len1 != 0) { v.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); v.amount = IBridgeValidator(v.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); /// @dev this check here might be too much already, but can't hurt - if (v.amount > dstAmount) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + if (v.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); v.chainId = uint64(block.chainid); @@ -248,7 +248,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li uint64 srcChainId ) internal - returns (uint256 dstAmount) + returns (uint256 shares) { (,, uint64 dstChainId) = singleVaultData_.superformId.getSuperform(); address vaultLoc = vault; @@ -262,7 +262,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li IERC20(v.asset()).safeIncreaseAllowance(vaultLoc, singleVaultData_.amount); /// @dev This makes ERC4626Form (address(this)) owner of v.shares - dstAmount = v.deposit(singleVaultData_.amount, address(this)); + shares = v.deposit(singleVaultData_.amount, address(this)); emit Processed(srcChainId, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); } @@ -283,7 +283,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li uint64 srcChainId ) internal - returns (uint256 dstAmount) + returns (uint256 assets) { uint256 len = singleVaultData_.liqData.txData.length; @@ -306,15 +306,15 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li /// the vault asset if (vars.asset != singleVaultData_.liqData.token) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); - /// @dev redeem vault positions (we operate only on positions, not assets) - dstAmount = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + /// @dev redeem shares for assets + assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); if (len != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > dstAmount) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); + if (vars.amount > assets) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); /// @dev validate and perform the swap to desired output token and send to beneficiary IBridgeValidator(vars.bridgeValidator).validateTxData( @@ -335,7 +335,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), singleVaultData_.liqData.txData, singleVaultData_.liqData.token, - dstAmount, + assets, singleVaultData_.liqData.nativeAmount ); } diff --git a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol index fdb609d5e..accd613a8 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol @@ -24,9 +24,9 @@ contract ERC4626FormInterfaceNotSupported is ERC4626FormImplementationInterfaceN ) internal override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processDirectDeposit(singleVaultData_); + shares = _processDirectDeposit(singleVaultData_); } /// @inheritdoc BaseForm @@ -36,9 +36,9 @@ contract ERC4626FormInterfaceNotSupported is ERC4626FormImplementationInterfaceN ) internal override - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _processDirectWithdraw(singleVaultData_, srcSender_); + assets = _processDirectWithdraw(singleVaultData_, srcSender_); } /// @inheritdoc BaseForm @@ -49,9 +49,9 @@ contract ERC4626FormInterfaceNotSupported is ERC4626FormImplementationInterfaceN ) internal override - returns (uint256 dstAmount) + returns (uint256 shares) { - dstAmount = _processXChainDeposit(singleVaultData_, srcChainId_); + shares = _processXChainDeposit(singleVaultData_, srcChainId_); } /// @inheritdoc BaseForm @@ -62,9 +62,9 @@ contract ERC4626FormInterfaceNotSupported is ERC4626FormImplementationInterfaceN ) internal override - returns (uint256 dstAmount) + returns (uint256 assets) { - dstAmount = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); + assets = _processXChainWithdraw(singleVaultData_, srcSender_, srcChainId_); } /// @inheritdoc BaseForm From 915ecd465e5be1961f9658beb9b5f1cbcfe2a23d Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Sat, 16 Dec 2023 15:52:18 +0000 Subject: [PATCH 075/210] fix: sup-4787 --- src/libraries/Error.sol | 5 ++++- src/payments/PaymentHelper.sol | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 005a60484..d8d9d5a53 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -25,6 +25,9 @@ library Error { /// @dev thrown if wormhole relayer is not set error RELAYER_NOT_SET(); + /// @dev thrown if get native token price estimate in paymentHelper is 0 + error INVALID_NATIVE_TOKEN_PRICE(); + ////////////////////////////////////////////////////////////// // AUTHORIZATION ERRORS // ////////////////////////////////////////////////////////////// @@ -118,7 +121,7 @@ library Error { /// COMMON INPUT VALIDATION ERRORS /// @dev thrown if there is an array length mismatch error ARRAY_LENGTH_MISMATCH(); - + /// @dev thrown if payload id does not exist error INVALID_PAYLOAD_ID(); diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index fb111386c..6bb44342a 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -808,6 +808,8 @@ contract PaymentHelper is IPaymentHelper { /// @dev converts the usd value to source chain's native token /// @dev native token price is 8 decimal which cancels the 8 decimal multiplied in previous step + uint256 nativeTokenPrice = _getNativeTokenPrice(CHAIN_ID); // native token price - 8 decimal + if (nativeTokenPrice == 0) revert Error.INVALID_NATIVE_TOKEN_PRICE(); nativeFee = (dstUsdValue) / _getNativeTokenPrice(CHAIN_ID); } From 3612e033257b4328fe5dbdb1d6c94a7adbd1cdc6 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 17 Dec 2023 21:24:38 -0500 Subject: [PATCH 076/210] chore: clean merge --- src/BaseRouterImplementation.sol | 1 + src/libraries/Error.sol | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 60f6a974c..8cfb0cfe9 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -827,6 +827,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { return false; } + /// @dev Additional length checks for hasDstSwaps and retain4626s if (lenSuperforms != superformsData_.hasDstSwaps.length || lenSuperforms != superformsData_.retain4626s.length) { diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 10e8dfa57..04252c5c4 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -258,9 +258,6 @@ library Error { ///@notice errors thrown due to function execution logic /// COMMON EXECUTION ERRORS - /// @dev thrown if allowance in direct deposit is not correct - error DIRECT_DEPOSIT_INSUFFICIENT_ALLOWANCE(); - /// @dev thrown if the swap in a direct deposit resulted in insufficient tokens error DIRECT_DEPOSIT_SWAP_FAILED(); From f3edbd37d7c575b4bffcef12b1328ba87753be97 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 17 Dec 2023 21:56:05 -0500 Subject: [PATCH 077/210] chore: cleaning PaymentHelper --- src/payments/PaymentHelper.sol | 216 ++++++++++++++++----------------- 1 file changed, 106 insertions(+), 110 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 9820fc7e1..0d4c3f70d 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -174,14 +174,8 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate dst swap cost if it exists totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); - } - - /// @dev step 6: estimate execution costs in dst (withdraw / deposit) - /// note: execution cost includes acknowledgement messaging cost - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], superformIdsLen); - - /// @dev step 6: estimate if timelock form processing costs are involved - if (!isDeposit_) { + } else { + /// @dev step 6: estimate if timelock form processing costs are involved for (uint256 j; j < superformIdsLen; ++j) { (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); if (formId == TIMELOCK_FORM_ID) { @@ -190,7 +184,11 @@ contract PaymentHelper is IPaymentHelper { } } - /// @dev step 7: convert all dst gas estimates to src chain estimate (withdraw / deposit) + /// @dev step 7: estimate execution costs in dst (withdraw / deposit) + /// note: execution cost includes acknowledgement messaging cost + totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], superformIdsLen); + + /// @dev step 8: convert all dst gas estimates to src chain estimate (withdraw / deposit) dstAmount += _convertToNativeFee(req_.dstChainIds[i], totalDstGas); } @@ -231,19 +229,19 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate if swap costs are involved totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); + } else { + /// @dev step 6: estimate if timelock form processing costs are involved + (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[req_.dstChainIds[i]]; + } } - /// @dev step 5: estimate execution costs in dst + /// @dev step 7: estimate execution costs in dst /// note: execution cost includes acknowledgement messaging cost totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], 1); - /// @dev step 6: estimate if timelock form processing costs are involved - (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); - if (!isDeposit_ && formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[req_.dstChainIds[i]]; - } - - /// @dev step 7: convert all dst gas estimates to src chain estimate + /// @dev step 8: convert all dst gas estimates to src chain estimate dstAmount += _convertToNativeFee(req_.dstChainIds[i], totalDstGas); } @@ -268,35 +266,32 @@ contract PaymentHelper is IPaymentHelper { _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateMultiVaultMessage(req_.superformsData)); srcAmount += ambFees; - /// @dev step 2, 3, 4, 5: process deposit-specific logic if (isDeposit_) { - // estimate update cost + /// @dev step 2: estimate update cost (only for deposit) totalDstGas += _estimateUpdateCost(req_.dstChainId, superformIdsLen); - // estimate execution cost of acknowledgement + /// @dev step 3: estimation execution cost of acknowledgement srcAmount += _estimateAckProcessingCost(superformIdsLen); - // estimate liquidity amount + /// @dev step 4: estimate the liqAmount liqAmount += _estimateLiqAmount(req_.superformsData.liqRequests); - // estimate swap fees + /// @dev step 5: estimate if swap costs are involved totalDstGas += _estimateSwapFees(req_.dstChainId, req_.superformsData.hasDstSwaps); - } - - /// @dev step 6: estimate execution costs in destination - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, superformIdsLen); - - /// @dev step 7: process non-deposit logic for timelock form processing costs - if (!isDeposit_) { + } else { + /// @dev step 6: process non-deposit logic for timelock form processing costs for (uint256 i; i < superformIdsLen; ++i) { (, uint32 formId,) = req_.superformsData.superformIds[i].getSuperform(); if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[CHAIN_ID]; + totalDstGas += timelockCost[req_.dstChainId]; } } } + /// @dev step 7: estimate execution costs in destination + totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, superformIdsLen); + /// @dev step 8: convert all destination gas estimates to source chain estimate dstAmount += _convertToNativeFee(req_.dstChainId, totalDstGas); @@ -321,33 +316,30 @@ contract PaymentHelper is IPaymentHelper { _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateSingleVaultMessage(req_.superformData)); srcAmount += ambFees; - /// @dev step 2,3,4,5: Process deposit-specific logic if (isDeposit_) { - // estimate update cost + /// @dev step 2: estimate update cost (only for deposit) totalDstGas += _estimateUpdateCost(req_.dstChainId, 1); - // estimate execution cost of acknowledgement + /// @dev step 3: estimation execution cost of acknowledgement srcAmount += _estimateAckProcessingCost(1); - // estimate the liquidity amount + /// @dev step 4: estimate the liqAmount liqAmount += _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); - // estimate swap fees + /// @dev step 5: estimate if swap costs are involved totalDstGas += _estimateSwapFees(req_.dstChainId, req_.superformData.hasDstSwap.castBoolToArray()); - } - - /// @dev step 6: estimate execution costs in destination - totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, 1); - - /// @dev step 7: process non-deposit logic for timelock form processing costs - if (!isDeposit_) { + } else { + /// @dev step 6: process non-deposit logic for timelock form processing costs (, uint32 formId,) = req_.superformData.superformId.getSuperform(); if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[CHAIN_ID]; + totalDstGas += timelockCost[req_.dstChainId]; } } + /// @dev step 7: estimate execution costs in destination + totalDstGas += _estimateDstExecutionCost(isDeposit_, req_.dstChainId, 1); + /// @dev step 8: convert all destination gas estimates to source chain estimate dstAmount += _convertToNativeFee(req_.dstChainId, totalDstGas); @@ -365,14 +357,16 @@ contract PaymentHelper is IPaymentHelper { override returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount) { - (, uint32 formId,) = req_.superformData.superformId.getSuperform(); - /// @dev only if timelock form withdrawal is involved - if (!isDeposit_ && formId == TIMELOCK_FORM_ID) { - srcAmount += timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); + if (!isDeposit_) { + /// @dev only if timelock form withdrawal is involved + (, uint32 formId,) = req_.superformData.superformId.getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + srcAmount = timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); + } + } else { + liqAmount = _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); } - - if (isDeposit_) liqAmount += _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); - + /// @dev not adding dstAmount to save some GAS totalAmount = liqAmount + srcAmount; } @@ -387,18 +381,20 @@ contract PaymentHelper is IPaymentHelper { override returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount) { - uint256 len = req_.superformData.superformIds.length; - for (uint256 i; i < len; ++i) { - (, uint32 formId,) = req_.superformData.superformIds[i].getSuperform(); - uint256 timelockPrice = timelockCost[uint64(block.chainid)] * _getGasPrice(uint64(block.chainid)); - /// @dev only if timelock form withdrawal is involved - if (!isDeposit_ && formId == TIMELOCK_FORM_ID) { - srcAmount += timelockPrice; + if (!isDeposit_) { + uint256 len = req_.superformData.superformIds.length; + for (uint256 i; i < len; ++i) { + (, uint32 formId,) = req_.superformData.superformIds[i].getSuperform(); + uint256 timelockPrice = timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); + /// @dev only if timelock form withdrawal is involved + if (formId == TIMELOCK_FORM_ID) { + srcAmount += timelockPrice; + } } + } else { + liqAmount += _estimateLiqAmount(req_.superformData.liqRequests); } - if (isDeposit_) liqAmount += _estimateLiqAmount(req_.superformData.liqRequests); - /// @dev not adding dstAmount to save some GAS totalAmount = liqAmount + srcAmount; } @@ -418,19 +414,51 @@ contract PaymentHelper is IPaymentHelper { uint256[] memory fees = new uint256[](len); /// @dev just checks the estimate for sending message from src -> dst - for (uint256 i; i < len; ++i) { - fees[i] = CHAIN_ID != dstChainId_ - ? IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees( + if (CHAIN_ID != dstChainId_) { + for (uint256 i; i < len; ++i) { + fees[i] = IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees( dstChainId_, message_, extraData_[i] - ) - : 0; + ); - totalFees += fees[i]; + totalFees += fees[i]; + } } return (totalFees, fees); } + /// @dev helps estimate the acknowledgement costs for amb processing + function estimateAckCost(uint256 payloadId_) external view returns (uint256 totalFees) { + EstimateAckCostVars memory v; + IBaseStateRegistry coreStateRegistry = + IBaseStateRegistry(superRegistry.getAddress(keccak256("CORE_STATE_REGISTRY"))); + v.currPayloadId = coreStateRegistry.payloadsCount(); + + if (payloadId_ > v.currPayloadId) revert Error.INVALID_PAYLOAD_ID(); + + v.payloadHeader = coreStateRegistry.payloadHeader(payloadId_); + v.payloadBody = coreStateRegistry.payloadBody(payloadId_); + + (, v.callbackType, v.isMulti,,, v.srcChainId) = DataLib.decodeTxInfo(v.payloadHeader); + + /// if callback type is return then return 0 + if (v.callbackType != 0) return 0; + + if (v.isMulti == 1) { + InitMultiVaultData memory data = abi.decode(v.payloadBody, (InitMultiVaultData)); + v.payloadBody = abi.encode(ReturnMultiData(v.currPayloadId, data.superformIds, data.amounts)); + } else { + InitSingleVaultData memory data = abi.decode(v.payloadBody, (InitSingleVaultData)); + v.payloadBody = abi.encode(ReturnSingleData(v.currPayloadId, data.superformId, data.amount)); + } + + v.ackAmbIds = coreStateRegistry.getMessageAMB(payloadId_); + + v.message = abi.encode(AMBMessage(coreStateRegistry.payloadHeader(payloadId_), v.payloadBody)); + + return _estimateAMBFees(v.ackAmbIds, v.srcChainId, v.message); + } + ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// @@ -591,38 +619,6 @@ contract PaymentHelper is IPaymentHelper { } } - /// @dev helps estimate the acknowledgement costs for amb processing - function estimateAckCost(uint256 payloadId_) external view returns (uint256 totalFees) { - EstimateAckCostVars memory v; - IBaseStateRegistry coreStateRegistry = - IBaseStateRegistry(superRegistry.getAddress(keccak256("CORE_STATE_REGISTRY"))); - v.currPayloadId = coreStateRegistry.payloadsCount(); - - if (payloadId_ > v.currPayloadId) revert Error.INVALID_PAYLOAD_ID(); - - v.payloadHeader = coreStateRegistry.payloadHeader(payloadId_); - v.payloadBody = coreStateRegistry.payloadBody(payloadId_); - - (, v.callbackType, v.isMulti,,, v.srcChainId) = DataLib.decodeTxInfo(v.payloadHeader); - - /// if callback type is return then return 0 - if (v.callbackType != 0) return 0; - - if (v.isMulti == 1) { - InitMultiVaultData memory data = abi.decode(v.payloadBody, (InitMultiVaultData)); - v.payloadBody = abi.encode(ReturnMultiData(v.currPayloadId, data.superformIds, data.amounts)); - } else { - InitSingleVaultData memory data = abi.decode(v.payloadBody, (InitSingleVaultData)); - v.payloadBody = abi.encode(ReturnSingleData(v.currPayloadId, data.superformId, data.amount)); - } - - v.ackAmbIds = coreStateRegistry.getMessageAMB(payloadId_); - - v.message = abi.encode(AMBMessage(coreStateRegistry.payloadHeader(payloadId_), v.payloadBody)); - - return _estimateAMBFees(v.ackAmbIds, v.srcChainId, v.message); - } - /// @dev helps estimate the cross-chain message costs function _estimateAMBFees( uint8[] memory ambIds_, @@ -644,14 +640,14 @@ contract PaymentHelper is IPaymentHelper { /// @dev just checks the estimate for sending message from src -> dst /// @dev only ambIds_[0] = primary amb (rest of the ambs send only the proof) - for (uint256 i; i < len; ++i) { - uint256 tempFee = CHAIN_ID != dstChainId_ - ? IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees( + if (CHAIN_ID != dstChainId_) { + for (uint256 i; i < len; ++i) { + uint256 tempFee = IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees( dstChainId_, i != 0 ? proof_ : abi.encode(ambIdEncodedMessage), extraDataPerAMB[i] - ) - : 0; + ); - totalFees += tempFee; + totalFees += tempFee; + } } } @@ -677,15 +673,15 @@ contract PaymentHelper is IPaymentHelper { bytes memory proof_ = abi.encode(AMBMessage(type(uint256).max, abi.encode(keccak256(message_)))); /// @dev just checks the estimate for sending message from src -> dst - for (uint256 i; i < len; ++i) { - uint256 tempFee = CHAIN_ID != dstChainId_ - ? IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees( + if (CHAIN_ID != dstChainId_) { + for (uint256 i; i < len; ++i) { + uint256 tempFee = IAmbImplementation(superRegistry.getAmbAddress(ambIds_[i])).estimateFees( dstChainId_, i != 0 ? proof_ : abi.encode(ambIdEncodedMessage), extraDataPerAMB[i] - ) - : 0; + ); - totalFees += tempFee; - feeSplitUp[i] = tempFee; + totalFees += tempFee; + feeSplitUp[i] = tempFee; + } } } From 3dd7379e9216e5bd89a3a10004b554996ae600ac Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 17 Dec 2023 22:23:47 -0500 Subject: [PATCH 078/210] chore: fix else --- src/payments/PaymentHelper.sol | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index bc6c575ab..a3732e6b3 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -171,11 +171,12 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate dst swap cost if it exists totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); } else { - /// @dev step 6: estimate if timelock form processing costs are involved - for (uint256 j; j < superformIdsLen; ++j) { - (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); - if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[req_.dstChainIds[i]]; + /// @dev step 6: estimate if timelock form processing costs are involved + for (uint256 j; j < superformIdsLen; ++j) { + (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[req_.dstChainIds[i]]; + } } } } @@ -223,15 +224,16 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 4: estimation execution cost of acknowledgement srcAmount += _estimateAckProcessingCost(1); - /// @dev step 5: estimate if swap costs are involved - totalDstGas += - _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); + /// @dev step 5: estimate if swap costs are involved + totalDstGas += + _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); } else { - /// @dev step 6: estimate if timelock form processing costs are involved - (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); - if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[req_.dstChainIds[i]]; - } + /// @dev step 6: estimate if timelock form processing costs are involved + (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[req_.dstChainIds[i]]; + } + } } /// @dev step 7: estimate execution costs in dst From 3464a4d6e0a3565fd8e1cf8676419c97d628c5a7 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 18 Dec 2023 03:40:25 -0500 Subject: [PATCH 079/210] chore: fix --- src/payments/PaymentHelper.sol | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index a3732e6b3..3d84b0999 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -170,7 +170,8 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate dst swap cost if it exists totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); - } else { + } + } else { /// @dev step 6: estimate if timelock form processing costs are involved for (uint256 j; j < superformIdsLen; ++j) { (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); @@ -227,7 +228,8 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate if swap costs are involved totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); - } else { + } + } else { /// @dev step 6: estimate if timelock form processing costs are involved (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); if (formId == TIMELOCK_FORM_ID) { @@ -382,9 +384,9 @@ contract PaymentHelper is IPaymentHelper { { if (!isDeposit_) { uint256 len = req_.superformData.superformIds.length; + uint256 timelockPrice = timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); for (uint256 i; i < len; ++i) { (, uint32 formId,) = req_.superformData.superformIds[i].getSuperform(); - uint256 timelockPrice = timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); /// @dev only if timelock form withdrawal is involved if (formId == TIMELOCK_FORM_ID) { srcAmount += timelockPrice; From 8c23fe3c5f9f267182f483e275128ea640a5f497 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 18 Dec 2023 03:43:35 -0500 Subject: [PATCH 080/210] chore: fix spacing --- src/payments/PaymentHelper.sol | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 3d84b0999..dddf7c5cc 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -171,7 +171,7 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate dst swap cost if it exists totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); } - } else { + } else { /// @dev step 6: estimate if timelock form processing costs are involved for (uint256 j; j < superformIdsLen; ++j) { (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); @@ -179,7 +179,6 @@ contract PaymentHelper is IPaymentHelper { totalDstGas += timelockCost[req_.dstChainIds[i]]; } } - } } /// @dev step 7: estimate execution costs in dst (withdraw / deposit) @@ -229,13 +228,12 @@ contract PaymentHelper is IPaymentHelper { totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); } - } else { + } else { /// @dev step 6: estimate if timelock form processing costs are involved (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); if (formId == TIMELOCK_FORM_ID) { totalDstGas += timelockCost[req_.dstChainIds[i]]; } - } } /// @dev step 7: estimate execution costs in dst From 1de50442c3bb697543f0a8fbddbfd6b38c6d1d64 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 18 Dec 2023 03:44:40 -0500 Subject: [PATCH 081/210] chore: else tabs --- src/payments/PaymentHelper.sol | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index dddf7c5cc..9e7dae0fc 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -172,13 +172,13 @@ contract PaymentHelper is IPaymentHelper { totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); } } else { - /// @dev step 6: estimate if timelock form processing costs are involved - for (uint256 j; j < superformIdsLen; ++j) { - (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); - if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[req_.dstChainIds[i]]; - } + /// @dev step 6: estimate if timelock form processing costs are involved + for (uint256 j; j < superformIdsLen; ++j) { + (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[req_.dstChainIds[i]]; } + } } /// @dev step 7: estimate execution costs in dst (withdraw / deposit) @@ -229,11 +229,11 @@ contract PaymentHelper is IPaymentHelper { _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); } } else { - /// @dev step 6: estimate if timelock form processing costs are involved - (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); - if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[req_.dstChainIds[i]]; - } + /// @dev step 6: estimate if timelock form processing costs are involved + (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); + if (formId == TIMELOCK_FORM_ID) { + totalDstGas += timelockCost[req_.dstChainIds[i]]; + } } /// @dev step 7: estimate execution costs in dst From d7bf1fc0fb696f1ed9525074c365b1a4f37d29c7 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 18 Dec 2023 15:00:48 +0000 Subject: [PATCH 082/210] fix: variable name --- src/BaseForm.sol | 6 +++--- src/forms/ERC4626Form.sol | 4 ++-- src/forms/ERC4626FormImplementation.sol | 8 ++++---- src/forms/ERC4626KYCDaoForm.sol | 4 ++-- src/forms/ERC4626TimelockForm.sol | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 04683b8d8..e90beb3e1 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -240,14 +240,14 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { /// @inheritdoc IBaseForm function emergencyWithdraw( address srcSender_, - address refundAddress_, + address receiverAddress_, uint256 amount_ ) external override onlyEmergencyQueue { - _emergencyWithdraw(srcSender_, refundAddress_, amount_); + _emergencyWithdraw(srcSender_, receiverAddress_, amount_); } /// @inheritdoc IBaseForm @@ -298,7 +298,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { returns (uint256 dstAmount); /// @dev withdraws vault shares from form during emergency - function _emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) internal virtual; + function _emergencyWithdraw(address srcSender_, address receiverAddress_, uint256 amount_) internal virtual; /// @dev forwards dust to paymaster function _forwardDustToPaymaster() internal virtual; diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index ee22074d6..a47e8d1f8 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -75,8 +75,8 @@ contract ERC4626Form is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _emergencyWithdraw(address, /*srcSender_*/ address refundAddress_, uint256 amount_) internal override { - _processEmergencyWithdraw(refundAddress_, amount_); + function _emergencyWithdraw(address, /*srcSender_*/ address receiverAddress_, uint256 amount_) internal override { + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 01d2b5955..dc6444ed0 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -391,17 +391,17 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit Processed(srcChainId_, vars.dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vault); } - function _processEmergencyWithdraw(address refundAddress_, uint256 amount_) internal { + function _processEmergencyWithdraw(address receiverAddress_, uint256 amount_) internal { IERC4626 vaultContract = IERC4626(vault); if (vaultContract.balanceOf(address(this)) < amount_) { revert Error.INSUFFICIENT_BALANCE(); } - if (refundAddress_ == address(0)) revert Error.ZERO_ADDRESS(); + if (receiverAddress_ == address(0)) revert Error.ZERO_ADDRESS(); - vaultContract.safeTransfer(refundAddress_, amount_); - emit EmergencyWithdrawalProcessed(refundAddress_, amount_); + vaultContract.safeTransfer(receiverAddress_, amount_); + emit EmergencyWithdrawalProcessed(receiverAddress_, amount_); } function _processForwardDustToPaymaster() internal { diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index bc57db6da..70bce6194 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -96,14 +96,14 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { /// @inheritdoc BaseForm function _emergencyWithdraw( address srcSender_, - address refundAddress_, + address receiverAddress_, uint256 amount_ ) internal override onlyKYC(srcSender_) { - _processEmergencyWithdraw(refundAddress_, amount_); + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 8937781f0..d0c14fc91 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -200,8 +200,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _emergencyWithdraw(address, /*srcSender_*/ address refundAddress_, uint256 amount_) internal override { - _processEmergencyWithdraw(refundAddress_, amount_); + function _emergencyWithdraw(address, /*srcSender_*/ address receiverAddress_, uint256 amount_) internal override { + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm From 2a104300ace0f27dd398340701f9f9c37b75db6b Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 18 Dec 2023 20:59:17 +0530 Subject: [PATCH 083/210] chore: add duplicate index protection to _batchProcessTx --- src/crosschain-liquidity/DstSwapper.sol | 35 ++++++++------ src/interfaces/IDstSwapper.sol | 6 +-- src/libraries/Error.sol | 3 ++ .../crosschain-liquidity/DstSwapper.t.sol | 48 ++++++++++--------- .../superform-router/SuperformRouter.t.sol | 1 - test/utils/InvariantProtocolActions.sol | 2 +- test/utils/ProtocolActions.sol | 2 +- 7 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 543587139..5c172d5c2 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -130,7 +130,6 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { /// @inheritdoc IDstSwapper function processTx( uint256 payloadId_, - uint256 index_, uint8 bridgeId_, bytes calldata txData_ ) @@ -149,7 +148,8 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { _processTx( payloadId_, - index_, + 0, + /// index is always 0 for single vault payload bridgeId_, txData_, abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitSingleVaultData)).liqData.interimToken, @@ -185,7 +185,11 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { for (uint256 i; i < len; ++i) { index = indices_[i]; + if (index >= maxIndex) revert Error.INDEX_OUT_OF_BOUNDS(); + if (i > 0 && index <= indices_[i - 1]) { + revert Error.DUPLICATE_INDEX(); + } _processTx( payloadId_, index, bridgeIds_[i], txData_[i], data.liqData[index].interimToken, coreStateRegistry @@ -194,16 +198,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { } /// @inheritdoc IDstSwapper - function updateFailedTx( - uint256 payloadId_, - uint256 index_, - address interimToken_, - uint256 amount_ - ) - external - override - onlySwapper - { + function updateFailedTx(uint256 payloadId_, address interimToken_, uint256 amount_) external override onlySwapper { IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); _isValidPayloadId(payloadId_, coreStateRegistry); @@ -214,7 +209,8 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { _updateFailedTx( payloadId_, - index_, + 0, + /// index is always zero for single vault payload interimToken_, abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitSingleVaultData)).liqData.interimToken, amount_, @@ -244,9 +240,20 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { InitMultiVaultData memory data = abi.decode(coreStateRegistry.payloadBody(payloadId_), (InitMultiVaultData)); + uint256 maxIndex = data.liqData.length; + uint256 index; + for (uint256 i; i < len; ++i) { + index = indices_[i]; + if (index >= maxIndex) revert Error.INDEX_OUT_OF_BOUNDS(); + _updateFailedTx( - payloadId_, indices_[i], interimTokens_[i], data.liqData[i].interimToken, amounts_[i], coreStateRegistry + payloadId_, + indices_[index], + interimTokens_[i], + data.liqData[index].interimToken, + amounts_[i], + coreStateRegistry ); } } diff --git a/src/interfaces/IDstSwapper.sol b/src/interfaces/IDstSwapper.sol index faba85946..74a6d8e9c 100644 --- a/src/interfaces/IDstSwapper.sol +++ b/src/interfaces/IDstSwapper.sol @@ -57,17 +57,15 @@ interface IDstSwapper { /// @notice will process dst swap through a liquidity bridge /// @param payloadId_ represents the id of the payload - /// @param index_ represents the index of the superformid in the payload /// @param bridgeId_ represents the id of liquidity bridge used /// @param txData_ represents the transaction data generated by liquidity bridge API. - function processTx(uint256 payloadId_, uint256 index_, uint8 bridgeId_, bytes calldata txData_) external; + function processTx(uint256 payloadId_, uint8 bridgeId_, bytes calldata txData_) external; /// @notice updates the amounts of intermediary tokens stuck because of failing dst swap /// @param payloadId_ represents the id of the payload - /// @param index_ represents the failing index in the payload /// @param interimToken_ is the intermediary token that cannot be swapped to the vault underlying /// @param amount_ is the amount of the intermediary token - function updateFailedTx(uint256 payloadId_, uint256 index_, address interimToken_, uint256 amount_) external; + function updateFailedTx(uint256 payloadId_, address interimToken_, uint256 amount_) external; /// @notice updates the amounts of intermediary tokens stuck because of failing dst swap in batch /// @param payloadId_ represents the id of the payload diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 7414d717f..6a25e531b 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -31,6 +31,9 @@ library Error { /// @dev thrown if indices are out of bounds error INDEX_OUT_OF_BOUNDS(); + /// @dev thrown if indices have duplicates + error DUPLICATE_INDEX(); + ////////////////////////////////////////////////////////////// // AUTHORIZATION ERRORS // ////////////////////////////////////////////////////////////// diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index dd8f6c1cb..678fefd9c 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -39,7 +39,7 @@ contract DstSwapperTest is ProtocolActions { _buildLiqBridgeTxDataDstSwap(1, native, getContract(ETH, "DAI"), dstSwapper, ETH, 1e18, 0); vm.expectRevert(Error.INVALID_INTERIM_TOKEN.selector); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); + DstSwapper(dstSwapper).processTx(1, 1, txData); } else { revert(); } @@ -63,21 +63,17 @@ contract DstSwapperTest is ProtocolActions { bytes memory txData = _buildLiqBridgeTxDataDstSwap(1, native, getContract(ETH, "DAI"), dstSwapper, ETH, 1e18, 0); vm.expectRevert(Error.INVALID_PAYLOAD_ID.selector); - DstSwapper(dstSwapper).processTx(1000, 0, 1, txData); + DstSwapper(dstSwapper).processTx(1000, 1, txData); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); - - /// @dev try with a non-existent index - vm.expectRevert(Error.INVALID_INDEX.selector); - DstSwapper(dstSwapper).processTx(1, 420, 1, txData); + DstSwapper(dstSwapper).processTx(1, 1, txData); /// @dev retry the same payload id and indices vm.expectRevert(Error.DST_SWAP_ALREADY_PROCESSED.selector); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); + DstSwapper(dstSwapper).processTx(1, 1, txData); /// @dev no funds in multi-tx processor at this point; should revert vm.expectRevert(abi.encodeWithSelector(Error.FAILED_TO_EXECUTE_TXDATA.selector, native)); - DstSwapper(dstSwapper).processTx(2, 0, 1, txData); + DstSwapper(dstSwapper).processTx(2, 1, txData); } else { revert(); } @@ -95,7 +91,7 @@ contract DstSwapperTest is ProtocolActions { _buildLiqBridgeTxDataDstSwap(1, getContract(ETH, "WETH"), getContract(ETH, "DAI"), dstSwapper, ETH, 1e18, 0); /// @dev no funds in multi-tx processor at this point; should revert vm.expectRevert(abi.encodeWithSelector(Error.FAILED_TO_EXECUTE_TXDATA.selector, getContract(ETH, "WETH"))); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); + DstSwapper(dstSwapper).processTx(1, 1, txData); } function test_partial_multi_vault_dstSwap() public { @@ -189,21 +185,21 @@ contract DstSwapperTest is ProtocolActions { deal(weth, dstSwapper, 1e18); vm.expectRevert(Error.ZERO_AMOUNT.selector); - DstSwapper(dstSwapper).updateFailedTx(1, 0, weth, 0); + DstSwapper(dstSwapper).updateFailedTx(1, weth, 0); vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); - DstSwapper(dstSwapper).updateFailedTx(1, 0, weth, 3e18); + DstSwapper(dstSwapper).updateFailedTx(1, weth, 3e18); - DstSwapper(dstSwapper).updateFailedTx(1, 0, weth, 1e18); + DstSwapper(dstSwapper).updateFailedTx(1, weth, 1e18); vm.expectRevert(Error.FAILED_DST_SWAP_ALREADY_UPDATED.selector); - DstSwapper(dstSwapper).updateFailedTx(1, 0, weth, 1e18); + DstSwapper(dstSwapper).updateFailedTx(1, weth, 1e18); vm.expectRevert(Error.INVALID_PAYLOAD_TYPE.selector); - DstSwapper(dstSwapper).updateFailedTx(2, 0, weth, 1e18); + DstSwapper(dstSwapper).updateFailedTx(2, weth, 1e18); vm.expectRevert(Error.INVALID_INTERIM_TOKEN.selector); - DstSwapper(dstSwapper).updateFailedTx(3, 0, weth, 1e18); + DstSwapper(dstSwapper).updateFailedTx(3, weth, 1e18); /// @dev set quorum to 0 for simplicity in testing setup SuperRegistry(getContract(OP, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); @@ -218,7 +214,7 @@ contract DstSwapperTest is ProtocolActions { CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, finalAmounts); vm.expectRevert(Error.INVALID_PAYLOAD_STATUS.selector); - DstSwapper(dstSwapper).updateFailedTx(1, 0, weth, 1e18); + DstSwapper(dstSwapper).updateFailedTx(1, weth, 1e18); vm.stopPrank(); AMBs = [2, 3]; @@ -265,7 +261,7 @@ contract DstSwapperTest is ProtocolActions { vm.startPrank(deployer); deal(weth, dstSwapper, 1e18); - DstSwapper(dstSwapper).updateFailedTx(1, 0, weth, 1e18); + DstSwapper(dstSwapper).updateFailedTx(1, weth, 1e18); vm.stopPrank(); @@ -286,7 +282,7 @@ contract DstSwapperTest is ProtocolActions { vm.startPrank(deployer); deal(dstSwapper, 1e18); - DstSwapper(dstSwapper).updateFailedTx(2, 0, native, 1e18); + DstSwapper(dstSwapper).updateFailedTx(2, native, 1e18); vm.stopPrank(); @@ -308,11 +304,11 @@ contract DstSwapperTest is ProtocolActions { vm.startPrank(deployer); vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); - DstSwapper(dstSwapper).updateFailedTx(1, 0, native, 1e18); + DstSwapper(dstSwapper).updateFailedTx(1, native, 1e18); deal(dstSwapper, 1e18); - DstSwapper(dstSwapper).updateFailedTx(1, 0, native, 1e18); + DstSwapper(dstSwapper).updateFailedTx(1, native, 1e18); /// @dev set quorum to 0 for simplicity in testing setup SuperRegistry(getContract(OP, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); @@ -527,6 +523,12 @@ contract DstSwapperTest is ProtocolActions { vm.expectRevert(Error.INDEX_OUT_OF_BOUNDS.selector); DstSwapper(dstSwapper).batchProcessTx(1, indices, bridgeId, txData); + + vm.expectRevert(Error.DUPLICATE_INDEX.selector); + indices[0] = 1; + indices[1] = 1; + DstSwapper(dstSwapper).batchProcessTx(1, indices, bridgeId, txData); + indices[0] = 0; indices[1] = 1; DstSwapper(dstSwapper).batchProcessTx(1, indices, bridgeId, txData); @@ -601,7 +603,7 @@ contract DstSwapperTest is ProtocolActions { _buildLiqBridgeTxDataDstSwap(1, getContract(ETH, "WETH"), getContract(ETH, "DAI"), dstSwapper, ETH, 0, 0); /// @dev txData with amount 0 should revert vm.expectRevert(Error.INVALID_SWAP_OUTPUT.selector); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); + DstSwapper(dstSwapper).processTx(1, 1, txData); } function test_failed_MAX_SLIPPAGE_INVARIANT_BROKEN() public { @@ -652,7 +654,7 @@ contract DstSwapperTest is ProtocolActions { ); /// @dev txData with amount 0 should revert vm.expectRevert(Error.SLIPPAGE_OUT_OF_BOUNDS.selector); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); + DstSwapper(dstSwapper).processTx(1, 1, txData); } function test_processFailedTx_invalidUserCall() public { diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 02d716b09..2d2fc1d44 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -2363,7 +2363,6 @@ contract SuperformRouterTest is ProtocolActions { if (hasDstSwap) { DstSwapper(payable(getContract(ARBI, "DstSwapper"))).processTx( 1, - 0, 1, _buildLiqBridgeTxDataDstSwap( 1, diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index 87dda7fa9..4bf01f1a7 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -1572,7 +1572,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.prank(deployer); - DstSwapper(payable(getContract(targetChainId_, "DstSwapper"))).processTx(1, 0, liqBridgeKind_, txData); + DstSwapper(payable(getContract(targetChainId_, "DstSwapper"))).processTx(1, liqBridgeKind_, txData); vm.selectFork(initialFork); } diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 743867d07..13b117dac 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -2344,7 +2344,7 @@ abstract contract ProtocolActions is CommonProtocolActions { ); vm.prank(deployer); - DstSwapper(payable(getContract(targetChainId_, "DstSwapper"))).processTx(1, 0, liqBridgeKind_, txData); + DstSwapper(payable(getContract(targetChainId_, "DstSwapper"))).processTx(1, liqBridgeKind_, txData); vm.selectFork(initialFork); } From 19d4081cbd05cd81685d17b229fc398d06af001c Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 18 Dec 2023 21:08:06 +0530 Subject: [PATCH 084/210] chore: add duplicates check on batchUpdateFailedTx --- src/crosschain-liquidity/DstSwapper.sol | 3 +++ test/unit/crosschain-liquidity/DstSwapper.t.sol | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 5c172d5c2..436a2cd72 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -246,6 +246,9 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { for (uint256 i; i < len; ++i) { index = indices_[i]; if (index >= maxIndex) revert Error.INDEX_OUT_OF_BOUNDS(); + if (i > 0 && index <= indices_[i - 1]) { + revert Error.DUPLICATE_INDEX(); + } _updateFailedTx( payloadId_, diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index 678fefd9c..3417371c8 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -374,6 +374,18 @@ contract DstSwapperTest is ProtocolActions { amounts[1] = 1e18; uint256[] memory indices = new uint256[](2); + indices[0] = 2; + indices[1] = 1; + + vm.expectRevert(Error.INDEX_OUT_OF_BOUNDS.selector); + DstSwapper(dstSwapper).batchUpdateFailedTx(1, indices, interimTokens, amounts); + + indices[0] = 1; + indices[1] = 1; + + vm.expectRevert(Error.DUPLICATE_INDEX.selector); + DstSwapper(dstSwapper).batchUpdateFailedTx(1, indices, interimTokens, amounts); + indices[0] = 0; indices[1] = 1; From 170e183cfd1c1273ac602d182e528d663fc717cb Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 18 Dec 2023 21:23:04 +0530 Subject: [PATCH 085/210] chore: merge develop --- test/unit/crosschain-liquidity/DstSwapper.t.sol | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index bf59e46c8..a28fa95f3 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -67,14 +67,12 @@ contract DstSwapperTest is ProtocolActions { DstSwapper(dstSwapper).processTx(1, 1, txData); - DstSwapper(dstSwapper).processTx(1, 0, 1, txData); - /// @dev retry the same payload id and indices vm.expectRevert(Error.DST_SWAP_ALREADY_PROCESSED.selector); DstSwapper(dstSwapper).processTx(1, 1, txData); /// @dev no funds in multi-tx processor at this point; should revert - vm.expectRevert(abi.encodeWithSelector(Error.FAILED_TO_EXECUTE_TXDATA.selector, native)); + vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); DstSwapper(dstSwapper).processTx(2, 1, txData); } else { revert(); @@ -92,7 +90,7 @@ contract DstSwapperTest is ProtocolActions { bytes memory txData = _buildLiqBridgeTxDataDstSwap(1, getContract(ETH, "WETH"), getContract(ETH, "DAI"), dstSwapper, ETH, 1e18, 0); /// @dev no funds in multi-tx processor at this point; should revert - vm.expectRevert(abi.encodeWithSelector(Error.FAILED_TO_EXECUTE_TXDATA.selector, getContract(ETH, "WETH"))); + vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); DstSwapper(dstSwapper).processTx(1, 1, txData); } @@ -616,7 +614,7 @@ contract DstSwapperTest is ProtocolActions { bytes memory txData = _buildLiqBridgeTxDataDstSwap(1, getContract(ETH, "WETH"), getContract(ETH, "DAI"), dstSwapper, ETH, 0, 0); /// @dev txData with amount 0 should revert - vm.expectRevert(Error.INVALID_SWAP_OUTPUT.selector); + vm.expectRevert(Error.ZERO_AMOUNT.selector); DstSwapper(dstSwapper).processTx(1, 1, txData); } From 9b9caf7b66cece4c26772273ca393502eb88eb16 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 18 Dec 2023 21:13:38 +0000 Subject: [PATCH 086/210] fix: contains fix for #277 and #251 --- src/BaseForm.sol | 20 ++---- src/BaseRouterImplementation.sol | 28 ++++++--- src/EmergencyQueue.sol | 19 ++---- src/SuperPositions.sol | 61 +++++++++++-------- .../layerzero/LayerzeroImplementation.sol | 4 +- .../extensions/CoreStateRegistry.sol | 20 +++--- src/crosschain-data/utils/PayloadHelper.sol | 12 +++- src/forms/ERC4626Form.sol | 4 +- src/forms/ERC4626FormImplementation.sol | 10 ++- src/forms/ERC4626KYCDaoForm.sol | 12 +--- src/forms/ERC4626TimelockForm.sol | 8 +-- src/interfaces/IBaseForm.sol | 7 +-- src/interfaces/ICoreStateRegistry.sol | 4 +- src/interfaces/IEmergencyQueue.sol | 9 ++- src/interfaces/IPayloadHelper.sol | 10 ++- src/interfaces/ISuperPositions.sol | 30 ++++++--- src/types/DataTypes.sol | 3 +- test/mocks/ERC4626FormExternal.sol | 4 +- .../BaseFormInterfaceNotSupported.sol | 14 +---- ...626ImplementationInterfaceNotSupported.sol | 6 +- .../ERC4626InterFaceNotSupported.sol | 4 +- .../TwoStepsFormStateRegistry.t.sol | 6 +- .../utils/PayloadHelper.multiVault.t.sol | 4 +- .../utils/PayloadHelper.singleVault.t.sol | 4 +- test/unit/emergency/EmergencyQueue.t.sol | 32 +++++++--- .../super-positions/super-positions.t.sol | 44 +++---------- .../superform-form.ERC4626Form.t.sol | 49 +++++++-------- .../superform-form.ERC4626KYCDao.t.sol | 8 +-- .../superform-form.ERC4626Timelock.t.sol | 12 ++-- .../superform-form.forwardDust.t.sol | 11 ++-- 30 files changed, 235 insertions(+), 224 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index d0dc4a51d..8c9b2df90 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -198,9 +198,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { if (!_isPaused(singleVaultData_.superformId)) { dstAmount = _directWithdrawFromVault(singleVaultData_, srcSender_); } else { - IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( - singleVaultData_, srcSender_ - ); + IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal(singleVaultData_); } } @@ -239,7 +237,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { dstAmount = _xChainWithdrawFromVault(singleVaultData_, srcSender_, srcChainId_); } else { IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( - singleVaultData_, srcSender_ + singleVaultData_ ); } } else { @@ -248,16 +246,8 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { } /// @inheritdoc IBaseForm - function emergencyWithdraw( - address srcSender_, - address refundAddress_, - uint256 amount_ - ) - external - override - onlyEmergencyQueue - { - _emergencyWithdraw(srcSender_, refundAddress_, amount_); + function emergencyWithdraw(address receiverAddress_, uint256 amount_) external override onlyEmergencyQueue { + _emergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc IBaseForm @@ -308,7 +298,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { returns (uint256 dstAmount); /// @dev withdraws vault shares from form during emergency - function _emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) internal virtual; + function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal virtual; /// @dev forwards dust to paymaster function _forwardDustToPaymaster() internal virtual; diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 2e94b5ec6..5dbce3d43 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -18,6 +18,8 @@ import { IPermit2 } from "./vendor/dragonfly-xyz/IPermit2.sol"; import "./crosschain-liquidity/LiquidityHandler.sol"; import "./types/DataTypes.sol"; +import "forge-std/console.sol"; + /// @title BaseRouterImplementation /// @author Zeropoint Labs /// @dev Extends BaseRouter with standard internal execution functions @@ -194,7 +196,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.srcChainId, req_.dstChainId, vars.currentPayloadId - ) + ), + req_.superformData.receiverAddress ); emit CrossChainInitiatedDepositSingle( @@ -290,7 +293,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.srcChainId, req_.dstChainId, vars.currentPayloadId - ) + ), + req_.superformsData.receiverAddress ); emit CrossChainInitiatedDepositMulti( @@ -397,7 +401,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.srcChainId, req_.dstChainId, vars.currentPayloadId - ) + ), + req_.superformData.receiverAddress ); emit CrossChainInitiatedWithdrawSingle( @@ -481,7 +486,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.srcChainId, req_.dstChainId, vars.currentPayloadId - ) + ), + req_.superformsData.receiverAddress ); emit CrossChainInitiatedWithdrawMulti( @@ -520,7 +526,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); } - function _dispatchAmbMessage(DispatchAMBMessageVars memory vars_) internal virtual { + function _dispatchAmbMessage(DispatchAMBMessageVars memory vars_, address receiverAddress_) internal virtual { AMBMessage memory ambMessage = AMBMessage( DataLib.packTxInfo( uint8(vars_.txType), @@ -537,7 +543,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou .calculateAMBData(vars_.dstChainId, vars_.ambIds, abi.encode(ambMessage)); ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).updateTxHistory( - vars_.currentPayloadId, ambMessage.txInfo + vars_.currentPayloadId, ambMessage.txInfo, receiverAddress_ ); /// @dev this call dispatches the message to the AMB bridge through dispatchPayload @@ -622,7 +628,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (dstAmount != 0 && !vaultData_.retain4626) { /// @dev mint super positions at the end of the deposit action if user doesn't retain 4626 ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintSingle( - srcSender_, vaultData_.superformId, dstAmount + vaultData_.receiverAddress, vaultData_.superformId, dstAmount ); } } @@ -672,7 +678,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev in direct deposits, SuperPositions are minted right after depositing to vaults ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintBatch( - srcSender_, vaultData_.superformIds, v.dstAmounts + vaultData_.receiverAddress, vaultData_.superformIds, v.dstAmounts ); } @@ -780,16 +786,21 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev the dstChainId_ (in the state request) must match the superforms' chainId (superform must exist on /// destination) (, uint32 formImplementationId, uint64 sfDstChainId) = superformId_.getSuperform(); + console.log("a"); if (dstChainId_ != sfDstChainId) return false; + console.log("b"); /// @dev 10000 = 100% slippage if (maxSlippage_ > 10_000) return false; + console.log("c"); /// @dev amount can't be 0 if (amount_ == 0) return false; + console.log("d"); if (isDeposit_ && factory_.isFormImplementationPaused(formImplementationId)) return false; + console.log("e"); /// @dev ensure that receiver address is set always /// @dev in deposits, this is important for receive4626 (on destination). It is also important for refunds on @@ -799,6 +810,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (receiverAddress_ == address(0)) { return false; } + console.log("f"); /// if it reaches this point then is valid return true; diff --git a/src/EmergencyQueue.sol b/src/EmergencyQueue.sol index de8a66251..20164814b 100644 --- a/src/EmergencyQueue.sol +++ b/src/EmergencyQueue.sol @@ -82,22 +82,13 @@ contract EmergencyQueue is IEmergencyQueue { ////////////////////////////////////////////////////////////// /// @inheritdoc IEmergencyQueue - function queueWithdrawal( - InitSingleVaultData memory data_, - address srcSender_ - ) - external - override - onlySuperform(data_.superformId) - { + function queueWithdrawal(InitSingleVaultData memory data_) external override onlySuperform(data_.superformId) { ++queueCounter; queuedWithdrawal[queueCounter] = - QueuedWithdrawal(srcSender_, data_.receiverAddress, data_.superformId, data_.amount, data_.payloadId, false); + QueuedWithdrawal(data_.receiverAddress, data_.superformId, data_.amount, data_.payloadId, false); - emit WithdrawalQueued( - srcSender_, data_.receiverAddress, queueCounter, data_.superformId, data_.amount, data_.payloadId - ); + emit WithdrawalQueued(data_.receiverAddress, queueCounter, data_.superformId, data_.amount, data_.payloadId); } /// @inheritdoc IEmergencyQueue @@ -126,8 +117,8 @@ contract EmergencyQueue is IEmergencyQueue { data.isProcessed = true; (address superform,,) = data.superformId.getSuperform(); - IBaseForm(superform).emergencyWithdraw(data.srcSender, data.refundAddress, data.amount); + IBaseForm(superform).emergencyWithdraw(data.receiverAddress, data.amount); - emit WithdrawalProcessed(data.refundAddress, id_, data.superformId, data.amount); + emit WithdrawalProcessed(data.receiverAddress, id_, data.superformId, data.amount); } } diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index f65d24c9f..caf71a3a6 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -39,7 +39,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { ////////////////////////////////////////////////////////////// /// @dev maps all transaction data routed through the smart contract. - mapping(uint256 transactionId => uint256 txInfo) public override txHistory; + mapping(uint256 transactionId => TxHistory txHistory) public override txHistory; /// @dev is the base uri set by admin string public dynamicURI; @@ -138,18 +138,28 @@ contract SuperPositions is ISuperPositions, ERC1155A { ////////////////////////////////////////////////////////////// /// @inheritdoc ISuperPositions - function updateTxHistory(uint256 payloadId_, uint256 txInfo_) external override onlyRouter { - txHistory[payloadId_] = txInfo_; + function updateTxHistory( + uint256 payloadId_, + uint256 txInfo_, + address receiverAddress_ + ) + external + override + onlyRouter + { + txHistory[payloadId_] = TxHistory({ txInfo: txInfo_, receiverAddress: receiverAddress_ }); + + emit TxHistorySet(payloadId_, txInfo_, receiverAddress_); } /// @inheritdoc ISuperPositions - function mintSingle(address srcSender_, uint256 id_, uint256 amount_) external override onlyMinter(id_) { - _mint(srcSender_, msg.sender, id_, amount_, ""); + function mintSingle(address receiverAddress_, uint256 id_, uint256 amount_) external override onlyMinter(id_) { + _mint(receiverAddress_, msg.sender, id_, amount_, ""); } /// @inheritdoc ISuperPositions function mintBatch( - address srcSender_, + address receiverAddress_, uint256[] memory ids_, uint256[] memory amounts_ ) @@ -157,7 +167,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { override onlyBatchMinter(ids_) { - _batchMint(srcSender_, msg.sender, ids_, amounts_, ""); + _batchMint(receiverAddress_, msg.sender, ids_, amounts_, ""); } /// @inheritdoc ISuperPositions @@ -182,8 +192,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { function stateMultiSync(AMBMessage memory data_) external override returns (uint64 srcChainId_) { /// @dev here we decode the txInfo and params from the data brought back from destination - (uint256 returnTxType, uint256 callbackType, uint8 multi,, address returnDataSrcSender,) = - data_.txInfo.decodeTxInfo(); + (uint256 returnTxType, uint256 callbackType, uint8 multi,,,) = data_.txInfo.decodeTxInfo(); if (callbackType != uint256(CallbackType.RETURN) && callbackType != uint256(CallbackType.FAIL)) { revert Error.INVALID_PAYLOAD_TYPE(); @@ -194,23 +203,20 @@ contract SuperPositions is ISuperPositions, ERC1155A { _validateStateSyncer(returnData.superformIds); - uint256 txInfo = txHistory[returnData.payloadId]; + uint256 txInfo = txHistory[returnData.payloadId].txInfo; /// @dev if txInfo is zero then the payloadId is invalid for ack if (txInfo == 0) { revert Error.TX_HISTORY_NOT_FOUND(); } - address srcSender; uint256 txType; /// @dev decode initial payload info stored on source chain in this contract - (txType,,,, srcSender, srcChainId_) = txInfo.decodeTxInfo(); + (txType,,,,, srcChainId_) = txInfo.decodeTxInfo(); /// @dev verify this is a not single vault mint if (multi != 1) revert Error.INVALID_PAYLOAD_TYPE(); - /// @dev compare final shares beneficiary to be the same (dst/src) - if (returnDataSrcSender != srcSender) revert Error.SRC_SENDER_MISMATCH(); /// @dev compare txType to be the same (dst/src) if (returnTxType != txType) revert Error.SRC_TX_TYPE_MISMATCH(); @@ -219,7 +225,13 @@ contract SuperPositions is ISuperPositions, ERC1155A { (txType == uint256(TransactionType.DEPOSIT) && callbackType == uint256(CallbackType.RETURN)) || (txType == uint256(TransactionType.WITHDRAW) && callbackType == uint256(CallbackType.FAIL)) ) { - _batchMint(srcSender, msg.sender, returnData.superformIds, returnData.amounts, ""); + _batchMint( + txHistory[returnData.payloadId].receiverAddress, + msg.sender, + returnData.superformIds, + returnData.amounts, + "" + ); } else { revert Error.INVALID_PAYLOAD_TYPE(); } @@ -231,8 +243,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { function stateSync(AMBMessage memory data_) external override returns (uint64 srcChainId_) { /// @dev here we decode the txInfo and params from the data brought back from destination - (uint256 returnTxType, uint256 callbackType, uint8 multi,, address returnDataSrcSender,) = - data_.txInfo.decodeTxInfo(); + (uint256 returnTxType, uint256 callbackType, uint8 multi,,,) = data_.txInfo.decodeTxInfo(); if (callbackType != uint256(CallbackType.RETURN) && callbackType != uint256(CallbackType.FAIL)) { revert Error.INVALID_PAYLOAD_TYPE(); @@ -242,7 +253,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { ReturnSingleData memory returnData = abi.decode(data_.params, (ReturnSingleData)); _validateStateSyncer(returnData.superformId); - uint256 txInfo = txHistory[returnData.payloadId]; + uint256 txInfo = txHistory[returnData.payloadId].txInfo; /// @dev if txInfo is zero then the payloadId is invalid for ack if (txInfo == 0) { @@ -250,16 +261,12 @@ contract SuperPositions is ISuperPositions, ERC1155A { } uint256 txType; - address srcSender; /// @dev decode initial payload info stored on source chain in this contract - (txType,,,, srcSender, srcChainId_) = txInfo.decodeTxInfo(); + (txType,,,,, srcChainId_) = txInfo.decodeTxInfo(); /// @dev this is a not multi vault mint if (multi != 0) revert Error.INVALID_PAYLOAD_TYPE(); - - /// @dev compare final shares beneficiary to be the same (dst/src) - if (returnDataSrcSender != srcSender) revert Error.SRC_SENDER_MISMATCH(); /// @dev compare txType to be the same (dst/src) if (returnTxType != txType) revert Error.SRC_TX_TYPE_MISMATCH(); @@ -268,7 +275,13 @@ contract SuperPositions is ISuperPositions, ERC1155A { (txType == uint256(TransactionType.DEPOSIT) && callbackType == uint256(CallbackType.RETURN)) || (txType == uint256(TransactionType.WITHDRAW) && callbackType == uint256(CallbackType.FAIL)) ) { - _mint(srcSender, msg.sender, returnData.superformId, returnData.amount, ""); + _mint( + txHistory[returnData.payloadId].receiverAddress, + msg.sender, + returnData.superformId, + returnData.amount, + "" + ); } else { revert Error.INVALID_PAYLOAD_TYPE(); } diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index f290e8fc4..54220f184 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -331,7 +331,7 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio function _lzSend( uint16 dstChainId_, bytes memory payload_, - address payable refundAddress_, + address payable receiverAddress_, address zroPaymentAddress_, bytes memory adapterParams_, uint256 msgValue_ @@ -344,7 +344,7 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio } lzEndpoint.send{ value: msgValue_ }( - dstChainId_, trustedRemote, payload_, refundAddress_, zroPaymentAddress_, adapterParams_ + dstChainId_, trustedRemote, payload_, receiverAddress_, zroPaymentAddress_, adapterParams_ ); } diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 36a33a3bb..98ae69199 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -223,10 +223,8 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { FailedDeposit storage failedDeposits_ = failedDeposits[payloadId_]; - if ( - failedDeposits_.superformIds.length == 0 - || failedDeposits_.superformIds.length != proposedAmounts_.length - ) { + if (failedDeposits_.superformIds.length == 0 || failedDeposits_.superformIds.length != proposedAmounts_.length) + { revert Error.INVALID_RESCUE_DATA(); } @@ -240,14 +238,14 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { (,, uint8 multi,,,) = DataLib.decodeTxInfo(payloadHeader[payloadId_]); - address refundAddress; + address receiverAddress; if (multi == 1) { - refundAddress = abi.decode(payloadBody[payloadId_], (InitMultiVaultData)).receiverAddress; + receiverAddress = abi.decode(payloadBody[payloadId_], (InitMultiVaultData)).receiverAddress; } else { - refundAddress = abi.decode(payloadBody[payloadId_], (InitSingleVaultData)).receiverAddress; + receiverAddress = abi.decode(payloadBody[payloadId_], (InitSingleVaultData)).receiverAddress; } - failedDeposits[payloadId_].refundAddress = refundAddress; + failedDeposits[payloadId_].receiverAddress = receiverAddress; emit RescueProposed(payloadId_, failedDeposits_.superformIds, proposedAmounts_, block.timestamp); } @@ -261,7 +259,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev the msg sender should be the refund address (or) the disputer if ( !( - msg.sender == failedDeposits_.refundAddress + msg.sender == failedDeposits_.receiverAddress || _hasRole(keccak256("CORE_STATE_REGISTRY_DISPUTER_ROLE"), msg.sender) ) ) { @@ -308,11 +306,11 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev refunds the amount to user specified refund address if (failedDeposits_.settleFromDstSwapper[i]) { dstSwapper.processFailedTx( - failedDeposits_.refundAddress, failedDeposits_.settlementToken[i], failedDeposits_.amounts[i] + failedDeposits_.receiverAddress, failedDeposits_.settlementToken[i], failedDeposits_.amounts[i] ); } else { IERC20(failedDeposits_.settlementToken[i]).safeTransfer( - failedDeposits_.refundAddress, failedDeposits_.amounts[i] + failedDeposits_.receiverAddress, failedDeposits_.amounts[i] ); } } diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index b4d5370fe..eed68ff20 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -166,9 +166,17 @@ contract PayloadHelper is IPayloadHelper { external view override - returns (uint8 txType, uint8 callbackType, uint8 multi, address srcSender, uint64 srcChainId) + returns ( + uint8 txType, + uint8 callbackType, + uint8 multi, + address srcSender, + address receiverAddress, + uint64 srcChainId + ) { - uint256 txInfo = + uint256 txInfo; + (txInfo, receiverAddress) = ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).txHistory(srcPayloadId_); if (txInfo == 0) { diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index 1b62df457..81d57ae56 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -75,8 +75,8 @@ contract ERC4626Form is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _emergencyWithdraw(address, /*srcSender_*/ address refundAddress_, uint256 amount_) internal override { - _processEmergencyWithdraw(refundAddress_, amount_); + function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal override { + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index d94c52821..d0199e30e 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -406,15 +406,19 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit Processed(srcChainId_, vars.dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vault); } - function _processEmergencyWithdraw(address refundAddress_, uint256 amount_) internal { + function _processEmergencyWithdraw(address receiverAddress_, uint256 amount_) internal { IERC4626 vaultContract = IERC4626(vault); + if (receiverAddress_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (vaultContract.balanceOf(address(this)) < amount_) { revert Error.INSUFFICIENT_BALANCE(); } - vaultContract.safeTransfer(refundAddress_, amount_); - emit EmergencyWithdrawalProcessed(refundAddress_, amount_); + vaultContract.safeTransfer(receiverAddress_, amount_); + emit EmergencyWithdrawalProcessed(receiverAddress_, amount_); } function _processForwardDustToPaymaster() internal { diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index b02c999e1..523a6a2a6 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -94,16 +94,8 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _emergencyWithdraw( - address srcSender_, - address refundAddress_, - uint256 amount_ - ) - internal - override - onlyKYC(srcSender_) - { - _processEmergencyWithdraw(refundAddress_, amount_); + function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal override { + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 556402f01..767af59e7 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -67,9 +67,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { returns (uint256 dstAmount) { if (_isPaused(p_.data.superformId)) { - IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal( - p_.data, p_.srcSender - ); + IEmergencyQueue(superRegistry.getAddress(keccak256("EMERGENCY_QUEUE"))).queueWithdrawal(p_.data); return 0; } withdrawAfterCoolDownLocalVars memory vars; @@ -201,8 +199,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _emergencyWithdraw(address, /*srcSender_*/ address refundAddress_, uint256 amount_) internal override { - _processEmergencyWithdraw(refundAddress_, amount_); + function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal override { + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm diff --git a/src/interfaces/IBaseForm.sol b/src/interfaces/IBaseForm.sol index ee34f726e..7a82df1f0 100644 --- a/src/interfaces/IBaseForm.sol +++ b/src/interfaces/IBaseForm.sol @@ -20,7 +20,7 @@ interface IBaseForm is IERC165 { event Processed(uint64 srcChainID, uint64 dstChainId, uint256 srcPayloadId, uint256 amount, address vault); /// @dev is emitted when an emergency withdrawal is processed - event EmergencyWithdrawalProcessed(address refundAddress, uint256 amount); + event EmergencyWithdrawalProcessed(address receiverAddress, uint256 amount); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // @@ -140,10 +140,9 @@ interface IBaseForm is IERC165 { returns (uint256 dstAmount); /// @dev process withdrawal of shares if form is paused - /// @param srcSender_ The address of the sender of the transaction - /// @param refundAddress_ The address to refund the shares to + /// @param receiverAddress_ The address to refund the shares to /// @param amount_ The amount of vault shares to refund - function emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) external; + function emergencyWithdraw(address receiverAddress_, uint256 amount_) external; /// @dev moves all dust in the contract to Paymaster contract function forwardDustToPaymaster() external; diff --git a/src/interfaces/ICoreStateRegistry.sol b/src/interfaces/ICoreStateRegistry.sol index 7a9fb3781..f95be0b4c 100644 --- a/src/interfaces/ICoreStateRegistry.sol +++ b/src/interfaces/ICoreStateRegistry.sol @@ -13,14 +13,14 @@ interface ICoreStateRegistry { /// @param superformIds is an array of failing superform ids /// @param settlementToken is an array of tokens to be refunded for the failing superform /// @param amounts is an array of amounts of settlementToken to be refunded - /// @param refundAddress is the users refund address + /// @param receiverAddress is the users refund address /// @param lastProposedTime indicates the rescue proposal timestamp struct FailedDeposit { uint256[] superformIds; address[] settlementToken; uint256[] amounts; bool[] settleFromDstSwapper; - address refundAddress; + address receiverAddress; uint256 lastProposedTimestamp; } diff --git a/src/interfaces/IEmergencyQueue.sol b/src/interfaces/IEmergencyQueue.sol index 6892ae626..70f16b8ff 100644 --- a/src/interfaces/IEmergencyQueue.sol +++ b/src/interfaces/IEmergencyQueue.sol @@ -9,15 +9,14 @@ interface IEmergencyQueue { ////////////////////////////////////////////////////////////// event WithdrawalQueued( - address indexed srcAddress, - address indexed refundAddress, + address indexed receiverAddress, uint256 indexed id, - uint256 superformId, + uint256 indexed superformId, uint256 amount, uint256 srcPayloadId ); - event WithdrawalProcessed(address indexed refundAddress, uint256 indexed id, uint256 superformId, uint256 amount); + event WithdrawalProcessed(address indexed receiverAddress, uint256 indexed id, uint256 superformId, uint256 amount); ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // @@ -34,7 +33,7 @@ interface IEmergencyQueue { /// @dev called by paused forms to queue up withdrawals for exit /// @param data_ is the single vault data passed by the user - function queueWithdrawal(InitSingleVaultData memory data_, address srcSender_) external; + function queueWithdrawal(InitSingleVaultData memory data_) external; /// @dev called by emergency admin to processed queued withdrawal /// @param id_ is the identifier of the queued action diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index 46915763f..4f6cc4f0f 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -68,11 +68,19 @@ interface IPayloadHelper { /// @return callbackType is the type of payload. check {CallbackType} enum in DataTypes.sol /// @return isMulti indicates if the transaction involves operations to multiple vaults /// @return srcSender is the user who initiated the transaction on the srcChain + /// @return receiverAddress is the address to be used for receiving assets /// @return srcChainId is the unique identifier of the srcChain function decodePayloadHistory(uint256 srcPayloadId_) external view - returns (uint8 txType, uint8 callbackType, uint8 isMulti, address srcSender, uint64 srcChainId); + returns ( + uint8 txType, + uint8 callbackType, + uint8 isMulti, + address srcSender, + address receiverAddress, + uint64 srcChainId + ); /// @dev returns decoded timelock form payloads /// @param timelockPayloadId_ is the unique identifier of payload in timelock state registry diff --git a/src/interfaces/ISuperPositions.sol b/src/interfaces/ISuperPositions.sol index d7855a453..5ed02f645 100644 --- a/src/interfaces/ISuperPositions.sol +++ b/src/interfaces/ISuperPositions.sol @@ -8,6 +8,14 @@ import { IERC1155A } from "ERC1155A/interfaces/IERC1155A.sol"; /// @author Zeropoint Labs. /// @dev interface for Super Positions interface ISuperPositions is IERC1155A { + ////////////////////////////////////////////////////////////// + // STRUCTS // + ////////////////////////////////////////////////////////////// + + struct TxHistory { + uint256 txInfo; + address receiverAddress; + } ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// @@ -21,13 +29,18 @@ interface ISuperPositions is IERC1155A { /// @dev is emitted when a aErc20 token is registered event AERC20TokenRegistered(uint256 indexed tokenId, address indexed tokenAddress); + /// @dev is emitted when a tx info is saved + event TxHistorySet(uint256 indexed payloadId, uint256 txInfo, address indexed receiverAddress); + ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// - /// @dev returns the payload header for a tx id on the source chain + /// @dev returns the payload header and the receiver address for a tx id on the source chain /// @param txId_ is the identifier of the transaction issued by superform router - function txHistory(uint256 txId_) external view returns (uint256); + /// @return txInfo is the header of the payload + /// @return receiverAddress is the address of the receiver + function txHistory(uint256 txId_) external view returns (uint256 txInfo, address receiverAddress); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // @@ -35,20 +48,21 @@ interface ISuperPositions is IERC1155A { /// @dev saves the message being sent together with the associated id formulated in a router /// @param payloadId_ is the id of the message being saved - /// @param txInfo_ is the relevant information of the transaction being saved - function updateTxHistory(uint256 payloadId_, uint256 txInfo_) external; + /// @param txInfo_ is the header of the AMBMessage of the transaction being saved + /// @param receiverAddress_ is the address of the receiver + function updateTxHistory(uint256 payloadId_, uint256 txInfo_, address receiverAddress_) external; /// @dev allows minter to mint shares on source - /// @param srcSender_ is the beneficiary of shares + /// @param receiverAddress_ is the beneficiary of shares /// @param id_ is the id of the shares /// @param amount_ is the amount of shares to mint - function mintSingle(address srcSender_, uint256 id_, uint256 amount_) external; + function mintSingle(address receiverAddress_, uint256 id_, uint256 amount_) external; /// @dev allows minter to mint shares on source in batch - /// @param srcSender_ is the beneficiary of shares + /// @param receiverAddress_ is the beneficiary of shares /// @param ids_ are the ids of the shares /// @param amounts_ are the amounts of shares to mint - function mintBatch(address srcSender_, uint256[] memory ids_, uint256[] memory amounts_) external; + function mintBatch(address receiverAddress_, uint256[] memory ids_, uint256[] memory amounts_) external; /// @dev allows superformRouter to burn shares on source /// @notice burn is done optimistically by the router in the beginning of the withdraw transactions diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index a17e749fb..a4708c2fa 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -135,8 +135,7 @@ struct InitSingleVaultData { /// @dev struct for Emergency Queue struct QueuedWithdrawal { - address srcSender; - address refundAddress; + address receiverAddress; uint256 superformId; uint256 amount; uint256 srcPayloadId; diff --git a/test/mocks/ERC4626FormExternal.sol b/test/mocks/ERC4626FormExternal.sol index b5f5495bf..b33e35658 100644 --- a/test/mocks/ERC4626FormExternal.sol +++ b/test/mocks/ERC4626FormExternal.sol @@ -68,8 +68,8 @@ contract ERC4626FormExternal is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _emergencyWithdraw(address, /*srcSender*/ address refundAddress_, uint256 amount_) internal override { - _processEmergencyWithdraw(refundAddress_, amount_); + function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal override { + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm diff --git a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol index 5ec8473a1..1256dac3c 100644 --- a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol @@ -155,16 +155,8 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { } /// @inheritdoc IBaseForm - function emergencyWithdraw( - address srcSender_, - address refundAddress_, - uint256 amount_ - ) - external - override - onlyEmergencyQueue - { - _emergencyWithdraw(srcSender_, refundAddress_, amount_); + function emergencyWithdraw(address receiverAddress_, uint256 amount_) external override onlyEmergencyQueue { + _emergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc IBaseForm @@ -268,7 +260,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { returns (uint256 dstAmount); /// @dev withdraws vault shares from form during emergency - function _emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) internal virtual; + function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal virtual; /// @dev forwards dust to paymaster function _forwardDustToPaymaster() internal virtual; diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index 6a0f5da0d..bb9bf0a62 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -343,16 +343,16 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li emit Processed(srcChainId, vars.dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vault); } - function _processEmergencyWithdraw(address refundAddress_, uint256 amount_) internal { + function _processEmergencyWithdraw(address receiverAddress_, uint256 amount_) internal { IERC4626 vaultContract = IERC4626(vault); if (vaultContract.balanceOf(address(this)) < amount_) { revert Error.INSUFFICIENT_BALANCE(); } - vaultContract.transfer(refundAddress_, amount_); + vaultContract.transfer(receiverAddress_, amount_); - emit EmergencyWithdrawalProcessed(refundAddress_, amount_); + emit EmergencyWithdrawalProcessed(receiverAddress_, amount_); } function _processForwardDustToPaymaster() internal { diff --git a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol index fdb609d5e..110894843 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol @@ -68,8 +68,8 @@ contract ERC4626FormInterfaceNotSupported is ERC4626FormImplementationInterfaceN } /// @inheritdoc BaseForm - function _emergencyWithdraw(address, /* srcSender*/ address refundAddress_, uint256 amount_) internal override { - _processEmergencyWithdraw(refundAddress_, amount_); + function _emergencyWithdraw(address receiverAddress_, uint256 amount_) internal override { + _processEmergencyWithdraw(receiverAddress_, amount_); } /// @inheritdoc BaseForm diff --git a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol index 3ebc1bfeb..d207516b0 100644 --- a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol @@ -43,12 +43,12 @@ contract TimelockStateRegistryTest is ProtocolActions { vm.prank(getContract(AVAX, "SuperformRouter")); SuperPositions(getContract(AVAX, "SuperPositions")).updateTxHistory( - 1, DataLib.packTxInfo(1, 2, 0, 3, deployer, ETH) + 1, DataLib.packTxInfo(1, 2, 0, 3, deployer, ETH), receiverAddress ); vm.prank(getContract(AVAX, "SuperformRouter")); SuperPositions(getContract(AVAX, "SuperPositions")).updateTxHistory( - 1, DataLib.packTxInfo(1, 2, 0, 3, deployer, ETH) + 1, DataLib.packTxInfo(1, 2, 0, 3, deployer, ETH), receiverAddress ); vm.prank(superform); @@ -150,7 +150,7 @@ contract TimelockStateRegistryTest is ProtocolActions { vm.prank(getContract(AVAX, "SuperformRouter")); SuperPositions(getContract(AVAX, "SuperPositions")).updateTxHistory( - 1, DataLib.packTxInfo(1, 2, 0, 3, deployer, ETH) + 1, DataLib.packTxInfo(1, 2, 0, 3, deployer, ETH), receiverAddress ); vm.prank(getContract(AVAX, "HyperlaneImplementation")); diff --git a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol index 5a710c897..4e2893350 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol @@ -156,7 +156,7 @@ contract PayloadHelperMultiTest is ProtocolActions { address _PayloadHelper = contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]; IPayloadHelper helper = IPayloadHelper(_PayloadHelper); - (uint8 txType, uint8 callbackType, uint8 multi, address srcSender, uint64 srcChainId) = + (uint8 txType, uint8 callbackType, uint8 multi, address srcSender, address receiverAddress, uint64 srcChainId) = helper.decodePayloadHistory(1); assertEq(txType, 0); @@ -169,6 +169,8 @@ contract PayloadHelperMultiTest is ProtocolActions { assertEq(multi, 1); /// 0 for not multi vault assertEq(srcSender, users[0]); + + assertEq(receiverAddress, users[0]); } struct CheckDstPayloadInternalVars { diff --git a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol index 131a57053..6110a54e4 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol @@ -185,7 +185,7 @@ contract PayloadHelperSingleTest is ProtocolActions { function _checkSrcPayload() internal { vm.selectFork(FORKS[CHAIN_0]); - (uint8 txType, uint8 callbackType, uint8 multi, address srcSender, uint64 srcChainId) = + (uint8 txType, uint8 callbackType, uint8 multi, address srcSender, address receiverAddress, uint64 srcChainId) = IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodePayloadHistory(1); /// @dev 0 for deposit @@ -200,6 +200,8 @@ contract PayloadHelperSingleTest is ProtocolActions { /// @dev 0 for not multi vault assertEq(multi, 0); assertEq(srcSender, users[0]); + + assertEq(receiverAddress, users[0]); } function _checkDstPayloadInit() internal { diff --git a/test/unit/emergency/EmergencyQueue.t.sol b/test/unit/emergency/EmergencyQueue.t.sol index 9124f8934..616f40b25 100644 --- a/test/unit/emergency/EmergencyQueue.t.sol +++ b/test/unit/emergency/EmergencyQueue.t.sol @@ -62,8 +62,7 @@ contract EmergencyQueueTest is ProtocolActions { false, mrimperfect, "" - ), - mrperfect + ) ); } @@ -93,8 +92,7 @@ contract EmergencyQueueTest is ProtocolActions { false, mrimperfect, "" - ), - mrperfect + ) ); } @@ -124,8 +122,7 @@ contract EmergencyQueueTest is ProtocolActions { false, mrimperfect, "" - ), - mrperfect + ) ); } @@ -324,7 +321,7 @@ contract EmergencyQueueTest is ProtocolActions { assertEq(balanceBefore + 1e18, balanceAfter); } - function test_emergencyWithdraw() public { + function test_emergencyWithdraw_INSUFFICIENT_BALANCE() public { /// user deposits successfully to a form _successfulDepositXChain(1, "VaultMock", 0, mrperfect, false); @@ -340,7 +337,26 @@ contract EmergencyQueueTest is ProtocolActions { vm.prank(emergencyQueue); vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); - IBaseForm(superform).emergencyWithdraw(address(0), address(0), 10e20); + IBaseForm(superform).emergencyWithdraw(address(0x1), 10e20); + } + + function test_emergencyWithdraw_ZEROADDRESS() public { + /// user deposits successfully to a form + _successfulDepositXChain(1, "VaultMock", 0, mrperfect, false); + + /// processing the queued withdrawal and assert + vm.selectFork(FORKS[ARBI]); + + /// @dev deployer has emergency admin role + address emergencyQueue = getContract(ARBI, "EmergencyQueue"); + + address superform = getContract( + ARBI, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ); + + vm.prank(emergencyQueue); + vm.expectRevert(Error.ZERO_ADDRESS.selector); + IBaseForm(superform).emergencyWithdraw(address(0), 10e20); } function test_emergencyQueueProcessingXChainMultiVault() public { diff --git a/test/unit/super-positions/super-positions.t.sol b/test/unit/super-positions/super-positions.t.sol index 38c2f725d..3557af324 100644 --- a/test/unit/super-positions/super-positions.t.sol +++ b/test/unit/super-positions/super-positions.t.sol @@ -19,6 +19,8 @@ contract SuperPositionsTest is BaseSetup { address vault; uint32 formImplementationId = 4; + address receiverAddress = deployer; + function setUp() public override { super.setUp(); vm.selectFork(FORKS[ETH]); @@ -77,7 +79,7 @@ contract SuperPositionsTest is BaseSetup { function test_revert_stateSync_InvalidPayloadStatus() public { uint256 txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0), ETH); vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, txInfo); + SuperPositions(address(superPositions)).updateTxHistory(0, txInfo, receiverAddress); ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, 1, 100); AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); @@ -129,7 +131,7 @@ contract SuperPositionsTest is BaseSetup { /// @dev multi = 1 uint256 txInfo = DataLib.packTxInfo(0, 2, 1, 1, address(0), ETH); vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, 1); + SuperPositions(address(superPositions)).updateTxHistory(0, 1, receiverAddress); ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, 1, 100); AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); @@ -139,25 +141,11 @@ contract SuperPositionsTest is BaseSetup { superPositions.stateSync(maliciousMessage); } - function test_revert_stateSync_SrcSenderMismatch() public { - /// @dev returnDataSrcSender = address(0x1) - uint256 txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0x1), ETH); - vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, 1); - - ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, 1, 100); - AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); - - vm.broadcast(getContract(ETH, "CoreStateRegistry")); - vm.expectRevert(Error.SRC_SENDER_MISMATCH.selector); - superPositions.stateSync(maliciousMessage); - } - function test_revert_stateSync_SrcTxTypeMismatch() public { /// @dev TxType = 1 uint256 txInfo = DataLib.packTxInfo(1, 2, 0, 1, address(0), ETH); vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, txInfo); + SuperPositions(address(superPositions)).updateTxHistory(0, txInfo, receiverAddress); txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0), ETH); ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, 1, 100); @@ -189,7 +177,7 @@ contract SuperPositionsTest is BaseSetup { function test_revert_stateMultiSync_InvalidPayloadStatus() public { uint256 txInfo = DataLib.packTxInfo(0, 2, 1, 1, address(0), ETH); vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, txInfo); + SuperPositions(address(superPositions)).updateTxHistory(0, txInfo, receiverAddress); uint256[] memory x = new uint256[](1); x[0] = 100; @@ -219,7 +207,7 @@ contract SuperPositionsTest is BaseSetup { function test_revert_stateMultiSync_InvalidPayload_Multi() public { uint256 txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0), ETH); vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, 1); + SuperPositions(address(superPositions)).updateTxHistory(0, 1, receiverAddress); uint256[] memory x = new uint256[](1); x[0] = 100; @@ -232,26 +220,10 @@ contract SuperPositionsTest is BaseSetup { superPositions.stateMultiSync(maliciousMessage); } - function test_revert_stateMultiSync_SrcSenderMismatch() public { - uint256 txInfo = DataLib.packTxInfo(0, 2, 1, 1, address(0x1), ETH); - vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, 1); - - uint256[] memory x = new uint256[](1); - x[0] = 100; - - ReturnMultiData memory maliciousReturnData = ReturnMultiData(0, x, x); - AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); - - vm.broadcast(getContract(ETH, "CoreStateRegistry")); - vm.expectRevert(Error.SRC_SENDER_MISMATCH.selector); - superPositions.stateMultiSync(maliciousMessage); - } - function test_revert_stateMultiSync_SrcTxTypeMismatch() public { uint256 txInfo = DataLib.packTxInfo(1, 2, 1, 1, address(0), ETH); vm.prank(getContract(ETH, "SuperformRouter")); - SuperPositions(address(superPositions)).updateTxHistory(0, txInfo); + SuperPositions(address(superPositions)).updateTxHistory(0, txInfo, receiverAddress); txInfo = DataLib.packTxInfo(0, 2, 1, 1, address(0), ETH); uint256[] memory x = new uint256[](1); x[0] = 100; diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index a08a6d242..f1fc6e20e 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -19,7 +19,7 @@ import "src/types/DataTypes.sol"; contract SuperformERC4626FormTest is ProtocolActions { uint64 internal chainId = ETH; - address refundAddress = address(444); + address receiverAddress = address(444); function setUp() public override { super.setUp(); @@ -376,7 +376,7 @@ contract SuperformERC4626FormTest is ProtocolActions { "", false, false, - refundAddress, + receiverAddress, "" ); @@ -414,7 +414,7 @@ contract SuperformERC4626FormTest is ProtocolActions { "", false, false, - refundAddress, + receiverAddress, "" ); @@ -470,7 +470,7 @@ contract SuperformERC4626FormTest is ProtocolActions { "", false, false, - refundAddress, + receiverAddress, "" ); @@ -493,7 +493,7 @@ contract SuperformERC4626FormTest is ProtocolActions { /// scenario: user could hack the funds from the form vm.selectFork(FORKS[ETH]); - vm.startPrank(deployer); + vm.startPrank(receiverAddress); address superform = getContract( ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) @@ -503,13 +503,13 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, - SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(deployer, superformId), + SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(receiverAddress, superformId), 100, - LiqRequest(_buildMaliciousTxData(1, DAI, superform, ETH, 2e18, deployer), DAI, address(0), 1, ETH, 0), + LiqRequest(_buildMaliciousTxData(1, DAI, superform, ETH, 2e18, receiverAddress), DAI, address(0), 1, ETH, 0), "", false, false, - refundAddress, + receiverAddress, "" ); @@ -552,7 +552,7 @@ contract SuperformERC4626FormTest is ProtocolActions { LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, false, - refundAddress, + receiverAddress, "" ); @@ -587,7 +587,7 @@ contract SuperformERC4626FormTest is ProtocolActions { LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, false, - refundAddress, + receiverAddress, "" ); @@ -600,7 +600,6 @@ contract SuperformERC4626FormTest is ProtocolActions { _successfulDeposit(false); vm.selectFork(FORKS[ETH]); - vm.startPrank(deployer); address superform = getContract( ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) @@ -608,10 +607,10 @@ contract SuperformERC4626FormTest is ProtocolActions { uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); - uint256 amount = SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(deployer, superformId); + uint256 amount = SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(receiverAddress, superformId); + vm.prank(deployer); MockERC20(getContract(ETH, "DAI")).transfer(superform, 1e18); - vm.stopPrank(); /// @dev simulating withdrawals with malicious tx data vm.startPrank(getContract(ETH, "CoreStateRegistry")); @@ -622,7 +621,7 @@ contract SuperformERC4626FormTest is ProtocolActions { amount, 100, LiqRequest( - _buildMaliciousTxData(1, getContract(ETH, "DAI"), superform, ARBI, 2e18, deployer), + _buildMaliciousTxData(1, getContract(ETH, "DAI"), superform, ARBI, 2e18, receiverAddress), getContract(ETH, "DAI"), address(0), 1, @@ -631,7 +630,7 @@ contract SuperformERC4626FormTest is ProtocolActions { ), false, false, - refundAddress, + receiverAddress, "" ); @@ -644,25 +643,26 @@ contract SuperformERC4626FormTest is ProtocolActions { _successfulDeposit(false); vm.selectFork(FORKS[ETH]); - vm.startPrank(deployer); address superform = getContract( ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) ); uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); + vm.prank(deployer); MockERC20(getContract(ETH, "DAI")).transfer(superform, 1e18); + vm.startPrank(receiverAddress); SingleVaultSFData memory data = SingleVaultSFData( superformId, - SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(deployer, superformId), + SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(receiverAddress, superformId), 100, LiqRequest("0x2222", getContract(ETH, "WETH"), address(0), 1, ETH, 0), "", false, false, - refundAddress, + receiverAddress, "" ); @@ -703,7 +703,7 @@ contract SuperformERC4626FormTest is ProtocolActions { LiqRequest(invalidTxData, getContract(ETH, "WETH"), address(0), 1, ARBI, 0), false, false, - refundAddress, + receiverAddress, "" ); @@ -771,7 +771,7 @@ contract SuperformERC4626FormTest is ProtocolActions { liqReqs[0] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", new bool[](1), new bool[](1), refundAddress, "" + superformIds, amounts, maxSlippages, liqReqs, "", new bool[](1), new bool[](1), receiverAddress, "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -821,7 +821,7 @@ contract SuperformERC4626FormTest is ProtocolActions { ); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", new bool[](1), new bool[](1), refundAddress, "" + superformIds, amounts, maxSlippages, liqReqs, "", new bool[](1), new bool[](1), receiverAddress, "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -853,7 +853,7 @@ contract SuperformERC4626FormTest is ProtocolActions { "", false, false, - refundAddress, + receiverAddress, "" ); @@ -898,7 +898,7 @@ contract SuperformERC4626FormTest is ProtocolActions { "", false, false, - refundAddress, + receiverAddress, "" ); req = SingleDirectSingleVaultStateReq(data); @@ -932,7 +932,7 @@ contract SuperformERC4626FormTest is ProtocolActions { "", false, retain4626, - refundAddress, + receiverAddress, "" ); @@ -943,6 +943,7 @@ contract SuperformERC4626FormTest is ProtocolActions { /// @dev approves before call MockERC20(getContract(ETH, "DAI")).approve(router, 1e18); SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); + vm.stopPrank(); } function _buildMaliciousTxData( diff --git a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol index a459c5283..ae2faa912 100644 --- a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol @@ -7,7 +7,7 @@ import "test/utils/ProtocolActions.sol"; contract SuperformERC4626KYCDaoFormTest is BaseSetup { uint64 internal chainId = ETH; - address refundAddress = address(444); + address receiverAddress = address(444); function setUp() public override { super.setUp(); @@ -33,7 +33,7 @@ contract SuperformERC4626KYCDaoFormTest is BaseSetup { "", false, false, - refundAddress, + receiverAddress, "" ); @@ -71,7 +71,7 @@ contract SuperformERC4626KYCDaoFormTest is BaseSetup { LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, false, - refundAddress, + receiverAddress, "" ); @@ -110,6 +110,6 @@ contract SuperformERC4626KYCDaoFormTest is BaseSetup { vm.prank(getContract(ETH, "EmergencyQueue")); - IBaseForm(superform).emergencyWithdraw(users[0], refundAddress, 1e18); + IBaseForm(superform).emergencyWithdraw(receiverAddress, 1e18); } } diff --git a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol index 6ff33dad9..36b7f7c63 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol @@ -14,7 +14,7 @@ import "src/types/DataTypes.sol"; contract SuperformERC4626TimelockFormTest is ProtocolActions { uint64 internal chainId = ETH; - address refundAddress = address(444); + address receiverAddress = address(444); function setUp() public override { super.setUp(); @@ -44,7 +44,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, false, - refundAddress, + receiverAddress, "" ); @@ -85,7 +85,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { LiqRequest(invalidNonEmptyTxData, address(0), address(0), 1, ETH, 0), false, false, - refundAddress, + receiverAddress, "" ); @@ -124,7 +124,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { LiqRequest("", address(0), address(0), 1, ETH, 0), false, false, - refundAddress, + receiverAddress, "" ); @@ -184,7 +184,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { ), false, false, - refundAddress, + receiverAddress, "" ); @@ -221,7 +221,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { bytes(""), false, false, - refundAddress, + receiverAddress, bytes("") ); diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index 56f244f18..17944de6e 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -15,7 +15,7 @@ import "src/types/DataTypes.sol"; contract ForwardDustFormTest is ProtocolActions { uint64 internal chainId = ETH; - address refundAddress = address(444); + address receiverAddress = address(444); function setUp() public override { super.setUp(); @@ -87,7 +87,7 @@ contract ForwardDustFormTest is ProtocolActions { "", false, false, - refundAddress, + receiverAddress, "" ); @@ -103,7 +103,8 @@ contract ForwardDustFormTest is ProtocolActions { vm.stopPrank(); - uint256 superPositionBalance = SuperPositions(getContract(ARBI, "SuperPositions")).balanceOf(user, superformId); + uint256 superPositionBalance = + SuperPositions(getContract(ARBI, "SuperPositions")).balanceOf(receiverAddress, superformId); InitSingleVaultData memory data2 = InitSingleVaultData( 1, @@ -121,7 +122,7 @@ contract ForwardDustFormTest is ProtocolActions { ETH, nasty_ ? 0.2e18 : IBaseForm(superform).previewRedeemFrom(superPositionBalance), // nastiness // here - refundAddress, + receiverAddress, false ) ), @@ -133,7 +134,7 @@ contract ForwardDustFormTest is ProtocolActions { ), false, false, - refundAddress, + receiverAddress, "" ); vm.selectFork(FORKS[ARBI]); From 5752ef1f077ca7cc1289ef7781aa7e48760e6a02 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 18 Dec 2023 20:48:48 -0500 Subject: [PATCH 087/210] chore: fix dstAmount --- src/forms/ERC4626TimelockForm.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 8dc4c8e73..c8a187213 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -91,7 +91,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @dev redeem from vault assets = v.redeem(p_.data.amount, vars.receiver, address(this)); - if (dstAmount == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); /// @dev validate and dispatches the tokens if (vars.len1 != 0) { From 4039269cfc6c274951c55722df87636652f3bdee Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 18 Dec 2023 20:49:05 -0500 Subject: [PATCH 088/210] chore: fix dst --- src/forms/ERC4626FormImplementation.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 1cbae3d75..206a7e7c0 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -310,7 +310,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev redeem shares for assets assets = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); - if (dstAmount == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); if (v.len1 != 0) { /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same @@ -380,7 +380,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev redeem shares for assets assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - if (dstAmount == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); if (len != 0) { /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same From 13ab8f54db7412f644b8ccd1b365e1edf2d23ad5 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 10:37:39 +0000 Subject: [PATCH 089/210] fix: external Token --- .../extensions/CoreStateRegistry.sol | 12 +-- .../extensions/TimelockStateRegistry.sol | 12 +-- src/forms/ERC4626FormImplementation.sol | 20 ++--- src/forms/ERC4626TimelockForm.sol | 7 +- src/libraries/Error.sol | 3 - src/types/DataTypes.sol | 3 +- ...626ImplementationInterfaceNotSupported.sol | 8 -- .../utils/PayloadHelper.multiVault.t.sol | 8 +- .../utils/PayloadHelper.singleVault.t.sol | 8 +- .../superform-form.ERC4626Form.t.sol | 76 ------------------- .../superform-form.forwardDust.t.sol | 2 +- .../superform-router/SuperformRouter.t.sol | 4 +- test/utils/InvariantProtocolActions.sol | 2 +- test/utils/ProtocolActions.sol | 2 +- 14 files changed, 42 insertions(+), 125 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 8b5e33daa..5a00f3669 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -636,17 +636,19 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { returns (InitMultiVaultData memory) { uint256 len = multiVaultData_.liqData.length; + IBaseForm superform; for (uint256 i; i < len; ++i) { if (txData_[i].length != 0 && multiVaultData_.liqData[i].txData.length == 0) { - (address superform,,) = multiVaultData_.superformIds[i].getSuperform(); + (address superformAddress,,) = multiVaultData_.superformIds[i].getSuperform(); + superform = IBaseForm(superformAddress); /// @dev for withdrawals the payload update can happen on core state registry (for normal forms) /// and also can happen in timelock state registry (for timelock form) /// @notice this check validates if the state registry is eligible to update tx data for the /// corresponding superform - if (IBaseForm(superform).getStateRegistryId() == _getStateRegistryId(address(this))) { + if (superform.getStateRegistryId() == _getStateRegistryId(address(this))) { PayloadUpdaterLib.validateLiqReq(multiVaultData_.liqData[i]); IBridgeValidator bridgeValidator = @@ -659,9 +661,9 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { srcChainId_, multiVaultData_.liqData[i].liqDstChainId, false, - superform, + superformAddress, srcSender_, - multiVaultData_.liqData[i].token, + superform.getVaultAsset(), address(0) ) ); @@ -669,7 +671,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { if ( !PayloadUpdaterLib.validateSlippage( bridgeValidator.decodeAmountIn(txData_[i], false), - IBaseForm(superform).previewRedeemFrom(multiVaultData_.amounts[i]), + superform.previewRedeemFrom(multiVaultData_.amounts[i]), multiVaultData_.maxSlippages[i] ) ) { diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index b75dba5bd..df9c84692 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -140,9 +140,9 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree /// @dev set status here to prevent re-entrancy p.status = TimelockStatus.PROCESSED; - (address superform,,) = p.data.superformId.getSuperform(); + (address superformAddress,,) = p.data.superformId.getSuperform(); - IERC4626TimelockForm form = IERC4626TimelockForm(superform); + IERC4626TimelockForm superform = IERC4626TimelockForm(superformAddress); /// @dev this step is used to re-feed txData to avoid using old txData that would have expired by now if (txData_.length != 0) { @@ -157,9 +157,9 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree p.srcChainId, p.data.liqData.liqDstChainId, false, - superform, + superformAddress, p.data.receiverAddress, - p.data.liqData.token, + superform.getVaultAsset(), address(0) ) ); @@ -167,7 +167,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree finalAmount = bridgeValidator.decodeAmountIn(txData_, false); if ( !PayloadUpdaterLib.validateSlippage( - finalAmount, form.previewRedeemFrom(p.data.amount), p.data.maxSlippage + finalAmount, superform.previewRedeemFrom(p.data.amount), p.data.maxSlippage ) ) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); @@ -176,7 +176,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree p.data.liqData.txData = txData_; } - try form.withdrawAfterCoolDown(p) { } + try superform.withdrawAfterCoolDown(p) { } catch { /// @dev dispatch acknowledgement to mint superPositions back because of failure if (p.isXChain == 1) { diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index dc6444ed0..9748b41b5 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -287,10 +287,6 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { dstAmount = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); if (v.len1 != 0) { - /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same - /// as the vault asset - if (singleVaultData_.liqData.token != v.asset) revert Error.DIRECT_WITHDRAW_INVALID_TOKEN(); - v.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); v.amount = IBridgeValidator(v.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); @@ -309,7 +305,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { false, address(this), singleVaultData_.receiverAddress, - singleVaultData_.liqData.token, + v.asset, address(0) ) ); @@ -317,7 +313,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { _dispatchTokens( superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), singleVaultData_.liqData.txData, - singleVaultData_.liqData.token, + v.asset, v.amount, singleVaultData_.liqData.nativeAmount ); @@ -336,6 +332,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev a case where the withdraw req liqData has a valid token and tx data is not updated by the keeper if (singleVaultData_.liqData.token != address(0) && len == 0) { revert Error.WITHDRAW_TX_DATA_NOT_UPDATED(); + } else if (singleVaultData_.liqData.token == address(0) && len != 0) { + revert Error.WITHDRAW_TOKEN_NOT_UPDATED(); } xChainWithdrawLocalVars memory vars; @@ -348,16 +346,12 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.receiver = len == 0 ? singleVaultData_.receiverAddress : address(this); IERC4626 v = IERC4626(vault); - vars.asset = asset; + vars.asset = address(asset); /// @dev redeem vault positions (we operate only on positions, not assets) dstAmount = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); if (len != 0) { - /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same - /// as the vault asset - if (vars.asset != singleVaultData_.liqData.token) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); - vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); @@ -374,7 +368,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { false, address(this), singleVaultData_.receiverAddress, - singleVaultData_.liqData.token, + vars.asset, address(0) ) ); @@ -382,7 +376,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { _dispatchTokens( superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), singleVaultData_.liqData.txData, - singleVaultData_.liqData.token, + vars.asset, vars.amount, singleVaultData_.liqData.nativeAmount ); diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index d0c14fc91..2b55ad1e1 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -34,6 +34,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { address bridgeValidator; uint64 chainId; address receiver; + address asset; uint256 amount; LiqRequest liqData; } @@ -91,6 +92,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @dev if the txData is empty, the tokens are sent directly to the sender, otherwise sent first to this form vars.receiver = vars.len1 == 0 ? p_.data.receiverAddress : address(this); + vars.asset = address(asset); + dstAmount = v.redeem(p_.data.amount, vars.receiver, address(this)); /// @dev validate and dispatches the tokens if (vars.len1 != 0) { @@ -112,7 +115,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { false, address(this), p_.data.receiverAddress, - vars.liqData.token, + vars.asset, address(0) ) ); @@ -120,7 +123,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { _dispatchTokens( superRegistry.getBridgeAddress(vars.liqData.bridgeId), vars.liqData.txData, - vars.liqData.token, + vars.asset, vars.amount, vars.liqData.nativeAmount ); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 30a01c097..5d0e52fac 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -171,9 +171,6 @@ library Error { /// @dev thrown if the amount in direct deposit is not correct error DIRECT_DEPOSIT_INVALID_DATA(); - /// @dev thrown if the token in direct withdraw is not correct - error DIRECT_WITHDRAW_INVALID_TOKEN(); - /// @dev thrown if the amount in direct withdraw is not correct error DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index dc7f3ddb5..970ff7aa9 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -27,7 +27,8 @@ enum PayloadState { struct LiqRequest { /// @dev generated data bytes txData; - /// @dev input token. Relevant for withdraws especially to know when to update txData + /// @dev input token for deposits, desired output token on target liqDstChainId for withdraws. Must be set for + /// txData to be updated on destination for withdraws address token; /// @dev intermediary token on destination. Relevant for xChain deposits where a destination swap is needed for /// validation purposes diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index a11e5a81a..0cec5682c 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -199,10 +199,6 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li v.v = IERC4626(vault); v.asset = address(v.v.asset()); - /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same as - /// the vault asset - if (singleVaultData_.liqData.token != v.asset) revert Error.DIRECT_WITHDRAW_INVALID_TOKEN(); - /// @dev redeem the underlying dstAmount = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); @@ -302,10 +298,6 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li IERC4626 v = IERC4626(vault); vars.asset = v.asset(); - /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same as - /// the vault asset - if (vars.asset != singleVaultData_.liqData.token) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); - /// @dev redeem vault positions (we operate only on positions, not assets) dstAmount = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); diff --git a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol index 9e9ad823d..b98979c8e 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol @@ -147,7 +147,9 @@ contract PayloadHelperMultiTest is ProtocolActions { _runMainStages(action, act, multiSuperformsData, singleSuperformsData, aV, vars, success); } - _checkDstPayloadLiqData(); + _checkDstPayloadLiqData( + getContract(FINAL_LIQ_DST_WITHDRAW[ARBI][0], UNDERLYING_TOKENS[actions[1].externalToken]) + ); } function _checkSrcPayload() internal { @@ -258,7 +260,7 @@ contract PayloadHelperMultiTest is ProtocolActions { uint256[] nativeAmounts; } - function _checkDstPayloadLiqData() internal { + function _checkDstPayloadLiqData(address externalToken_) internal { vm.selectFork(FORKS[DST_CHAINS[0]]); CheckDstPayloadLiqDataInternalVars memory v; @@ -270,7 +272,7 @@ contract PayloadHelperMultiTest is ProtocolActions { assertGt(v.txDatas[0].length, 0); - assertEq(v.tokens[0], getContract(DST_CHAINS[0], UNDERLYING_TOKENS[TARGET_UNDERLYINGS[ARBI][1][0]])); + assertEq(v.tokens[0], externalToken_); assertEq(v.liqDstChainIds[0], FINAL_LIQ_DST_WITHDRAW[ARBI][0]); diff --git a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol index 658868f06..af210f8cf 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol @@ -134,7 +134,9 @@ contract PayloadHelperSingleTest is ProtocolActions { _runMainStages(action, act, multiSuperformsData, singleSuperformsData, aV, vars, success); } - _checkDstPayloadLiqData(); + _checkDstPayloadLiqData( + getContract(FINAL_LIQ_DST_WITHDRAW[POLY][0], UNDERLYING_TOKENS[actions[1].externalToken]) + ); } function test_decodePayloadHistory_InvalidPayloadId() public { @@ -289,7 +291,7 @@ contract PayloadHelperSingleTest is ProtocolActions { uint256[] nativeAmounts; } - function _checkDstPayloadLiqData() internal { + function _checkDstPayloadLiqData(address externalToken_) internal { vm.selectFork(FORKS[DST_CHAINS[0]]); CheckDstPayloadLiqDataInternalVars memory v; @@ -301,7 +303,7 @@ contract PayloadHelperSingleTest is ProtocolActions { assertGt(v.txDatas[0].length, 0); - assertEq(v.tokens[0], getContract(DST_CHAINS[0], UNDERLYING_TOKENS[TARGET_UNDERLYINGS[POLY][0][0]])); + assertEq(v.tokens[0], externalToken_); assertEq(v.liqDstChainIds[0], FINAL_LIQ_DST_WITHDRAW[POLY][0]); diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index e45fc4d20..b2bdfea93 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -639,82 +639,6 @@ contract SuperformERC4626FormTest is ProtocolActions { IBaseForm(superform).xChainWithdrawFromVault(data, deployer, ARBI); } - function test_superformDirectWithdrawWithInvalidLiqDataToken() public { - /// @dev prank deposits (just mint super-shares) - _successfulDeposit(false); - - vm.selectFork(FORKS[ETH]); - vm.startPrank(deployer); - - address superform = getContract( - ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) - ); - - uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); - - MockERC20(getContract(ETH, "DAI")).transfer(superform, 1e18); - - SingleVaultSFData memory data = SingleVaultSFData( - superformId, - SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(deployer, superformId), - 100, - LiqRequest("0x2222", getContract(ETH, "WETH"), address(0), 1, ETH, 0), - "", - false, - false, - refundAddress, - "" - ); - - SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); - - SuperPositions(getContract(ETH, "SuperPositions")).increaseAllowance( - getContract(ETH, "SuperformRouter"), superformId, 1e18 - ); - vm.expectRevert(Error.DIRECT_WITHDRAW_INVALID_TOKEN.selector); - SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultWithdraw(req); - - vm.stopPrank(); - } - - function test_superformXChainWithInvalidLiqDataToken() public { - /// @dev prank deposits (just mint super-shares) - _successfulDeposit(false); - - vm.selectFork(FORKS[ETH]); - vm.startPrank(deployer); - - address superform = getContract( - ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) - ); - - uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); - - MockERC20(getContract(ETH, "DAI")).transfer(superform, 1e18); - vm.stopPrank(); - - bytes memory invalidTxData = abi.encode(1); - - InitSingleVaultData memory data = InitSingleVaultData( - 1, - superformId, - 0.9e18, - 100, - LiqRequest(invalidTxData, getContract(ETH, "WETH"), address(0), 1, ARBI, 0), - false, - false, - refundAddress, - "" - ); - - vm.startPrank(getContract(ETH, "CoreStateRegistry")); - - vm.expectRevert(Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST.selector); - IBaseForm(superform).xChainWithdrawFromVault(data, deployer, ARBI); - - vm.stopPrank(); - } - function test_revert_baseForm_notSuperRegistry() public { vm.startPrank(deployer); diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index c29e58470..2384d6259 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -125,7 +125,7 @@ contract ForwardDustFormTest is ProtocolActions { false ) ), - getContract(ARBI, "WETH"), + getContract(ETH, "WETH"), address(0), 1, ETH, diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 02d716b09..25d04a410 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -312,8 +312,8 @@ contract SuperformRouterTest is ProtocolActions { bool[] memory retain4626s = new bool[](1); LiqRequest[] memory liqReq = new LiqRequest[](2); - liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); - liqReq[1] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); + liqReq[0] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); + liqReq[1] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index 87dda7fa9..cc6e12945 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -1228,7 +1228,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vars.liqReq = LiqRequest( vars.txData, /// @dev for certain test cases, insert txData as null here - args.underlyingTokenDst, + args.externalToken, address(0), args.liqBridge, args.liqDstChainId, diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 743867d07..7ce0d7bea 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -1875,7 +1875,7 @@ abstract contract ProtocolActions is CommonProtocolActions { vars.liqReq = LiqRequest( GENERATE_WITHDRAW_TX_DATA_ON_DST ? bytes("") : vars.txData, /// @dev for certain test cases, insert txData as null here - args.underlyingTokenDst, + args.externalToken, address(0), args.liqBridge, args.liqDstChainId, From 43519480ed367e101cccb818d3fc1c72957c4bec Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 12:00:28 +0000 Subject: [PATCH 090/210] fix: _extractBridgeData --- .../lifi/LiFiValidator.sol | 8 +- src/vendor/lifi/AmarokFacet.sol | 55 +++++++++++ src/vendor/lifi/CelerIMFacetBase.sol | 62 ++++++++++++ src/vendor/lifi/LiFiTxDataExtractor.sol | 86 +++++++++++++++-- src/vendor/lifi/StandardizedCallFacet.sol | 2 +- src/vendor/lifi/StargateFacet.sol | 57 +++++++++++ .../lifi/celer-network/MsgDataTypes.sol | 94 +++++++++++++++++++ .../superform-factory.createSuperforms.t.sol | 2 +- 8 files changed, 354 insertions(+), 12 deletions(-) create mode 100644 src/vendor/lifi/AmarokFacet.sol create mode 100644 src/vendor/lifi/CelerIMFacetBase.sol create mode 100644 src/vendor/lifi/StargateFacet.sol create mode 100644 src/vendor/lifi/celer-network/MsgDataTypes.sol diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index cba1cfc98..3b6f9aa78 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -26,7 +26,8 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { /// @inheritdoc BridgeValidator function validateReceiver(bytes calldata txData_, address receiver_) external pure override returns (bool valid_) { - return _extractBridgeData(txData_).receiver == receiver_; + (, address receiver) = _extractBridgeData(txData_); + return receiver == receiver_; } /// @inheritdoc BridgeValidator @@ -200,7 +201,8 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { bool hasDestinationCall ) { - ILiFi.BridgeData memory bridgeData = _extractBridgeData(data_); + ILiFi.BridgeData memory bridgeData; + (bridgeData, receiver) = _extractBridgeData(data_); if (bridgeData.hasSourceSwaps) { LibSwap.SwapData[] memory swapData = _extractSwapData(data_); @@ -214,7 +216,7 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { return ( bridgeData.bridge, sendingAssetId, - bridgeData.receiver, + receiver, amount, minAmount, bridgeData.destinationChainId, diff --git a/src/vendor/lifi/AmarokFacet.sol b/src/vendor/lifi/AmarokFacet.sol new file mode 100644 index 000000000..192a00afd --- /dev/null +++ b/src/vendor/lifi/AmarokFacet.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { ILiFi } from "./ILiFi.sol"; +import { LibSwap } from "./LibSwap.sol"; + +/// @title Amarok Facet +/// @author LI.FI (https://li.fi) +/// @notice Provides functionality for bridging through Connext Amarok +/// @notice taken from LiFi contracts https://github.com/lifinance/contracts and stripped down to needs +/// @custom:version 2.0.0 +contract AmarokFacet { + /// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty. + /// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data + /// @param relayerFee The amount of relayer fee the tx called xcall with + /// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage) + /// @param delegate Destination delegate address + /// @param destChainDomainId The Amarok-specific domainId of the destination chain + /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not + struct AmarokData { + bytes callData; + address callTo; + uint256 relayerFee; + uint256 slippageTol; + address delegate; + uint32 destChainDomainId; + bool payFeeWithSendingAsset; + } + + /// External Methods /// + + /// @notice Bridges tokens via Amarok + /// @param _bridgeData Data containing core information for bridging + /// @param _amarokData Data specific to bridge + function startBridgeTokensViaAmarok( + ILiFi.BridgeData calldata _bridgeData, + AmarokData calldata _amarokData + ) + external + payable + { } + + /// @notice Performs a swap before bridging via Amarok + /// @param _bridgeData The core information needed for bridging + /// @param _swapData An array of swap related data for performing swaps before bridging + /// @param _amarokData Data specific to Amarok + function swapAndStartBridgeTokensViaAmarok( + ILiFi.BridgeData memory _bridgeData, + LibSwap.SwapData[] calldata _swapData, + AmarokData calldata _amarokData + ) + external + payable + { } +} diff --git a/src/vendor/lifi/CelerIMFacetBase.sol b/src/vendor/lifi/CelerIMFacetBase.sol new file mode 100644 index 000000000..c807f6955 --- /dev/null +++ b/src/vendor/lifi/CelerIMFacetBase.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { ILiFi } from "./ILiFi.sol"; +import { LibSwap } from "./LibSwap.sol"; +import { MsgDataTypes } from "./celer-network/MsgDataTypes.sol"; + +interface CelerIM { + /// @param maxSlippage The max slippage accepted, given as percentage in point (pip). + /// @param nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice. + /// @param callTo The address of the contract to be called at destination. + /// @param callData The encoded calldata with below data + /// bytes32 transactionId, + /// LibSwap.SwapData[] memory swapData, + /// address receiver, + /// address refundAddress + /// @param messageBusFee The fee to be paid to CBridge message bus for relaying the message + /// @param bridgeType Defines the bridge operation type (must be one of the values of CBridge library + /// MsgDataTypes.BridgeSendType) + struct CelerIMData { + uint32 maxSlippage; + uint64 nonce; + bytes callTo; + bytes callData; + uint256 messageBusFee; + MsgDataTypes.BridgeSendType bridgeType; + } +} + +/// @title CelerIM Facet Base +/// @author LI.FI (https://li.fi) +/// @notice Provides functionality for bridging tokens and data through CBridge +/// @notice Used to differentiate between contract instances for mutable and immutable diamond as these cannot be shared +/// @notice taken from LiFi contracts https://github.com/lifinance/contracts and stripped down to needs +/// @custom:version 2.0.0 +abstract contract CelerIMFacetBase { + /// External Methods /// + + /// @notice Bridges tokens via CBridge + /// @param _bridgeData The core information needed for bridging + /// @param _celerIMData Data specific to CelerIM + function startBridgeTokensViaCelerIM( + ILiFi.BridgeData memory _bridgeData, + CelerIM.CelerIMData calldata _celerIMData + ) + external + payable + { } + + /// @notice Performs a swap before bridging via CBridge + /// @param _bridgeData The core information needed for bridging + /// @param _swapData An array of swap related data for performing swaps before bridging + /// @param _celerIMData Data specific to CelerIM + function swapAndStartBridgeTokensViaCelerIM( + ILiFi.BridgeData memory _bridgeData, + LibSwap.SwapData[] calldata _swapData, + CelerIM.CelerIMData calldata _celerIMData + ) + external + payable + { } +} diff --git a/src/vendor/lifi/LiFiTxDataExtractor.sol b/src/vendor/lifi/LiFiTxDataExtractor.sol index 383d230ee..68ea110cf 100644 --- a/src/vendor/lifi/LiFiTxDataExtractor.sol +++ b/src/vendor/lifi/LiFiTxDataExtractor.sol @@ -4,6 +4,9 @@ pragma solidity ^0.8.23; import { ILiFi } from "src/vendor/lifi/ILiFi.sol"; import { LibSwap } from "src/vendor/lifi/LibSwap.sol"; import { StandardizedCallFacet } from "./StandardizedCallFacet.sol"; +import { AmarokFacet } from "./AmarokFacet.sol"; +import { CelerIMFacetBase, CelerIM } from "./CelerIMFacetBase.sol"; +import { StargateFacet } from "./StargateFacet.sol"; /// @title LiFiTxDataExtractor /// @author LI.FI (https://li.fi) @@ -11,24 +14,93 @@ import { StandardizedCallFacet } from "./StandardizedCallFacet.sol"; /// @notice upgraded to solidity 0.8.23 and adapted from CalldataVerificationFacet and LibBytes without any changes to /// used functions (just stripped down functionality and renamed contract name) /// @notice taken from LiFi contracts https://github.com/lifinance/contracts -/// @custom:version 1.1.0 - +/// @custom:version 2.2.0 contract LiFiTxDataExtractor { error SliceOverflow(); error SliceOutOfBounds(); - /// @notice Extracts the bridge data from the calldata + /// @notice Extracts the bridge data from the calldata. Extracts receiver correctly pending certain facet feauresa /// @param data The calldata to extract the bridge data from /// @return bridgeData The bridge data extracted from the calldata - function _extractBridgeData(bytes calldata data) internal pure returns (ILiFi.BridgeData memory bridgeData) { + function _extractBridgeData(bytes calldata data) + internal + pure + returns (ILiFi.BridgeData memory bridgeData, address receiver) + { + bytes memory callData = data; + if (bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector) { // StandardizedCall - bytes memory unwrappedData = abi.decode(data[4:], (bytes)); - bridgeData = abi.decode(_slice(unwrappedData, 4, unwrappedData.length - 4), (ILiFi.BridgeData)); - return bridgeData; + callData = abi.decode(data[4:], (bytes)); + } + + bytes4 selector = abi.decode(callData, (bytes4)); + + // Case: Amarok + if (selector == AmarokFacet.startBridgeTokensViaAmarok.selector) { + AmarokFacet.AmarokData memory amarokData; + (bridgeData, amarokData) = + abi.decode(_slice(callData, 4, callData.length - 4), (ILiFi.BridgeData, AmarokFacet.AmarokData)); + receiver = amarokData.callTo; + + return (bridgeData, receiver); + } + if (selector == AmarokFacet.swapAndStartBridgeTokensViaAmarok.selector) { + AmarokFacet.AmarokData memory amarokData; + + (bridgeData,, amarokData) = abi.decode( + _slice(callData, 4, callData.length - 4), (ILiFi.BridgeData, LibSwap.SwapData[], AmarokFacet.AmarokData) + ); + receiver = amarokData.callTo; + + return (bridgeData, receiver); + } + + // Case: Stargate + if (selector == StargateFacet.startBridgeTokensViaStargate.selector) { + StargateFacet.StargateData memory stargateData; + (bridgeData, stargateData) = + abi.decode(_slice(callData, 4, callData.length - 4), (ILiFi.BridgeData, StargateFacet.StargateData)); + + receiver = abi.decode(stargateData.callTo, (address)); + + return (bridgeData, receiver); + } + if (selector == StargateFacet.swapAndStartBridgeTokensViaStargate.selector) { + StargateFacet.StargateData memory stargateData; + (bridgeData,, stargateData) = abi.decode( + _slice(callData, 4, callData.length - 4), + (ILiFi.BridgeData, LibSwap.SwapData[], StargateFacet.StargateData) + ); + receiver = abi.decode(stargateData.callTo, (address)); + + return (bridgeData, receiver); + } + + // Case: Celer + if (selector == CelerIMFacetBase.startBridgeTokensViaCelerIM.selector) { + CelerIM.CelerIMData memory celerIMData; + (bridgeData, celerIMData) = + abi.decode(_slice(callData, 4, callData.length - 4), (ILiFi.BridgeData, CelerIM.CelerIMData)); + + receiver = abi.decode(celerIMData.callTo, (address)); + + return (bridgeData, receiver); + } + if (selector == CelerIMFacetBase.swapAndStartBridgeTokensViaCelerIM.selector) { + CelerIM.CelerIMData memory celerIMData; + + (bridgeData,, celerIMData) = abi.decode( + _slice(callData, 4, callData.length - 4), (ILiFi.BridgeData, LibSwap.SwapData[], CelerIM.CelerIMData) + ); + receiver = abi.decode(celerIMData.callTo, (address)); + + return (bridgeData, receiver); } + // normal call bridgeData = abi.decode(data[4:], (ILiFi.BridgeData)); + receiver = bridgeData.receiver; } /// @notice Extracts the swap data from the calldata diff --git a/src/vendor/lifi/StandardizedCallFacet.sol b/src/vendor/lifi/StandardizedCallFacet.sol index b1c8e904e..5b037079f 100644 --- a/src/vendor/lifi/StandardizedCallFacet.sol +++ b/src/vendor/lifi/StandardizedCallFacet.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; /// @title StandardizedCallFacet /// @author LI.FI (https://li.fi) /// @notice taken from LiFi contracts https://github.com/lifinance/contracts -/// @custom:version 1.1.0 +/// @custom:version 2.2.0 contract StandardizedCallFacet { /// External Methods /// diff --git a/src/vendor/lifi/StargateFacet.sol b/src/vendor/lifi/StargateFacet.sol new file mode 100644 index 000000000..6c262d4cd --- /dev/null +++ b/src/vendor/lifi/StargateFacet.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { ILiFi } from "./ILiFi.sol"; +import { LibSwap } from "./LibSwap.sol"; + +/// @title Stargate Facet +/// @author Li.Finance (https://li.finance) +/// @notice Provides functionality for bridging through Stargate +/// @notice taken from LiFi contracts https://github.com/lifinance/contracts and stripped down to needs +/// @custom:version 2.2.0 +contract StargateFacet { + /// @param srcPoolId Source pool id. + /// @param dstPoolId Dest pool id. + /// @param minAmountLD The min qty you would accept on the destination. + /// @param dstGasForCall Additional gas fee for extral call on the destination. + /// @param lzFee Estimated message fee. + /// @param refundAddress Refund adddress. Extra gas (if any) is returned to this address + /// @param callTo The address to send the tokens to on the destination. + /// @param callData Additional payload. + struct StargateData { + uint256 srcPoolId; + uint256 dstPoolId; + uint256 minAmountLD; + uint256 dstGasForCall; + uint256 lzFee; + address payable refundAddress; + bytes callTo; + bytes callData; + } + + /// External Methods /// + + /// @notice Bridges tokens via Stargate Bridge + /// @param _bridgeData Data used purely for tracking and analytics + /// @param _stargateData Data specific to Stargate Bridge + function startBridgeTokensViaStargate( + ILiFi.BridgeData calldata _bridgeData, + StargateData calldata _stargateData + ) + external + payable + { } + + /// @notice Performs a swap before bridging via Stargate Bridge + /// @param _bridgeData Data used purely for tracking and analytics + /// @param _swapData An array of swap related data for performing swaps before bridging + /// @param _stargateData Data specific to Stargate Bridge + function swapAndStartBridgeTokensViaStargate( + ILiFi.BridgeData memory _bridgeData, + LibSwap.SwapData[] calldata _swapData, + StargateData calldata _stargateData + ) + external + payable + { } +} diff --git a/src/vendor/lifi/celer-network/MsgDataTypes.sol b/src/vendor/lifi/celer-network/MsgDataTypes.sol new file mode 100644 index 000000000..7a63d0ac6 --- /dev/null +++ b/src/vendor/lifi/celer-network/MsgDataTypes.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-3.0-only + +pragma solidity >=0.8.0; + +/// @notice taken from https://github.com/celer-network/sgn-v2-contracts on 19/12/2023 +library MsgDataTypes { + string constant ABORT_PREFIX = "MSG::ABORT:"; + + // bridge operation type at the sender side (src chain) + enum BridgeSendType { + Null, + Liquidity, + PegDeposit, + PegBurn, + PegV2Deposit, + PegV2Burn, + PegV2BurnFrom + } + + // bridge operation type at the receiver side (dst chain) + enum TransferType { + Null, + LqRelay, // relay through liquidity bridge + LqWithdraw, // withdraw from liquidity bridge + PegMint, // mint through pegged token bridge + PegWithdraw, // withdraw from original token vault + PegV2Mint, // mint through pegged token bridge v2 + PegV2Withdraw // withdraw from original token vault v2 + } + + enum MsgType { + MessageWithTransfer, + MessageOnly + } + + enum TxStatus { + Null, + Success, + Fail, + Fallback, + Pending // transient state within a transaction + } + + struct TransferInfo { + TransferType t; + address sender; + address receiver; + address token; + uint256 amount; + uint64 wdseq; // only needed for LqWithdraw (refund) + uint64 srcChainId; + bytes32 refId; + bytes32 srcTxHash; // src chain msg tx hash + } + + struct RouteInfo { + address sender; + address receiver; + uint64 srcChainId; + bytes32 srcTxHash; // src chain msg tx hash + } + + // used for msg from non-evm chains with longer-bytes address + struct RouteInfo2 { + bytes sender; + address receiver; + uint64 srcChainId; + bytes32 srcTxHash; + } + + // combination of RouteInfo and RouteInfo2 for easier processing + struct Route { + address sender; // from RouteInfo + bytes senderBytes; // from RouteInfo2 + address receiver; + uint64 srcChainId; + bytes32 srcTxHash; + } + + struct MsgWithTransferExecutionParams { + bytes message; + TransferInfo transfer; + bytes[] sigs; + address[] signers; + uint256[] powers; + } + + struct BridgeTransferParams { + bytes request; + bytes[] sigs; + address[] signers; + uint256[] powers; + } +} diff --git a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol index 01882b313..17e17e56f 100644 --- a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol +++ b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol @@ -97,7 +97,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { uint256 totalSuperformsBefore = SuperformFactory(getContract(chainId, "SuperformFactory")).getSuperformCount(); /// @dev Creating superform using form - (uint256 superformIdCreated, address superformCreated) = + (uint256 superformIdCreated,) = SuperformFactory(getContract(chainId, "SuperformFactory")).createSuperform(formImplementationId, vault); uint256 totalSuperformsAfter = SuperformFactory(getContract(chainId, "SuperformFactory")).getSuperformCount(); From cd924d5ab3db4f5313011964902fbac612d9a997 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 12:47:02 +0000 Subject: [PATCH 091/210] feat: add emergency cost --- script/Abstract.Deploy.Single.s.sol | 3 + src/interfaces/IPaymentHelper.sol | 2 + src/payments/PaymentHelper.sol | 110 ++++++++++++++++++------- test/unit/payments/PaymentHelper.t.sol | 11 ++- test/utils/BaseSetup.sol | 2 + 5 files changed, 97 insertions(+), 31 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index 90d134256..f59866bde 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -585,6 +585,8 @@ abstract contract AbstractDeploySingle is Script { PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 9, abi.encode(750)); PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 10, abi.encode(40_000)); PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 11, abi.encode(50_000)); + /// @dev FIXME emergencyCost value + PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 12, abi.encode(10_000)); vm.stopBroadcast(); @@ -835,6 +837,7 @@ abstract contract AbstractDeploySingle is Script { 28 gwei, 750, 10_000, + 10_000, 10_000 ) ); diff --git a/src/interfaces/IPaymentHelper.sol b/src/interfaces/IPaymentHelper.sol index 5402dcb7d..aa15e518e 100644 --- a/src/interfaces/IPaymentHelper.sol +++ b/src/interfaces/IPaymentHelper.sol @@ -29,6 +29,7 @@ interface IPaymentHelper { /// @param dstGasPerByte is the gas per size of data on the specified chain /// @param ackGasCost is the gas cost for processing acknowledgements on src chain /// @param timelockCost is the extra cost for processing timelocked payloads + /// @param emergencyCost is the extra cost for processing emergency payloads struct PaymentHelperConfig { address nativeFeedOracle; address gasPriceOracle; @@ -41,6 +42,7 @@ interface IPaymentHelper { uint256 dstGasPerByte; uint256 ackGasCost; uint256 timelockCost; + uint256 emergencyCost; } ////////////////////////////////////////////////////////////// diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 31d64a933..b882580de 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -5,6 +5,7 @@ import { AggregatorV3Interface } from "../vendor/chainlink/AggregatorV3Interface import { IPaymentHelper } from "../interfaces/IPaymentHelper.sol"; import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; +import { ISuperformFactory } from "../interfaces/ISuperformFactory.sol"; import { IBaseStateRegistry } from "../interfaces/IBaseStateRegistry.sol"; import { IAmbImplementation } from "../interfaces/IAmbImplementation.sol"; import { Error } from "../libraries/Error.sol"; @@ -53,6 +54,7 @@ contract PaymentHelper is IPaymentHelper { mapping(uint64 chainId => uint256 gasPerByte) public gasPerByte; mapping(uint64 chainId => uint256 gasForOps) public ackGasCost; mapping(uint64 chainId => uint256 gasForOps) public timelockCost; + mapping(uint64 chainId => uint256 gasForOps) public emergencyCost; /// @dev register transmuter params bytes public extraDataForTransmuter; @@ -130,6 +132,14 @@ contract PaymentHelper is IPaymentHelper { return extraDataForTransmuter; } + struct LocalEstimateVars { + uint256 len; + uint256 superformIdsLen; + uint256 totalDstGas; + uint256 ambFees; + bool paused; + } + /// @inheritdoc IPaymentHelper function estimateMultiDstMultiVault( MultiDstMultiVaultStateReq calldata req_, @@ -140,54 +150,58 @@ contract PaymentHelper is IPaymentHelper { override returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) { - uint256 len = req_.dstChainIds.length; - uint256 superformIdsLen; - uint256 totalDstGas; + LocalEstimateVars memory v; + v.len = req_.dstChainIds.length; - for (uint256 i; i < len; ++i) { + ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); + for (uint256 i; i < v.len; ++i) { bool xChain = req_.dstChainIds[i] != CHAIN_ID; - totalDstGas = 0; + v.totalDstGas = 0; /// @dev step 1: estimate amb costs - uint256 ambFees = xChain + v.ambFees = xChain ? _estimateAMBFees(req_.ambIds[i], req_.dstChainIds[i], _generateMultiVaultMessage(req_.superformsData[i])) : 0; - superformIdsLen = req_.superformsData[i].superformIds.length; + v.superformIdsLen = req_.superformsData[i].superformIds.length; - srcAmount += ambFees; + srcAmount += v.ambFees; if (isDeposit_) { /// @dev step 2: estimate liq amount liqAmount += _estimateLiqAmount(req_.superformsData[i].liqRequests); if (xChain) { /// @dev step 3: estimate update cost (only for deposit) - totalDstGas += _estimateUpdateCost(req_.dstChainIds[i], superformIdsLen); + v.totalDstGas += _estimateUpdateCost(req_.dstChainIds[i], v.superformIdsLen); /// @dev step 4: estimation processing cost of acknowledgement /// @notice optimistically estimating. (Ideal case scenario: no failed deposits / withdrawals) - srcAmount += _estimateAckProcessingCost(superformIdsLen); + srcAmount += _estimateAckProcessingCost(v.superformIdsLen); /// @dev step 5: estimate dst swap cost if it exists - totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); - } + v.totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); + } } else { /// @dev step 6: estimate if timelock form processing costs are involved - for (uint256 j; j < superformIdsLen; ++j) { + for (uint256 j; j < v.superformIdsLen; ++j) { (, uint32 formId,) = req_.superformsData[i].superformIds[j].getSuperform(); - if (formId == TIMELOCK_FORM_ID) { - totalDstGas += timelockCost[req_.dstChainIds[i]]; + v.paused = factory.isFormImplementationPaused(formId); + + if (!v.paused && formId == TIMELOCK_FORM_ID) { + v.totalDstGas += timelockCost[req_.dstChainIds[i]]; + } else if (v.paused) { + v.totalDstGas += emergencyCost[req_.dstChainIds[i]]; } } } /// @dev step 7: estimate execution costs in dst (withdraw / deposit) /// note: execution cost includes acknowledgement messaging cost - totalDstGas += xChain ? _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], superformIdsLen) : 0; + v.totalDstGas += xChain ? _estimateDstExecutionCost(isDeposit_, req_.dstChainIds[i], v.superformIdsLen) : 0; /// @dev step 8: convert all dst gas estimates to src chain estimate (withdraw / deposit) - dstAmount += _convertToNativeFee(req_.dstChainIds[i], totalDstGas); + dstAmount += _convertToNativeFee(req_.dstChainIds[i], v.totalDstGas); } totalAmount = srcAmount + dstAmount + liqAmount; @@ -204,6 +218,8 @@ contract PaymentHelper is IPaymentHelper { returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) { uint256 len = req_.dstChainIds.length; + ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); + for (uint256 i; i < len; ++i) { bool xChain = req_.dstChainIds[i] != CHAIN_ID; uint256 totalDstGas; @@ -228,12 +244,17 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate if swap costs are involved totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); - } + } } else { /// @dev step 6: estimate if timelock form processing costs are involved (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); - if (formId == TIMELOCK_FORM_ID) { + + bool paused = factory.isFormImplementationPaused(formId); + + if (!paused && formId == TIMELOCK_FORM_ID) { totalDstGas += timelockCost[req_.dstChainIds[i]]; + } else if (paused) { + totalDstGas += emergencyCost[req_.dstChainIds[i]]; } } @@ -261,13 +282,14 @@ contract PaymentHelper is IPaymentHelper { uint256 totalDstGas; uint256 superformIdsLen = req_.superformsData.superformIds.length; + ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); + /// @dev step 1: estimate AMB costs uint256 ambFees = _estimateAMBFees(req_.ambIds, req_.dstChainId, _generateMultiVaultMessage(req_.superformsData)); srcAmount += ambFees; if (isDeposit_) { - /// @dev step 2: estimate update cost (only for deposit) totalDstGas += _estimateUpdateCost(req_.dstChainId, superformIdsLen); @@ -283,8 +305,13 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 6: process non-deposit logic for timelock form processing costs for (uint256 i; i < superformIdsLen; ++i) { (, uint32 formId,) = req_.superformsData.superformIds[i].getSuperform(); - if (formId == TIMELOCK_FORM_ID) { + + bool paused = factory.isFormImplementationPaused(formId); + + if (!paused && formId == TIMELOCK_FORM_ID) { totalDstGas += timelockCost[req_.dstChainId]; + } else if (paused) { + totalDstGas += emergencyCost[req_.dstChainId]; } } } @@ -298,7 +325,6 @@ contract PaymentHelper is IPaymentHelper { totalAmount = srcAmount + dstAmount + liqAmount; } - /// @inheritdoc IPaymentHelper function estimateSingleXChainSingleVault( SingleXChainSingleVaultStateReq calldata req_, @@ -310,6 +336,7 @@ contract PaymentHelper is IPaymentHelper { returns (uint256 liqAmount, uint256 srcAmount, uint256 dstAmount, uint256 totalAmount) { uint256 totalDstGas; + ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); /// @dev step 1: estimate AMB costs uint256 ambFees = @@ -317,7 +344,6 @@ contract PaymentHelper is IPaymentHelper { srcAmount += ambFees; if (isDeposit_) { - /// @dev step 2: estimate update cost (only for deposit) totalDstGas += _estimateUpdateCost(req_.dstChainId, 1); @@ -332,8 +358,13 @@ contract PaymentHelper is IPaymentHelper { } else { /// @dev step 6: process non-deposit logic for timelock form processing costs (, uint32 formId,) = req_.superformData.superformId.getSuperform(); - if (formId == TIMELOCK_FORM_ID) { + + bool paused = factory.isFormImplementationPaused(formId); + + if (!paused && formId == TIMELOCK_FORM_ID) { totalDstGas += timelockCost[req_.dstChainId]; + } else if (paused) { + totalDstGas += emergencyCost[req_.dstChainId]; } } @@ -346,7 +377,6 @@ contract PaymentHelper is IPaymentHelper { totalAmount = srcAmount + dstAmount + liqAmount; } - /// @inheritdoc IPaymentHelper function estimateSingleDirectSingleVault( SingleDirectSingleVaultStateReq calldata req_, @@ -357,16 +387,23 @@ contract PaymentHelper is IPaymentHelper { override returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount) { + ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); + if (!isDeposit_) { /// @dev only if timelock form withdrawal is involved (, uint32 formId,) = req_.superformData.superformId.getSuperform(); - if (formId == TIMELOCK_FORM_ID) { - srcAmount = timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); + + bool paused = factory.isFormImplementationPaused(formId); + + if (!paused && formId == TIMELOCK_FORM_ID) { + srcAmount += timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); + } else if (paused) { + srcAmount += emergencyCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); } } else { liqAmount = _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); } - + /// @dev not adding dstAmount to save some GAS totalAmount = liqAmount + srcAmount; } @@ -381,14 +418,20 @@ contract PaymentHelper is IPaymentHelper { override returns (uint256 liqAmount, uint256 srcAmount, uint256 totalAmount) { + ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); + if (!isDeposit_) { uint256 len = req_.superformData.superformIds.length; uint256 timelockPrice = timelockCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); + uint256 emergencyPrice = emergencyCost[CHAIN_ID] * _getGasPrice(CHAIN_ID); for (uint256 i; i < len; ++i) { (, uint32 formId,) = req_.superformData.superformIds[i].getSuperform(); - /// @dev only if timelock form withdrawal is involved - if (formId == TIMELOCK_FORM_ID) { + bool paused = factory.isFormImplementationPaused(formId); + + if (!paused && formId == TIMELOCK_FORM_ID) { srcAmount += timelockPrice; + } else if (paused) { + srcAmount += emergencyPrice; } } } else { @@ -489,6 +532,8 @@ contract PaymentHelper is IPaymentHelper { gasPerByte[chainId_] = config_.dstGasPerByte; ackGasCost[chainId_] = config_.ackGasCost; timelockCost[chainId_] = config_.timelockCost; + emergencyCost[chainId_] = config_.emergencyCost; + emit ChainConfigAdded(chainId_, config_); } @@ -557,6 +602,11 @@ contract PaymentHelper is IPaymentHelper { timelockCost[chainId_] = abi.decode(config_, (uint256)); } + /// @dev Type 12: EMERGENCY PROCESSING COST + if (configType_ == 12) { + emergencyCost[chainId_] = abi.decode(config_, (uint256)); + } + emit ChainConfigUpdated(chainId_, configType_, config_); } diff --git a/test/unit/payments/PaymentHelper.t.sol b/test/unit/payments/PaymentHelper.t.sol index 5508f8bda..70c2fce4f 100644 --- a/test/unit/payments/PaymentHelper.t.sol +++ b/test/unit/payments/PaymentHelper.t.sol @@ -619,7 +619,9 @@ contract PaymentHelperTest is ProtocolActions { vm.prank(deployer); paymentHelper.addRemoteChain( 420, - IPaymentHelper.PaymentHelperConfig(address(420), address(421), 422, 423, 424, 425, 426, 427, 428, 429, 430) + IPaymentHelper.PaymentHelperConfig( + address(420), address(421), 422, 423, 424, 425, 426, 427, 428, 429, 430, 431 + ) ); } @@ -702,6 +704,13 @@ contract PaymentHelperTest is ProtocolActions { uint256 result11 = paymentHelper.timelockCost(1); assertEq(result11, 430); + + /// set config type: 12 + vm.prank(deployer); + paymentHelper.updateRemoteChain(1, 12, abi.encode(431)); + + uint256 result12 = paymentHelper.emergencyCost(1); + assertEq(result12, 431); } function _generateTimelockSuperformPackWithShift() internal pure returns (uint256 superformId_) { diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 57413fe0b..b51d00c5e 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -790,6 +790,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { 28 gwei, 750, 10_000, + 10_000, 10_000 ) ); @@ -897,6 +898,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { ); PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 10, abi.encode(40_000)); PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 11, abi.encode(50_000)); + PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain(vars.chainId, 12, abi.encode(10_000)); PaymentHelper(payable(vars.paymentHelper)).updateRemoteChain( vars.chainId, 8, abi.encode(50 * 10 ** 9 wei) ); From 510ff3e98f5d18cdbd454c7fa1291af2c69cb4cb Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:16:12 +0000 Subject: [PATCH 092/210] fix: SUP-4816 --- src/BaseRouterImplementation.sol | 40 ++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 5dbce3d43..35bf437f6 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8.23; import { BaseRouter } from "./BaseRouter.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; +import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol"; import { IBaseStateRegistry } from "./interfaces/IBaseStateRegistry.sol"; import { IBaseRouterImplementation } from "./interfaces/IBaseRouterImplementation.sol"; import { IPayMaster } from "./interfaces/IPayMaster.sol"; @@ -18,8 +20,6 @@ import { IPermit2 } from "./vendor/dragonfly-xyz/IPermit2.sol"; import "./crosschain-liquidity/LiquidityHandler.sol"; import "./types/DataTypes.sol"; -import "forge-std/console.sol"; - /// @title BaseRouterImplementation /// @author Zeropoint Labs /// @dev Extends BaseRouter with standard internal execution functions @@ -774,7 +774,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ISuperformFactory factory_ ) internal - view virtual returns (bool) { @@ -786,21 +785,16 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev the dstChainId_ (in the state request) must match the superforms' chainId (superform must exist on /// destination) (, uint32 formImplementationId, uint64 sfDstChainId) = superformId_.getSuperform(); - console.log("a"); if (dstChainId_ != sfDstChainId) return false; - console.log("b"); /// @dev 10000 = 100% slippage if (maxSlippage_ > 10_000) return false; - console.log("c"); /// @dev amount can't be 0 if (amount_ == 0) return false; - console.log("d"); if (isDeposit_ && factory_.isFormImplementationPaused(formImplementationId)) return false; - console.log("e"); /// @dev ensure that receiver address is set always /// @dev in deposits, this is important for receive4626 (on destination). It is also important for refunds on @@ -810,7 +804,12 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (receiverAddress_ == address(0)) { return false; } - console.log("f"); + + /// @dev FIXME both this and the check above should probably be done in a secondary internal function (since + /// this would be receiverAddressOnSrc) + _doSafeTransferAcceptanceCheck(receiverAddress_); + + /// @dev NOTE add receiverAddressOnDst checks here /// if it reaches this point then is valid return true; @@ -822,7 +821,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou bool deposit_ ) internal - view virtual returns (bool) { @@ -1060,4 +1058,26 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou return (v.amountsIn, v.bridgeIds); } + + /// @dev implementation copied from OpenZeppelin 5.0 and stripped down + function _doSafeTransferAcceptanceCheck(address to) private { + if (to.code.length > 0) { + try IERC1155Receiver(to).onERC1155Received(address(0), address(0), 0, 0, "") returns (bytes4 response) { + if (response != IERC1155Receiver.onERC1155Received.selector) { + // Tokens rejected + revert IERC1155Errors.ERC1155InvalidReceiver(to); + } + } catch (bytes memory reason) { + if (reason.length == 0) { + // non-IERC1155Receiver implementer + revert IERC1155Errors.ERC1155InvalidReceiver(to); + } else { + /// @solidity memory-safe-assembly + assembly { + revert(add(32, reason), mload(reason)) + } + } + } + } + } } From 465101b557ea28136eda422eb7802742e1e4bb99 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Tue, 19 Dec 2023 20:45:37 +0530 Subject: [PATCH 093/210] chore: fix refunds in wormhole ar impl --- .../automatic-relayer/WormholeARImplementation.sol | 10 ++++++++-- src/payments/PaymentHelper.sol | 10 +++------- .../adapters/WormholeARImplementation.t.sol | 4 +++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 15fc96f3c..76e6a56e3 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -167,7 +167,7 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { (uint256 fees,) = relayer.quoteEVMDeliveryPrice(targetChain, 0, newGasLimit); - if (fees != msg.value) { + if (msg.value < fees) { revert Error.INVALID_RETRY_FEE(); } @@ -175,9 +175,15 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { revert Error.ZERO_ADDRESS(); } - relayer.resendToEvm{ value: msg.value }( + relayer.resendToEvm{ value: fees }( deliveryVaaKey, targetChain, newReceiverValue, newGasLimit, newDeliveryProviderAddress ); + + /// refunds excess msg.value to msg.sender + uint256 excessPaid = msg.value - fees; + if (excessPaid > 0) { + payable(msg.sender).call{ value: excessPaid }(""); + } } /// @inheritdoc IWormholeReceiver diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 31d64a933..97e105f63 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -171,7 +171,7 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate dst swap cost if it exists totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwaps); - } + } } else { /// @dev step 6: estimate if timelock form processing costs are involved for (uint256 j; j < superformIdsLen; ++j) { @@ -228,7 +228,7 @@ contract PaymentHelper is IPaymentHelper { /// @dev step 5: estimate if swap costs are involved totalDstGas += _estimateSwapFees(req_.dstChainIds[i], req_.superformsData[i].hasDstSwap.castBoolToArray()); - } + } } else { /// @dev step 6: estimate if timelock form processing costs are involved (, uint32 formId,) = req_.superformsData[i].superformId.getSuperform(); @@ -267,7 +267,6 @@ contract PaymentHelper is IPaymentHelper { srcAmount += ambFees; if (isDeposit_) { - /// @dev step 2: estimate update cost (only for deposit) totalDstGas += _estimateUpdateCost(req_.dstChainId, superformIdsLen); @@ -298,7 +297,6 @@ contract PaymentHelper is IPaymentHelper { totalAmount = srcAmount + dstAmount + liqAmount; } - /// @inheritdoc IPaymentHelper function estimateSingleXChainSingleVault( SingleXChainSingleVaultStateReq calldata req_, @@ -317,7 +315,6 @@ contract PaymentHelper is IPaymentHelper { srcAmount += ambFees; if (isDeposit_) { - /// @dev step 2: estimate update cost (only for deposit) totalDstGas += _estimateUpdateCost(req_.dstChainId, 1); @@ -346,7 +343,6 @@ contract PaymentHelper is IPaymentHelper { totalAmount = srcAmount + dstAmount + liqAmount; } - /// @inheritdoc IPaymentHelper function estimateSingleDirectSingleVault( SingleDirectSingleVaultStateReq calldata req_, @@ -366,7 +362,7 @@ contract PaymentHelper is IPaymentHelper { } else { liqAmount = _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); } - + /// @dev not adding dstAmount to save some GAS totalAmount = liqAmount + srcAmount; } diff --git a/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol b/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol index 416c3a81d..afd42cc5b 100644 --- a/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol +++ b/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol @@ -52,7 +52,9 @@ contract WormholeARImplementationTest is BaseSetup { uint256 fee = wormholeARImpl.estimateFees(uint64(137), bytes(""), abi.encode(uint256(0), uint256(4))); vm.prank(deployer); - wormholeARImpl.retryPayload{ value: fee }(data); + uint256 balanceBefore = deployer.balance; + wormholeARImpl.retryPayload{ value: fee + 1 ether }(data); + assertEq(deployer.balance, balanceBefore - fee); vm.clearMockedCalls(); } From 748579ed04a1b585b60f0d849fee57f0a1b4c6fb Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Tue, 19 Dec 2023 21:07:43 +0530 Subject: [PATCH 094/210] chore: add has4626 estimations to singleXChainSingleVault --- src/payments/PaymentHelper.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index d971f0151..4f6d25dc6 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -333,7 +333,9 @@ contract PaymentHelper is IPaymentHelper { totalDstGas += _estimateUpdateCost(req_.dstChainId, 1); /// @dev step 3: estimation execution cost of acknowledgement - srcAmount += _estimateAckProcessingCost(1); + if (!req_.superformData.retain4626) { + srcAmount += _estimateAckProcessingCost(1); + } /// @dev step 4: estimate the liqAmount liqAmount += _estimateLiqAmount(req_.superformData.liqRequest.castLiqRequestToArray()); From 6acd84138be60d4a8299e83223436852ae83b6e2 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:54:09 +0000 Subject: [PATCH 095/210] fix: move chainId check and change 2 tests --- .../extensions/CoreStateRegistry.sol | 4 ++++ src/crosschain-liquidity/lifi/LiFiValidator.sol | 14 +++++++------- .../socket/SocketOneInchValidator.sol | 8 ++++---- .../adapters/LayerzeroImplementation.t.sol | 3 ++- .../4626.Native.Slippage.AMB23.t.sol | 2 +- .../4626.Timelocked.Native.Slippage.AMB12.t.sol | 5 +++-- .../socket/SocketOneInchValidator.t.sol | 2 +- 7 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index e8bc88a90..1772a1fd3 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -659,6 +659,10 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { IBridgeValidator bridgeValidator = IBridgeValidator(superRegistry.getBridgeValidator(multiVaultData_.liqData[i].bridgeId)); + // The txdata provided here can be bridgeData or sameChain Data + // if bridgeData liqDstChainId (the final destination chain) is the same as dstChainId of txData + // if sameChainData: liqDstChainId should be qual to dstChainId on withdraws + // srcChainId being equal to dstChainId is only valid for deposits bridgeValidator.validateTxData( IBridgeValidator.ValidateTxDataArgs( txData_[i], diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index cba1cfc98..784c943db 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -52,8 +52,8 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { /// @dev 1. chainId validation /// @dev for deposits, liqDstChainId/toChainId will be the normal destination (where the target superform /// is) - /// @dev for withdraws, liqDstChainId/toChainId will be the desired chain to where the underlying must be - /// sent + /// @dev for withdraws, liqDstChainId will be the desired chain to where the underlying must be + /// sent (post any bridge/swap). To ChainId is where the target superform is /// @dev to after vault redemption if (uint256(args_.liqDstChainId) != destinationChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); @@ -96,16 +96,16 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { } catch { (address sendingAssetId,, address receiver,,) = extractGenericSwapParameters(args_.txData); - /// @dev 1. chainId validation - - if (args_.srcChainId != args_.dstChainId) revert Error.INVALID_ACTION(); - - /// @dev 2. receiver address validation if (args_.deposit) { + /// @dev 1. chainId validation + if (args_.srcChainId != args_.dstChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); if (args_.dstChainId != args_.liqDstChainId) revert Error.INVALID_DEPOSIT_LIQ_DST_CHAIN_ID(); + + /// @dev 2. receiver address validation /// @dev If same chain deposits then receiver address must be the superform if (receiver != args_.superform) revert Error.INVALID_TXDATA_RECEIVER(); } else { + /// @dev 2. receiver address validation /// @dev if withdraws, then receiver address must be the receiverAddress if (receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index 1911c62a5..eb019600f 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -30,16 +30,16 @@ contract SocketOneInchValidator is BridgeValidator { function validateTxData(ValidateTxDataArgs calldata args_) external pure override returns (bool) { ISocketOneInchImpl.SwapInput memory decodedReq = _decodeTxData(args_.txData); - /// @dev 1. chain id validation (only allow samechain with this) - if (args_.dstChainId != args_.srcChainId) revert Error.INVALID_ACTION(); - - /// @dev 2. receiver address validation if (args_.deposit) { + /// @dev 1. chain id validation (only allow samechain with this) + if (args_.dstChainId != args_.srcChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); if (args_.dstChainId != args_.liqDstChainId) revert Error.INVALID_DEPOSIT_LIQ_DST_CHAIN_ID(); + /// @dev 2. receiver address validation /// @dev If same chain deposits then receiver address must be the superform if (decodedReq.receiver != args_.superform) revert Error.INVALID_TXDATA_RECEIVER(); } else { + /// @dev 2. receiver address validation /// @dev if withdraws, then receiver address must be the receiverAddress if (decodedReq.receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } diff --git a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol index b1f755ebd..8f2a23786 100644 --- a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol @@ -155,6 +155,7 @@ contract LayerzeroImplementationTest is BaseSetup { function test_setSendVersion_and_revert_invalidCaller(uint16 versionSeed_, address malice_) public { uint16 version = uint16(bound(versionSeed_, 0, 3)); + vm.assume(malice_ != deployer); vm.expectEmit(false, false, false, true, LZ_ENDPOINT_ETH); emit UaSendVersionSet(address(layerzeroImplementation), version); @@ -168,7 +169,7 @@ contract LayerzeroImplementationTest is BaseSetup { function test_setReceiveVersion_and_revert_invalidCaller(uint16 versionSeed_, address malice_) public { uint16 version = uint16(bound(versionSeed_, 0, 3)); - + vm.assume(malice_ != deployer); vm.expectEmit(false, false, false, true, LZ_ENDPOINT_ETH); emit UaReceiveVersionSet(address(layerzeroImplementation), version); vm.prank(deployer); diff --git a/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol b/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol index 417b0a0ff..1ff1842ac 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol @@ -39,7 +39,7 @@ contract SXSVWNormal4626NativeSlippageAMB23 is ProtocolActions { GENERATE_WITHDRAW_TX_DATA_ON_DST = true; - FINAL_LIQ_DST_WITHDRAW[OP] = [POLY]; + FINAL_LIQ_DST_WITHDRAW[OP] = [OP]; actions.push( TestAction({ diff --git a/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Timelocked.Native.Slippage.AMB12.t.sol b/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Timelocked.Native.Slippage.AMB12.t.sol index 3bde6c012..6c2a7680b 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Timelocked.Native.Slippage.AMB12.t.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-singleXChainSingleVaultWithdraw/4626.Timelocked.Native.Slippage.AMB12.t.sol @@ -32,14 +32,15 @@ contract SXSVWTimelockedNativeSlippageAMB12 is ProtocolActions { MAX_SLIPPAGE = 1000; LIQ_BRIDGES[ARBI][0] = [1]; - LIQ_BRIDGES[ARBI][1] = [2]; + LIQ_BRIDGES[ARBI][1] = [3]; + /// extract with 1inch impl RECEIVE_4626[ARBI][0] = [false]; RECEIVE_4626[ARBI][1] = [false]; GENERATE_WITHDRAW_TX_DATA_ON_DST = true; - FINAL_LIQ_DST_WITHDRAW[ARBI] = [ETH]; + FINAL_LIQ_DST_WITHDRAW[ARBI] = [ARBI]; actions.push( TestAction({ diff --git a/test/unit/crosschain-liquidity/socket/SocketOneInchValidator.t.sol b/test/unit/crosschain-liquidity/socket/SocketOneInchValidator.t.sol index 313981498..efa6f73f5 100644 --- a/test/unit/crosschain-liquidity/socket/SocketOneInchValidator.t.sol +++ b/test/unit/crosschain-liquidity/socket/SocketOneInchValidator.t.sol @@ -130,7 +130,7 @@ contract SocketOneInchValidatorTest is ProtocolActions { } function test_validateTxData_reverts() public { - vm.expectRevert(Error.INVALID_ACTION.selector); + vm.expectRevert(Error.INVALID_TXDATA_CHAIN_ID.selector); SocketOneInchValidator(getContract(BSC, "SocketOneInchValidator")).validateTxData( IBridgeValidator.ValidateTxDataArgs( _buildDummyTxDataUnitTests( From ef0acf2a4e6c29c998033281517001196fc0e26b Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:56:54 +0000 Subject: [PATCH 096/210] chore: remove comments --- src/crosschain-data/extensions/CoreStateRegistry.sol | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 1772a1fd3..7ef2043ba 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -223,10 +223,8 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { FailedDeposit storage failedDeposits_ = failedDeposits[payloadId_]; - if ( - failedDeposits_.superformIds.length == 0 - || failedDeposits_.superformIds.length != proposedAmounts_.length - ) { + if (failedDeposits_.superformIds.length == 0 || failedDeposits_.superformIds.length != proposedAmounts_.length) + { revert Error.INVALID_RESCUE_DATA(); } @@ -659,10 +657,6 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { IBridgeValidator bridgeValidator = IBridgeValidator(superRegistry.getBridgeValidator(multiVaultData_.liqData[i].bridgeId)); - // The txdata provided here can be bridgeData or sameChain Data - // if bridgeData liqDstChainId (the final destination chain) is the same as dstChainId of txData - // if sameChainData: liqDstChainId should be qual to dstChainId on withdraws - // srcChainId being equal to dstChainId is only valid for deposits bridgeValidator.validateTxData( IBridgeValidator.ValidateTxDataArgs( txData_[i], From ccbbf4c519cecef056ed49ce9c8c891f8f9f4326 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 17:18:00 +0000 Subject: [PATCH 097/210] chore: fix typo --- src/vendor/lifi/LiFiTxDataExtractor.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vendor/lifi/LiFiTxDataExtractor.sol b/src/vendor/lifi/LiFiTxDataExtractor.sol index 68ea110cf..ec00cdd43 100644 --- a/src/vendor/lifi/LiFiTxDataExtractor.sol +++ b/src/vendor/lifi/LiFiTxDataExtractor.sol @@ -19,7 +19,7 @@ contract LiFiTxDataExtractor { error SliceOverflow(); error SliceOutOfBounds(); - /// @notice Extracts the bridge data from the calldata. Extracts receiver correctly pending certain facet feauresa + /// @notice Extracts the bridge data from the calldata. Extracts receiver correctly pending certain facet features /// @param data The calldata to extract the bridge data from /// @return bridgeData The bridge data extracted from the calldata function _extractBridgeData(bytes calldata data) From df8445fbfa63c4dfc0b0707d2ea6a36c456b9d6f Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:10:13 -0500 Subject: [PATCH 098/210] chore: add checks, make consistent --- src/forms/ERC4626FormImplementation.sol | 90 ++++++++++++------------- src/libraries/Error.sol | 6 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 206a7e7c0..1c84bc966 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -50,7 +50,6 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { address bridgeValidator; uint256 len1; uint256 amount; - IERC4626 v; } struct xChainWithdrawLocalVars { @@ -236,18 +235,14 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev notice that vars.assetDifference is deposited regardless if txData exists or not /// @dev this presumes no dust is left in the superform IERC20(vars.asset).safeIncreaseAllowance(vault, vars.assetDifference); - - if (singleVaultData_.retain4626) { - shares = v.deposit(vars.assetDifference, singleVaultData_.receiverAddress); - } else { - /// @dev This makes ERC4626Form (address(this)) owner of v.shares - /// @dev add extra validation check in minting SuperPositions to ensure accounting - uint256 sharesBalanceBefore = v.balanceOf(address(this)); - shares = v.deposit(vars.assetDifference, address(this)); - uint256 sharesBalanceAfter = v.balanceOf(address(this)); - if (sharesBalanceAfter - sharesBalanceBefore != shares) { - revert Error.INVALID_OUTPUT_AMOUNT(); - } + + /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior + address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); + uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); + shares = v.deposit(vars.assetDifference, sharesReceiver); + uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); + if (sharesBalanceAfter - sharesBalanceBefore != shares) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); } } @@ -273,18 +268,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev allowance is modified inside of the IERC20.transferFrom() call IERC20(asset).safeIncreaseAllowance(vaultLoc, singleVaultData_.amount); - /// @dev Deposit into vault - if (singleVaultData_.retain4626) { - shares = v.deposit(singleVaultData_.amount, singleVaultData_.receiverAddress); - } else { - /// @dev This makes ERC4626Form (address(this)) owner of v.shares - /// @dev add extra validation check in minting SuperPositions to ensure accounting - uint256 sharesBalanceBefore = v.balanceOf(address(this)); - shares = v.deposit(singleVaultData_.amount, address(this)); - uint256 sharesBalanceAfter = v.balanceOf(address(this)); - if (sharesBalanceAfter - sharesBalanceBefore != shares) { - revert Error.INVALID_OUTPUT_AMOUNT(); - } + /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior + address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); + uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); + shares = v.deposit(singleVaultData_.amount, sharesReceiver); + uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); + if (sharesBalanceAfter - sharesBalanceBefore != shares) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); } emit Processed(srcChainId_, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); @@ -297,40 +287,45 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { internal returns (uint256 assets) { - directWithdrawLocalVars memory v; - v.len1 = singleVaultData_.liqData.txData.length; + directWithdrawLocalVars memory vars; + vars.len1 = singleVaultData_.liqData.txData.length; /// @dev if there is no txData, on withdraws the receiver is the original beneficiary (srcSender_), otherwise it /// is this contract (before swap) - v.receiver = v.len1 == 0 ? srcSender_ : address(this); + vars.receiver = vars.len1 == 0 ? srcSender_ : address(this); - v.v = IERC4626(vault); - v.asset = address(asset); + IERC4626 v = IERC4626(vault); + vars.asset = address(asset); - /// @dev redeem shares for assets - assets = v.v.redeem(singleVaultData_.amount, v.receiver, address(this)); + /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior + uint256 assetsBalanceBefore = v.balanceOf(vars.receiver); + assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = v.balanceOf(vars.receiver); + if (assetsBalanceAfter - assetsBalanceBefore != assets) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); - if (v.len1 != 0) { + if (vars.len1 != 0) { /// @dev the token we are swapping from to our desired output token (if there is txData), must be the same /// as the vault asset - if (singleVaultData_.liqData.token != v.asset) revert Error.DIRECT_WITHDRAW_INVALID_TOKEN(); + if (singleVaultData_.liqData.token != vars.asset) revert Error.DIRECT_WITHDRAW_INVALID_TOKEN(); - v.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); - v.amount = IBridgeValidator(v.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); + vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); + vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (v.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); - v.chainId = CHAIN_ID; + vars.chainId = CHAIN_ID; /// @dev validate and perform the swap to desired output token and send to beneficiary - IBridgeValidator(v.bridgeValidator).validateTxData( + IBridgeValidator(vars.bridgeValidator).validateTxData( IBridgeValidator.ValidateTxDataArgs( singleVaultData_.liqData.txData, - v.chainId, - v.chainId, + vars.chainId, + vars.chainId, singleVaultData_.liqData.liqDstChainId, false, address(this), @@ -344,7 +339,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), singleVaultData_.liqData.txData, singleVaultData_.liqData.token, - v.amount, + vars.amount, singleVaultData_.liqData.nativeAmount ); } @@ -358,14 +353,14 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { internal returns (uint256 assets) { - uint256 len = singleVaultData_.liqData.txData.length; + xChainWithdrawLocalVars memory vars; + uint256 len = singleVaultData_.liqData.txData.length; /// @dev a case where the withdraw req liqData has a valid token and tx data is not updated by the keeper if (singleVaultData_.liqData.token != address(0) && len == 0) { revert Error.WITHDRAW_TX_DATA_NOT_UPDATED(); } - xChainWithdrawLocalVars memory vars; (,, vars.dstChainId) = singleVaultData_.superformId.getSuperform(); /// @dev receiverAddress is checked for existence on source @@ -377,8 +372,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC4626 v = IERC4626(vault); vars.asset = asset; - /// @dev redeem shares for assets + /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior + uint256 assetsBalanceBefore = v.balanceOf(vars.receiver); assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = v.balanceOf(vars.receiver); + if (assetsBalanceAfter - assetsBalanceBefore != assets) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index a382c3ef2..e214450fe 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -377,15 +377,15 @@ library Error { /// FORM EXECUTION ERRORS - /// @dev thrown if shares != deposit output or assets != redeem output when minting SuperPositions - error INVALID_OUTPUT_AMOUNT(); - /// @dev thrown in KYCDAO form if no KYC token is present error NO_VALID_KYC_TOKEN(); /// @dev thrown if form implementation is PAUSED, users cannot perform any action error PAUSED(); + /// @dev thrown if shares != deposit output or assets != redeem output when minting SuperPositions + error VAULT_IMPLEMENTATION_FAILED(); + /// @dev thrown if withdrawal tx data is not updated error WITHDRAW_TOKEN_NOT_UPDATED(); From 7428e71def869bfb7b842ae80cecb02e5c68296e Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:22:59 -0500 Subject: [PATCH 099/210] chore: replace dstAmount return --- src/forms/ERC4626FormImplementation.sol | 2 +- src/forms/ERC4626TimelockForm.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 4f9184ed7..1a997bfc2 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -283,7 +283,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit Processed(srcChainId_, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); } - function _processDirectWithdraw(InitSingleVaultData memory singleVaultData_) internal returns (uint256 dstAmount) { + function _processDirectWithdraw(InitSingleVaultData memory singleVaultData_) internal returns (uint256 assets) { directWithdrawLocalVars memory vars; vars.len1 = singleVaultData_.liqData.txData.length; diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 232db3a4e..1bdeee872 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -93,7 +93,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { vars.receiver = vars.len1 == 0 ? p_.data.receiverAddress : address(this); /// @dev redeem from vault - ars.asset = address(asset); + vars.asset = address(asset); assets = v.redeem(p_.data.amount, vars.receiver, address(this)); if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); From cb09a52d2569a9b6dce67722d3c5da366c5ea6b7 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 19:21:07 +0000 Subject: [PATCH 100/210] feat: add receiverAddressSP, refactor validations --- src/BaseRouterImplementation.sol | 157 +++++++---- src/SuperPositions.sol | 18 +- src/interfaces/ISuperPositions.sol | 10 +- src/types/DataTypes.sol | 6 + .../extensions/CoreStateRegistry.t.sol | 12 + test/unit/emergency/EmergencyQueue.t.sol | 27 +- test/unit/payments/PayMaster.t.sol | 1 + test/unit/payments/PaymentHelper.t.sol | 13 + .../superform-form.ERC4626Form.t.sol | 29 +- .../superform-form.ERC4626KYCDao.t.sol | 1 + .../superform-form.ERC4626Timelock.t.sol | 1 + .../superform-form.forwardDust.t.sol | 1 + .../superform-router/SuperformRouter.AA.t.sol | 72 ++++- .../superform-router/SuperformRouter.t.sol | 261 ++++++++++++++++-- test/utils/InvariantProtocolActions.sol | 5 + test/utils/ProtocolActions.sol | 7 + 16 files changed, 511 insertions(+), 110 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 0f7c9995d..e345b017c 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -47,6 +47,18 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou bool deposit; } + struct SingleDepositLocalVars { + address superform; + uint256 dstAmount; + } + + struct MultiDepositArgs { + address srcSender; + bytes permit2data; + address receiverAddressSP; + InitMultiVaultData vaultData; + } + struct MultiDepositLocalVars { uint256 len; address[] superforms; @@ -99,9 +111,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippage, req_.superformData.amount, req_.superformData.receiverAddress, + req_.superformData.receiverAddressSP, CHAIN_ID, true, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))) + ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + false ) ) { revert Error.INVALID_SUPERFORMS_DATA(); @@ -120,7 +134,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); /// @dev same chain action & forward residual payment to payment collector - _directSingleDeposit(msg.sender, req_.superformData.permit2data, vaultData); + _directSingleDeposit( + msg.sender, req_.superformData.permit2data, req_.superformData.receiverAddressSP, vaultData + ); emit Completed(); } @@ -138,9 +154,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippage, req_.superformData.amount, req_.superformData.receiverAddress, + req_.superformData.receiverAddressSP, req_.dstChainId, true, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))) + ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + false ) ) { revert Error.INVALID_SUPERFORMS_DATA(); @@ -197,7 +215,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.dstChainId, vars.currentPayloadId ), - req_.superformData.receiverAddress + req_.superformData.receiverAddressSP ); emit CrossChainInitiatedDepositSingle( @@ -225,7 +243,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); /// @dev same chain action & forward residual payment to payment collector - _directMultiDeposit(msg.sender, req_.superformData.permit2data, vaultData); + _directMultiDeposit( + MultiDepositArgs( + msg.sender, req_.superformData.permit2data, req_.superformData.receiverAddressSP, vaultData + ) + ); emit Completed(); } @@ -294,7 +316,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.dstChainId, vars.currentPayloadId ), - req_.superformsData.receiverAddress + req_.superformsData.receiverAddressSP ); emit CrossChainInitiatedDepositMulti( @@ -311,9 +333,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippage, req_.superformData.amount, req_.superformData.receiverAddress, + req_.superformData.receiverAddressSP, CHAIN_ID, false, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))) + ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + false ) ) { revert Error.INVALID_SUPERFORMS_DATA(); @@ -357,9 +381,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippage, req_.superformData.amount, req_.superformData.receiverAddress, + req_.superformData.receiverAddressSP, req_.dstChainId, false, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))) + ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + false ) ) { revert Error.INVALID_SUPERFORMS_DATA(); @@ -399,7 +425,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.dstChainId, vars.currentPayloadId ), - req_.superformData.receiverAddress + req_.superformData.receiverAddressSP ); emit CrossChainInitiatedWithdrawSingle( @@ -484,7 +510,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.dstChainId, vars.currentPayloadId ), - req_.superformsData.receiverAddress + req_.superformsData.receiverAddressSP ); emit CrossChainInitiatedWithdrawMulti( @@ -523,7 +549,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); } - function _dispatchAmbMessage(DispatchAMBMessageVars memory vars_, address receiverAddress_) internal virtual { + function _dispatchAmbMessage(DispatchAMBMessageVars memory vars_, address receiverAddressSP_) internal virtual { AMBMessage memory ambMessage = AMBMessage( DataLib.packTxInfo( uint8(vars_.txType), @@ -540,7 +566,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou .calculateAMBData(vars_.dstChainId, vars_.ambIds, abi.encode(ambMessage)); ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).updateTxHistory( - vars_.currentPayloadId, ambMessage.txInfo, receiverAddress_ + vars_.currentPayloadId, ambMessage.txInfo, receiverAddressSP_ ); /// @dev this call dispatches the message to the AMB bridge through dispatchPayload @@ -594,22 +620,22 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou function _directSingleDeposit( address srcSender_, bytes memory permit2data_, + address receiverAddressSP_, InitSingleVaultData memory vaultData_ ) internal virtual { - address superform; - uint256 dstAmount; + SingleDepositLocalVars memory v; /// @dev decode superforms - (superform,,) = vaultData_.superformId.getSuperform(); + (v.superform,,) = vaultData_.superformId.getSuperform(); - _singleVaultTokenForward(srcSender_, superform, permit2data_, vaultData_, false); + _singleVaultTokenForward(srcSender_, v.superform, permit2data_, vaultData_, false); /// @dev deposits token to a given vault and mint vault positions. - dstAmount = _directDeposit( - superform, + v.dstAmount = _directDeposit( + v.superform, vaultData_.payloadId, vaultData_.superformId, vaultData_.amount, @@ -622,60 +648,53 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou srcSender_ ); - if (dstAmount != 0 && !vaultData_.retain4626) { + if (v.dstAmount != 0 && !vaultData_.retain4626) { /// @dev mint super positions at the end of the deposit action if user doesn't retain 4626 ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintSingle( - vaultData_.receiverAddress, vaultData_.superformId, dstAmount + receiverAddressSP_, vaultData_.superformId, v.dstAmount ); } } /// @notice deposits to multiple vaults on the same chain /// @dev loops and call `_directDeposit` - function _directMultiDeposit( - address srcSender_, - bytes memory permit2data_, - InitMultiVaultData memory vaultData_ - ) - internal - virtual - { + function _directMultiDeposit(MultiDepositArgs memory args_) internal virtual { MultiDepositLocalVars memory v; - v.len = vaultData_.superformIds.length; + v.len = args_.vaultData.superformIds.length; v.superforms = new address[](v.len); v.dstAmounts = new uint256[](v.len); /// @dev decode superforms - v.superforms = DataLib.getSuperforms(vaultData_.superformIds); + v.superforms = DataLib.getSuperforms(args_.vaultData.superformIds); - _multiVaultTokenForward(srcSender_, v.superforms, permit2data_, vaultData_, false); + _multiVaultTokenForward(args_.srcSender, v.superforms, args_.permit2data, args_.vaultData, false); for (uint256 i; i < v.len; ++i) { /// @dev deposits token to a given vault and mint vault positions. v.dstAmounts[i] = _directDeposit( v.superforms[i], - vaultData_.payloadId, - vaultData_.superformIds[i], - vaultData_.amounts[i], - vaultData_.maxSlippages[i], - vaultData_.retain4626s[i], - vaultData_.liqData[i], - vaultData_.receiverAddress, - vaultData_.extraFormData, - vaultData_.liqData[i].nativeAmount, - srcSender_ + args_.vaultData.payloadId, + args_.vaultData.superformIds[i], + args_.vaultData.amounts[i], + args_.vaultData.maxSlippages[i], + args_.vaultData.retain4626s[i], + args_.vaultData.liqData[i], + args_.vaultData.receiverAddress, + args_.vaultData.extraFormData, + args_.vaultData.liqData[i].nativeAmount, + args_.srcSender ); /// @dev if retain4626 is set to True, set the amount of SuperPositions to mint to 0 - if (v.dstAmounts[i] != 0 && vaultData_.retain4626s[i]) { + if (v.dstAmounts[i] != 0 && args_.vaultData.retain4626s[i]) { v.dstAmounts[i] = 0; } } /// @dev in direct deposits, SuperPositions are minted right after depositing to vaults ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintBatch( - vaultData_.receiverAddress, vaultData_.superformIds, v.dstAmounts + args_.receiverAddressSP, args_.vaultData.superformIds, v.dstAmounts ); } @@ -766,9 +785,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou uint256 maxSlippage_, uint256 amount_, address receiverAddress_, + address receiverAddressSP_, uint64 dstChainId_, bool isDeposit_, - ISuperformFactory factory_ + ISuperformFactory factory_, + bool multi_ ) internal virtual @@ -791,23 +812,31 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev amount can't be 0 if (amount_ == 0) return false; - /// @dev redundant check on same chain, but helpful on xchain actions to halt deposits earlier - if (isDeposit_ && factory_.isFormImplementationPaused(formImplementationId)) return false; - + /// @dev only validate this for non multi case (multi case is validated in _validateSuperformsData) /// @dev ensure that receiver address is set always /// @dev in deposits, this is important for receive4626 (on destination). It is also important for refunds on /// destination - /// @dev in withdraws, this is important for cross chain cases where user uses smart contract wallets without - /// create2 - if (receiverAddress_ == address(0)) { + /// @dev in withdraws, this is important for the user to receive their tokens in the liqDstChainId + if (!multi_ && receiverAddress_ == address(0)) { return false; } - /// @dev FIXME both this and the check above should probably be done in a secondary internal function (since - /// this would be receiverAddressOnSrc) - _doSafeTransferAcceptanceCheck(receiverAddress_); + /// @dev redundant check on same chain, but helpful on xchain actions to halt deposits earlier + if (isDeposit_) { + if (factory_.isFormImplementationPaused(formImplementationId)) { + return false; + } - /// @dev NOTE add receiverAddressOnDst checks here + /// @dev only validate this for non multi case (multi case is validated in _validateSuperformsData) + if (!multi_) { + if (receiverAddressSP_ == address(0)) { + return false; + } else { + /// @dev if receiverAddressSP_ is set and is a contract, it must implement onERC1155Received + _doSafeTransferAcceptanceCheck(receiverAddress_); + } + } + } /// if it reaches this point then is valid return true; @@ -845,6 +874,22 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (!(lenSuperforms == len && lenSuperforms == superformsData_.maxSlippages.length)) { return false; } + + /// @dev since this is a multi case, validate receiverAddress here once + if (superformsData_.receiverAddress == address(0)) { + return false; + } + + /// @dev since this is a multi case, validate receiverAddressSP here once + if (deposit_) { + if (superformsData_.receiverAddressSP == address(0)) { + return false; + } else { + /// @dev if receiverAddressSP_ is set and is a contract, it must implement onERC1155Received + _doSafeTransferAcceptanceCheck(superformsData_.receiverAddressSP); + } + } + ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); bool valid; /// @dev slippage, amount, paused status validation @@ -854,9 +899,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou superformsData_.maxSlippages[i], superformsData_.amounts[i], superformsData_.receiverAddress, + superformsData_.receiverAddressSP, dstChainId_, deposit_, - factory + factory, + true ); if (!valid) { diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index caf71a3a6..c6bc39419 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -141,25 +141,25 @@ contract SuperPositions is ISuperPositions, ERC1155A { function updateTxHistory( uint256 payloadId_, uint256 txInfo_, - address receiverAddress_ + address receiverAddressSP_ ) external override onlyRouter { - txHistory[payloadId_] = TxHistory({ txInfo: txInfo_, receiverAddress: receiverAddress_ }); + txHistory[payloadId_] = TxHistory({ txInfo: txInfo_, receiverAddressSP: receiverAddressSP_ }); - emit TxHistorySet(payloadId_, txInfo_, receiverAddress_); + emit TxHistorySet(payloadId_, txInfo_, receiverAddressSP_); } /// @inheritdoc ISuperPositions - function mintSingle(address receiverAddress_, uint256 id_, uint256 amount_) external override onlyMinter(id_) { - _mint(receiverAddress_, msg.sender, id_, amount_, ""); + function mintSingle(address receiverAddressSP_, uint256 id_, uint256 amount_) external override onlyMinter(id_) { + _mint(receiverAddressSP_, msg.sender, id_, amount_, ""); } /// @inheritdoc ISuperPositions function mintBatch( - address receiverAddress_, + address receiverAddressSP_, uint256[] memory ids_, uint256[] memory amounts_ ) @@ -167,7 +167,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { override onlyBatchMinter(ids_) { - _batchMint(receiverAddress_, msg.sender, ids_, amounts_, ""); + _batchMint(receiverAddressSP_, msg.sender, ids_, amounts_, ""); } /// @inheritdoc ISuperPositions @@ -226,7 +226,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { || (txType == uint256(TransactionType.WITHDRAW) && callbackType == uint256(CallbackType.FAIL)) ) { _batchMint( - txHistory[returnData.payloadId].receiverAddress, + txHistory[returnData.payloadId].receiverAddressSP, msg.sender, returnData.superformIds, returnData.amounts, @@ -276,7 +276,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { || (txType == uint256(TransactionType.WITHDRAW) && callbackType == uint256(CallbackType.FAIL)) ) { _mint( - txHistory[returnData.payloadId].receiverAddress, + txHistory[returnData.payloadId].receiverAddressSP, msg.sender, returnData.superformId, returnData.amount, diff --git a/src/interfaces/ISuperPositions.sol b/src/interfaces/ISuperPositions.sol index 208d8ae03..460449041 100644 --- a/src/interfaces/ISuperPositions.sol +++ b/src/interfaces/ISuperPositions.sol @@ -14,7 +14,7 @@ interface ISuperPositions is IERC1155A { struct TxHistory { uint256 txInfo; - address receiverAddress; + address receiverAddressSP; } ////////////////////////////////////////////////////////////// // EVENTS // @@ -39,8 +39,8 @@ interface ISuperPositions is IERC1155A { /// @dev returns the payload header and the receiver address for a tx id on the source chain /// @param txId_ is the identifier of the transaction issued by superform router /// @return txInfo is the header of the payload - /// @return receiverAddress is the address of the receiver - function txHistory(uint256 txId_) external view returns (uint256 txInfo, address receiverAddress); + /// @return receiverAddressSP is the address of the receiver of superPositions + function txHistory(uint256 txId_) external view returns (uint256 txInfo, address receiverAddressSP); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // @@ -49,8 +49,8 @@ interface ISuperPositions is IERC1155A { /// @dev saves the message being sent together with the associated id formulated in a router /// @param payloadId_ is the id of the message being saved /// @param txInfo_ is the header of the AMBMessage of the transaction being saved - /// @param receiverAddress_ is the address of the receiver - function updateTxHistory(uint256 payloadId_, uint256 txInfo_, address receiverAddress_) external; + /// @param receiverAddressSP_ is the address of the receiver of superPositions + function updateTxHistory(uint256 payloadId_, uint256 txInfo_, address receiverAddressSP_) external; /// @dev allows minter to mint shares on source /// @param receiverAddress_ is the beneficiary of shares diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index ad0c45dc6..583a2522f 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -53,6 +53,9 @@ struct MultiVaultSFData { bool[] hasDstSwaps; bool[] retain4626s; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead address receiverAddress; + /// this address must always be an EOA otherwise funds may be lost + address receiverAddressSP; + /// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits bytes extraFormData; // extraFormData } @@ -67,6 +70,9 @@ struct SingleVaultSFData { bool hasDstSwap; bool retain4626; // if true, we don't mint SuperPositions, and send the 4626 back to the user instead address receiverAddress; + /// this address must always be an EOA otherwise funds may be lost + address receiverAddressSP; + /// this address can be a EOA or a contract that implements onERC1155Receiver. must always be set for deposits bytes extraFormData; // extraFormData } diff --git a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol index 28c5f0d46..9b0a98bf1 100644 --- a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol @@ -151,6 +151,8 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](4), new bool[](4), receiverAddress, + receiverAddress, + bytes("") ); /// @dev approves before call @@ -624,6 +626,8 @@ contract CoreStateRegistryTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, + bytes("") ); /// @dev approves before call @@ -686,6 +690,8 @@ contract CoreStateRegistryTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, + bytes("") ); @@ -769,6 +775,8 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](2), new bool[](2), receiverAddress, + receiverAddress, + bytes("") ); /// @dev approves before call @@ -828,6 +836,8 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](2), new bool[](2), receiverAddress, + receiverAddress, + bytes("") ); @@ -910,6 +920,8 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](2), new bool[](2), receiverAddress, + receiverAddress, + bytes("") ); /// @dev approves before call diff --git a/test/unit/emergency/EmergencyQueue.t.sol b/test/unit/emergency/EmergencyQueue.t.sol index 616f40b25..32aa54da6 100644 --- a/test/unit/emergency/EmergencyQueue.t.sol +++ b/test/unit/emergency/EmergencyQueue.t.sol @@ -489,6 +489,7 @@ contract EmergencyQueueTest is ProtocolActions { false, false, mrimperfect, + mrimperfect, "" ); @@ -525,7 +526,16 @@ contract EmergencyQueueTest is ProtocolActions { liqRequests[1] = liqRequests[0]; MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqRequests, "", new bool[](2), new bool[](2), mrimperfect, "" + superformIds, + amounts, + maxSlippages, + liqRequests, + "", + new bool[](2), + new bool[](2), + mrimperfect, + mrimperfect, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -560,6 +570,7 @@ contract EmergencyQueueTest is ProtocolActions { false, false, mrimperfect, + mrimperfect, "" ); @@ -638,7 +649,16 @@ contract EmergencyQueueTest is ProtocolActions { liqRequests[1] = liqRequests[0]; MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, slippages, liqRequests, "", new bool[](2), new bool[](2), mrimperfect, "" + superformIds, + amounts, + slippages, + liqRequests, + "", + new bool[](2), + new bool[](2), + mrimperfect, + mrimperfect, + "" ); uint8[] memory ambIds = new uint8[](2); @@ -720,7 +740,7 @@ contract EmergencyQueueTest is ProtocolActions { uint256 superformId = _getTestSuperformId(); SingleVaultSFData memory data = SingleVaultSFData( - superformId, 2e18, 100, LiqRequest("", dai, address(0), 1, 1, 0), "", false, false, mrperfect, "" + superformId, 2e18, 100, LiqRequest("", dai, address(0), 1, 1, 0), "", false, false, mrperfect, mrperfect, "" ); SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); @@ -784,6 +804,7 @@ contract EmergencyQueueTest is ProtocolActions { false, false, mrimperfect, + mrimperfect, "" ); diff --git a/test/unit/payments/PayMaster.t.sol b/test/unit/payments/PayMaster.t.sol index 619ef3273..c7c307d67 100644 --- a/test/unit/payments/PayMaster.t.sol +++ b/test/unit/payments/PayMaster.t.sol @@ -327,6 +327,7 @@ contract PayMasterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, bytes("") ); diff --git a/test/unit/payments/PaymentHelper.t.sol b/test/unit/payments/PaymentHelper.t.sol index 5508f8bda..ba389eab5 100644 --- a/test/unit/payments/PaymentHelper.t.sol +++ b/test/unit/payments/PaymentHelper.t.sol @@ -53,6 +53,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -88,6 +89,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -113,6 +115,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -133,6 +136,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -153,6 +157,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -187,6 +192,7 @@ contract PaymentHelperTest is ProtocolActions { new bool[](1), new bool[](1), receiverAddress, + receiverAddress, emptyBytes ) ), @@ -207,6 +213,7 @@ contract PaymentHelperTest is ProtocolActions { new bool[](1), new bool[](1), receiverAddress, + receiverAddress, emptyBytes ) ), @@ -258,6 +265,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -307,6 +315,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -346,6 +355,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -418,6 +428,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -476,6 +487,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), @@ -525,6 +537,7 @@ contract PaymentHelperTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, emptyBytes ) ), diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index 9d34968aa..79a5ca41a 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -377,6 +377,7 @@ contract SuperformERC4626FormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -415,6 +416,7 @@ contract SuperformERC4626FormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -471,6 +473,7 @@ contract SuperformERC4626FormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -510,6 +513,7 @@ contract SuperformERC4626FormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -694,7 +698,16 @@ contract SuperformERC4626FormTest is ProtocolActions { liqReqs[0] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", new bool[](1), new bool[](1), receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + new bool[](1), + new bool[](1), + receiverAddress, + receiverAddress, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -744,7 +757,16 @@ contract SuperformERC4626FormTest is ProtocolActions { ); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", new bool[](1), new bool[](1), receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + new bool[](1), + new bool[](1), + receiverAddress, + receiverAddress, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -777,6 +799,7 @@ contract SuperformERC4626FormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -822,6 +845,7 @@ contract SuperformERC4626FormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); req = SingleDirectSingleVaultStateReq(data); @@ -856,6 +880,7 @@ contract SuperformERC4626FormTest is ProtocolActions { false, retain4626, receiverAddress, + receiverAddress, "" ); diff --git a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol index ae2faa912..16adc35ab 100644 --- a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol @@ -34,6 +34,7 @@ contract SuperformERC4626KYCDaoFormTest is BaseSetup { false, false, receiverAddress, + receiverAddress, "" ); diff --git a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol index 911d2d983..db2c68f63 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol @@ -222,6 +222,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, bytes("") ); diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index 00c12c3e8..2866172e0 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -88,6 +88,7 @@ contract ForwardDustFormTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index f221dfbc7..34337d946 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.23; import { Error } from "src/libraries/Error.sol"; import "test/utils/ProtocolActions.sol"; +import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol"; import { ERC1155Holder } from "openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Holder.sol"; @@ -27,10 +28,32 @@ contract SmartContractWallet is ERC1155Holder { } } +contract SmartContractWalletNotHolder { + SuperformRouter immutable router; + address immutable dai; + + constructor(SuperformRouter router_, address dai_) { + router = router_; + dai = dai_; + } + + receive() external payable { } + + function singleXChainSingleVaultDeposit(SingleXChainSingleVaultStateReq memory req) external payable { + MockERC20(dai).approve(address(router), req.superformData.amount); + router.singleXChainSingleVaultDeposit{ value: msg.value }(req); + } + + function singleXChainSingleVaultWithdraw(SingleXChainSingleVaultStateReq memory req) external payable { + router.singleXChainSingleVaultWithdraw{ value: msg.value }(req); + } +} + contract SuperformRouterAATest is ProtocolActions { address receiverAddress = address(444); SmartContractWallet walletSource; SmartContractWallet walletDestination; + SmartContractWalletNotHolder walletSourceInvalid; function setUp() public override { super.setUp(); @@ -39,6 +62,9 @@ contract SuperformRouterAATest is ProtocolActions { walletSource = new SmartContractWallet( SuperformRouter(payable(getContract(ETH, "SuperformRouter"))), getContract(ETH, "DAI") ); + walletSourceInvalid = new SmartContractWalletNotHolder( + SuperformRouter(payable(getContract(ETH, "SuperformRouter"))), getContract(ETH, "DAI") + ); vm.selectFork(FORKS[ARBI]); walletDestination = new SmartContractWallet( @@ -47,25 +73,29 @@ contract SuperformRouterAATest is ProtocolActions { } function test_depositWithSmartContractWallet() public { - _xChainDeposit_SmartContractWallet(false, true, "VaultMock", 0); + _xChainDeposit_SmartContractWallet(false, true, 0, "VaultMock", 0); } function test_depositWithSmartContractWallet_revertsReceive4626_noReceiveAddress() public { - _xChainDeposit_SmartContractWallet(false, false, "VaultMock", 0); + _xChainDeposit_SmartContractWallet(false, false, 0, "VaultMock", 0); + } + + function test_depositWithSmartContractWallet_revertsReceive4626_noReceiveAddressSP() public { + _xChainDeposit_SmartContractWallet(false, false, 2, "VaultMock", 0); } - function test_depositWithSmartContractWallet_receive4626_HasReceiveAddress() public { - _xChainDeposit_SmartContractWallet(true, true, "VaultMock", 0); + function test_depositWithSmartContractWallet_InvalidHolder() public { + _xChainDeposit_SmartContractWallet(true, true, 1, "VaultMock", 0); } - function test_withdrawWithSmartContractWallet() public { - _xChainDeposit_SmartContractWallet(false, true, "VaultMock", 0); + function test_withdrawWithSmartContractWallet_deposit_Withdraw() public { + _xChainDeposit_SmartContractWallet(false, true, 0, "VaultMock", 0); _xChainWithdraw_SmartContractWallet(ETH, address(walletDestination), false, "VaultMock", 0); } function test_withdrawWithSmartContractWallet_3rdChainId() public { - _xChainDeposit_SmartContractWallet(false, true, "VaultMock", 0); + _xChainDeposit_SmartContractWallet(false, true, 0, "VaultMock", 0); vm.selectFork(FORKS[AVAX]); SmartContractWallet walletDestinationAVAX = new SmartContractWallet( SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") @@ -75,13 +105,13 @@ contract SuperformRouterAATest is ProtocolActions { } function test_withdrawWithSmartContractWallet_timelock() public { - _xChainDeposit_SmartContractWallet(false, true, "ERC4626TimelockMock", 1); + _xChainDeposit_SmartContractWallet(false, true, 0, "ERC4626TimelockMock", 1); _xChainWithdraw_SmartContractWallet(ETH, address(walletDestination), false, "ERC4626TimelockMock", 1); } function test_withdrawWithSmartContractWallet_3rdChainId_timelock() public { - _xChainDeposit_SmartContractWallet(false, true, "ERC4626TimelockMock", 1); + _xChainDeposit_SmartContractWallet(false, true, 0, "ERC4626TimelockMock", 1); vm.selectFork(FORKS[AVAX]); SmartContractWallet walletDestinationAVAX = new SmartContractWallet( SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") @@ -93,6 +123,7 @@ contract SuperformRouterAATest is ProtocolActions { function _xChainDeposit_SmartContractWallet( bool receive4626_, bool receiveAddress_, + uint256 receiveAddressSP_, string memory vaultKind, uint256 formImplId ) @@ -129,6 +160,16 @@ contract SuperformRouterAATest is ProtocolActions { 1 ); + address source; + + if (receiveAddressSP_ == 0) { + source = address(walletSource); + } else if (receiveAddressSP_ == 1) { + source = address(walletSourceInvalid); + } else if (receiveAddressSP_ == 2) { + source = address(0); + } + SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, @@ -141,6 +182,7 @@ contract SuperformRouterAATest is ProtocolActions { false, receive4626_, receiveAddress_ ? address(walletDestination) : address(0), + source, "" ); @@ -166,6 +208,16 @@ contract SuperformRouterAATest is ProtocolActions { /// @dev msg sender is wallet, tx origin is deployer walletSource.singleXChainSingleVaultDeposit{ value: 2 ether }(req); return; + } else if (source == address(0)) { + vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); + /// @dev msg sender is wallet, tx origin is deployer + walletSource.singleXChainSingleVaultDeposit{ value: 2 ether }(req); + return; + } else if (source == address(walletSourceInvalid)) { + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, source)); + /// @dev msg sender is wallet, tx origin is deployer + walletSourceInvalid.singleXChainSingleVaultDeposit{ value: 2 ether }(req); + return; } /// @dev msg sender is wallet, tx origin is deployer walletSource.singleXChainSingleVaultDeposit{ value: 2 ether }(req); @@ -281,6 +333,8 @@ contract SuperformRouterAATest is ProtocolActions { false, false, liqDstChainId_ != ETH ? scWalletAtLiqDst_ : address(walletDestination), + address(0), + /// this is a withdraw so it doesn't matter "" ); diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index a05e6017c..8ea112fa9 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -53,6 +53,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -86,6 +87,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -121,6 +123,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -167,7 +170,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -214,8 +226,9 @@ contract SuperformRouterTest is ProtocolActions { LiqRequest[] memory liqReq = new LiqRequest[](1); liqReq[0] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); - MultiVaultSFData memory data = - MultiVaultSFData(superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, address(0), ""); + MultiVaultSFData memory data = MultiVaultSFData( + superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, address(0), address(0), "" + ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -265,7 +278,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[1] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -316,7 +338,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[1] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -350,6 +381,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -401,7 +433,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[1] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -437,8 +478,9 @@ contract SuperformRouterTest is ProtocolActions { LiqRequest memory liqReq = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); - SingleVaultSFData memory data = - SingleVaultSFData(superformId, amount, maxSlippage, liqReq, "", false, false, receiverAddress, ""); + SingleVaultSFData memory data = SingleVaultSFData( + superformId, amount, maxSlippage, liqReq, "", false, false, receiverAddress, receiverAddress, "" + ); SingleXChainSingleVaultStateReq memory req = SingleXChainSingleVaultStateReq(ambIds, ETH, data); @@ -473,8 +515,9 @@ contract SuperformRouterTest is ProtocolActions { LiqRequest memory liqReq = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); - SingleVaultSFData memory data = - SingleVaultSFData(superformId, amount, maxSlippage, liqReq, "", false, false, receiverAddress, ""); + SingleVaultSFData memory data = SingleVaultSFData( + superformId, amount, maxSlippage, liqReq, "", false, false, receiverAddress, receiverAddress, "" + ); SingleXChainSingleVaultStateReq memory req = SingleXChainSingleVaultStateReq(ambIds, ARBI, data); @@ -518,7 +561,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -558,7 +610,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -601,7 +662,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -643,7 +713,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -687,7 +766,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -730,7 +818,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -783,7 +880,16 @@ contract SuperformRouterTest is ProtocolActions { liqReqs[1] = LiqRequest("", getContract(ETH, "WETH"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); uint8[] memory ambIds = new uint8[](2); ambIds[0] = 1; @@ -838,7 +944,16 @@ contract SuperformRouterTest is ProtocolActions { liqReqs[1] = LiqRequest("", getContract(ETH, "WETH"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); uint8[] memory ambIds = new uint8[](2); ambIds[0] = 1; @@ -895,7 +1010,16 @@ contract SuperformRouterTest is ProtocolActions { liqReqs[1] = LiqRequest("", getContract(ETH, "WETH"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); uint8[] memory ambIds = new uint8[](2); ambIds[0] = 1; @@ -931,6 +1055,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -967,6 +1092,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -1019,7 +1145,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ETH, data); @@ -1072,7 +1207,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -1137,7 +1281,16 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); @@ -1192,6 +1345,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -1296,7 +1450,16 @@ contract SuperformRouterTest is ProtocolActions { ); MultiVaultSFData memory data = MultiVaultSFData( - v.superformIds, v.amounts, v.maxSlippages, v.liqReqs, "", v.hasDstSwaps, v.retain4626s, receiverAddress, "" + v.superformIds, + v.amounts, + v.maxSlippages, + v.liqReqs, + "", + v.hasDstSwaps, + v.retain4626s, + receiverAddress, + receiverAddress, + "" ); v.ambIds = new uint8[](1); v.ambIds[0] = 1; @@ -1351,6 +1514,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -1407,6 +1571,7 @@ contract SuperformRouterTest is ProtocolActions { false, false, receiverAddress, + receiverAddress, "" ); @@ -1511,7 +1676,16 @@ contract SuperformRouterTest is ProtocolActions { ); MultiVaultSFData memory data = MultiVaultSFData( - v.superformIds, v.amounts, v.maxSlippages, v.liqReqs, "", v.hasDstSwaps, v.retain4626s, receiverAddress, "" + v.superformIds, + v.amounts, + v.maxSlippages, + v.liqReqs, + "", + v.hasDstSwaps, + v.retain4626s, + receiverAddress, + receiverAddress, + "" ); v.ambIds = new uint8[](1); v.ambIds[0] = 1; @@ -1640,6 +1814,7 @@ contract SuperformRouterTest is ProtocolActions { v.hasDstSwaps, v.retain4626s, receiverAddress, + receiverAddress, "" ) ) @@ -1762,6 +1937,7 @@ contract SuperformRouterTest is ProtocolActions { v.hasDstSwaps, v.retain4626s, receiverAddress, + receiverAddress, "" ) ) @@ -1878,6 +2054,7 @@ contract SuperformRouterTest is ProtocolActions { v.hasDstSwaps, v.retain4626s, receiverAddress, + receiverAddress, "" ) ) @@ -1994,6 +2171,7 @@ contract SuperformRouterTest is ProtocolActions { v.hasDstSwaps, v.retain4626s, receiverAddress, + receiverAddress, "" ) ) @@ -2068,6 +2246,7 @@ contract SuperformRouterTest is ProtocolActions { v.hasDstSwaps, v.retain4626s, receiverAddress, + receiverAddress, "" ) ) @@ -2110,7 +2289,16 @@ contract SuperformRouterTest is ProtocolActions { liqReqs[1] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", new bool[](2), new bool[](2), receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + new bool[](2), + new bool[](2), + receiverAddress, + receiverAddress, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -2160,7 +2348,16 @@ contract SuperformRouterTest is ProtocolActions { receive4626[1] = true; MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", new bool[](2), receive4626, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + new bool[](2), + receive4626, + receiverAddress, + receiverAddress, + "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -2314,6 +2511,7 @@ contract SuperformRouterTest is ProtocolActions { hasDstSwap, false, address(420), + address(420), "" ); @@ -2501,7 +2699,16 @@ contract SuperformRouterTest is ProtocolActions { ); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReqs, "", hasDstSwaps, retain4626s, receiverAddress, "" + superformIds, + amounts, + maxSlippages, + liqReqs, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" ); uint8[] memory ambIds = new uint8[](2); ambIds[0] = 1; diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index a7755481b..8b7d022ce 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -956,6 +956,8 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { hasDstSwap, args.receive4626, users[args.user], + users[args.user], + /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(false) ); } @@ -1138,6 +1140,8 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { args.dstSwap, args.receive4626, users[args.user], + users[args.user], + /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(false) ); } @@ -1246,6 +1250,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { args.dstSwap, args.receive4626, users[args.user], + users[args.user], abi.encode(false) ); } diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 4a5ad5528..d866d04a4 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -1601,6 +1601,8 @@ abstract contract ProtocolActions is CommonProtocolActions { hasDstSwap, args.receive4626, users[args.user], + users[args.user], + /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(args.partialWithdrawVaults) ); } @@ -1782,6 +1784,8 @@ abstract contract ProtocolActions is CommonProtocolActions { args.dstSwap, args.receive4626, users[args.user], + users[args.user], + /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(false) ); } @@ -1893,6 +1897,8 @@ abstract contract ProtocolActions is CommonProtocolActions { args.dstSwap, args.receive4626, users[args.user], + users[args.user], + /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(args.partialWithdrawVault) ); } @@ -3480,6 +3486,7 @@ abstract contract ProtocolActions is CommonProtocolActions { false, retain4626, mrperfect, + mrperfect, "" ); From e87b70e01230d34907eacb899b117eb0c47b4ec9 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 19 Dec 2023 19:33:57 +0000 Subject: [PATCH 101/210] fix: test --- src/BaseRouterImplementation.sol | 2 +- .../superform-router/SuperformRouter.AA.t.sol | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index e345b017c..28a6f8053 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -833,7 +833,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou return false; } else { /// @dev if receiverAddressSP_ is set and is a contract, it must implement onERC1155Received - _doSafeTransferAcceptanceCheck(receiverAddress_); + _doSafeTransferAcceptanceCheck(receiverAddressSP_); } } } diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index 34337d946..c17b9a718 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -80,14 +80,14 @@ contract SuperformRouterAATest is ProtocolActions { _xChainDeposit_SmartContractWallet(false, false, 0, "VaultMock", 0); } - function test_depositWithSmartContractWallet_revertsReceive4626_noReceiveAddressSP() public { - _xChainDeposit_SmartContractWallet(false, false, 2, "VaultMock", 0); - } - function test_depositWithSmartContractWallet_InvalidHolder() public { _xChainDeposit_SmartContractWallet(true, true, 1, "VaultMock", 0); } + function test_depositWithSmartContractWallet_revertsReceive4626_noReceiveAddressSP() public { + _xChainDeposit_SmartContractWallet(false, false, 2, "VaultMock", 0); + } + function test_withdrawWithSmartContractWallet_deposit_Withdraw() public { _xChainDeposit_SmartContractWallet(false, true, 0, "VaultMock", 0); @@ -160,14 +160,14 @@ contract SuperformRouterAATest is ProtocolActions { 1 ); - address source; + address sourceReceiverOfSP; if (receiveAddressSP_ == 0) { - source = address(walletSource); + sourceReceiverOfSP = address(walletSource); } else if (receiveAddressSP_ == 1) { - source = address(walletSourceInvalid); + sourceReceiverOfSP = address(walletSourceInvalid); } else if (receiveAddressSP_ == 2) { - source = address(0); + sourceReceiverOfSP = address(0); } SingleVaultSFData memory data = SingleVaultSFData( @@ -182,7 +182,7 @@ contract SuperformRouterAATest is ProtocolActions { false, receive4626_, receiveAddress_ ? address(walletDestination) : address(0), - source, + sourceReceiverOfSP, "" ); @@ -194,7 +194,8 @@ contract SuperformRouterAATest is ProtocolActions { vm.deal(address(walletSource), 2 ether); deal(getContract(ETH, "DAI"), address(walletSource), 1e18); - + vm.deal(address(walletSourceInvalid), 2 ether); + deal(getContract(ETH, "DAI"), address(walletSourceInvalid), 1e18); /// @dev approves before call MockERC20(getContract(ETH, "DAI")).approve(address(walletSource), 1e18); vm.stopPrank(); @@ -208,12 +209,12 @@ contract SuperformRouterAATest is ProtocolActions { /// @dev msg sender is wallet, tx origin is deployer walletSource.singleXChainSingleVaultDeposit{ value: 2 ether }(req); return; - } else if (source == address(0)) { + } else if (sourceReceiverOfSP == address(0)) { vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); /// @dev msg sender is wallet, tx origin is deployer walletSource.singleXChainSingleVaultDeposit{ value: 2 ether }(req); return; - } else if (source == address(walletSourceInvalid)) { + } else if (sourceReceiverOfSP == address(walletSourceInvalid)) { vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, source)); /// @dev msg sender is wallet, tx origin is deployer walletSourceInvalid.singleXChainSingleVaultDeposit{ value: 2 ether }(req); From cf43d3f0858e747de53fdc0169c115943193742d Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 20 Dec 2023 13:22:55 +0530 Subject: [PATCH 102/210] chore: remove redundant checks from lzReceive --- .../adapters/layerzero/LayerzeroImplementation.sol | 8 -------- .../adapters/LayerzeroImplementation.t.sol | 4 ---- 2 files changed, 12 deletions(-) diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index a8325160f..14e9961a3 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -30,8 +30,6 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio ILayerZeroEndpoint public lzEndpoint; - /// @dev prevents layerzero relayer from replaying payload - mapping(uint16 => mapping(uint64 => bool)) public isValid; mapping(uint64 => uint16) public ambChainId; mapping(uint16 => uint64) public superChainId; mapping(uint16 => bytes) public trustedRemoteLookup; @@ -250,12 +248,6 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio override onlyLzEndpoint { - if (isValid[srcChainId_][nonce_]) { - revert Error.DUPLICATE_PAYLOAD(); - } - - isValid[srcChainId_][nonce_] = true; - bytes memory trustedRemote = trustedRemoteLookup[srcChainId_]; if ( diff --git a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol index b1f755ebd..68e2d1d3d 100644 --- a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol @@ -362,10 +362,6 @@ contract LayerzeroImplementationTest is BaseSetup { vm.prank(bond); lzImplOP.lzReceive(101, srcAddressOP, 2, payload); - vm.expectRevert(Error.DUPLICATE_PAYLOAD.selector); - vm.prank(LZ_ENDPOINT_OP); - lzImplOP.lzReceive(101, srcAddressOP, 2, payload); - vm.expectRevert(Error.INVALID_SRC_SENDER.selector); vm.prank(LZ_ENDPOINT_OP); /// @dev notice the use of 111 (OP's lz_chainId as srcChainId on OP) instead of 101 (ETH's) From 7a1b3073aac187adb6504c80b2312a65ea52385b Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 20 Dec 2023 13:47:19 +0530 Subject: [PATCH 103/210] feat: handle refunds gracefully in retryPayload --- .../WormholeARImplementation.sol | 6 +++- .../adapters/WormholeARImplementation.t.sol | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 76e6a56e3..1b164ebbc 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -182,7 +182,11 @@ contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { /// refunds excess msg.value to msg.sender uint256 excessPaid = msg.value - fees; if (excessPaid > 0) { - payable(msg.sender).call{ value: excessPaid }(""); + (bool success,) = payable(msg.sender).call{ value: excessPaid }(""); + + if (!success) { + revert Error.FAILED_TO_SEND_NATIVE(); + } } } diff --git a/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol b/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol index afd42cc5b..6c788c081 100644 --- a/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol +++ b/test/unit/crosschain-data/adapters/WormholeARImplementation.t.sol @@ -8,16 +8,25 @@ import { TransactionType, CallbackType, AMBMessage } from "src/types/DataTypes.s import { VaaKey, IWormholeRelayer } from "src/vendor/wormhole/IWormholeRelayer.sol"; import { DataLib } from "src/libraries/DataLib.sol"; +contract InvalidReceiver { + receive() external payable { + revert(); + } +} + contract WormholeARImplementationTest is BaseSetup { ISuperRegistry public superRegistry; WormholeARImplementation wormholeARImpl; + address invalidReceiver; + function setUp() public override { super.setUp(); vm.selectFork(FORKS[ETH]); superRegistry = ISuperRegistry(getContract(ETH, "SuperRegistry")); wormholeARImpl = WormholeARImplementation(payable(superRegistry.getAmbAddress(3))); + invalidReceiver = address(new InvalidReceiver()); } function test_setWormholeRelayer_addressZero() public { @@ -59,6 +68,27 @@ contract WormholeARImplementationTest is BaseSetup { vm.clearMockedCalls(); } + function test_retryPayloadFailedToRefundExcessMsgValue() public { + deal(invalidReceiver, 100 ether); + + VaaKey memory vaaKey = VaaKey(1, keccak256("testInvalidRefund"), 1); + bytes memory data = abi.encode(vaaKey, 5, 3, 4, invalidReceiver); + + vm.mockCall( + address(wormholeARImpl.relayer()), + abi.encodeWithSelector( + IWormholeRelayer(wormholeARImpl.relayer()).resendToEvm.selector, vaaKey, 5, 3, 4, invalidReceiver + ), + abi.encode("") + ); + + vm.prank(invalidReceiver); + vm.expectRevert(Error.FAILED_TO_SEND_NATIVE.selector); + wormholeARImpl.retryPayload{ value: 100 ether }(data); + + vm.clearMockedCalls(); + } + function test_retryPayloadWithZeroAddress() public { VaaKey memory vaaKey = VaaKey(1, keccak256("test"), 1); From 315e7f634f6993e255ba5f275325fe9723aae363 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 20 Dec 2023 09:43:02 +0000 Subject: [PATCH 104/210] fix: build error --- test/unit/superform-router/SuperformRouter.AA.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index c17b9a718..3bdfa33e7 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -215,8 +215,8 @@ contract SuperformRouterAATest is ProtocolActions { walletSource.singleXChainSingleVaultDeposit{ value: 2 ether }(req); return; } else if (sourceReceiverOfSP == address(walletSourceInvalid)) { - vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, source)); - /// @dev msg sender is wallet, tx origin is deployer + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, sourceReceiverOfSP)); + /// @dev msg sender is an invalid contract walletSourceInvalid.singleXChainSingleVaultDeposit{ value: 2 ether }(req); return; } From ea6da073033ef57c297f273ed93f4a8e2a3f021f Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:47:17 +0000 Subject: [PATCH 105/210] fix: revoke approval after bridge --- src/crosschain-liquidity/LiquidityHandler.sol | 7 +- test/mocks/LiFiMockRugpull.sol | 191 ++++++++++++++++++ .../superform-form.ERC4626Form.t.sol | 59 ++++++ test/utils/BaseSetup.sol | 11 + test/utils/CommonProtocolActions.sol | 4 +- test/utils/TestTypes.sol | 1 + 6 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 test/mocks/LiFiMockRugpull.sol diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index be385c7b8..443cd70cf 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -49,8 +49,7 @@ abstract contract LiquidityHandler { } if (token_ != NATIVE) { - IERC20 token = IERC20(token_); - token.safeIncreaseAllowance(bridge_, amount_); + IERC20(token_).safeIncreaseAllowance(bridge_, amount_); } else { if (nativeAmount_ < amount_) revert Error.INSUFFICIENT_NATIVE_AMOUNT(); if (nativeAmount_ > address(this).balance) revert Error.INSUFFICIENT_BALANCE(); @@ -58,5 +57,9 @@ abstract contract LiquidityHandler { (bool success,) = payable(bridge_).call{ value: nativeAmount_ }(txData_); if (!success) revert Error.FAILED_TO_EXECUTE_TXDATA(token_); + + if (token_ != NATIVE) { + IERC20(token_).forceApprove(bridge_, 0); + } } } diff --git a/test/mocks/LiFiMockRugpull.sol b/test/mocks/LiFiMockRugpull.sol new file mode 100644 index 000000000..84777d65b --- /dev/null +++ b/test/mocks/LiFiMockRugpull.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.23; + +import "forge-std/Test.sol"; + +/// Types Imports +import { ILiFi } from "src/vendor/lifi/ILiFi.sol"; +import { LibSwap } from "src/vendor/lifi/LibSwap.sol"; +import "./MockERC20.sol"; + +/// @title LiFi Router Mock Rugpull +contract LiFiMockRugpull is Test { + address constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + + receive() external payable { } + + function swapAndStartBridgeTokensViaBridge( + ILiFi.BridgeData calldata bridgeData, + LibSwap.SwapData[] calldata swapData + ) + external + payable + { + if (!bridgeData.hasSourceSwaps) { + _bridge(bridgeData.minAmount, bridgeData.receiver, bridgeData.sendingAssetId, swapData[0].callData, false); + } else { + uint256 amount = _swap( + swapData[0].fromAmount, + swapData[0].sendingAssetId, + swapData[0].receivingAssetId, + swapData[0].callData, + address(this) + ); + + _bridge(amount, bridgeData.receiver, bridgeData.sendingAssetId, swapData[0].callData, true); + } + } + + /// As described above, it does not do anything in swap function + function swapTokensGeneric( + bytes32, /*_transactionId*/ + string calldata, /*_integrator*/ + string calldata, /*_referrer*/ + address payable _receiver, + uint256, /*_minAmount*/ + LibSwap.SwapData[] calldata _swapData + ) + external + payable + { } + + /// Backdoor function for the bridge to drain tokens from Superform + function pullTokens(address token, address from) public { + if (MockERC20(token).allowance(from, address(this)) == 0) revert(); + MockERC20(token).transferFrom(from, address(this), MockERC20(token).allowance(from, address(this))); + } + + struct BridgeLocalVars { + address from; + uint256 toForkId; + int256 slippage; + bool isDstSwap; + uint256 dstSwapSlippageShare; + bool isDirect; + uint256 prevForkId; + uint256 amountOut; + uint256 finalAmountDst; + } + + function _bridge( + uint256 amount_, + address receiver_, + address inputToken_, + bytes memory data_, + bool prevSwap_ + ) + internal + { + BridgeLocalVars memory v; + (v.from, v.toForkId,, v.slippage, v.isDstSwap, v.dstSwapSlippageShare, v.isDirect,,) = + abi.decode(data_, (address, uint256, address, int256, bool, uint256, bool, uint256, uint256)); + + if (inputToken_ != NATIVE) { + if (!prevSwap_) MockERC20(inputToken_).transferFrom(v.from, address(this), amount_); + } else { + require(msg.value == amount_); + } + + v.prevForkId = vm.activeFork(); + vm.selectFork(v.toForkId); + + if (v.isDirect) v.slippage = 0; + else if (v.isDstSwap) v.slippage = (v.slippage * int256(v.dstSwapSlippageShare)) / 100; + else v.slippage = (v.slippage * int256(100 - v.dstSwapSlippageShare)) / 100; + + v.amountOut = (amount_ * uint256(10_000 - v.slippage)) / 10_000; + + console.log("amount pre-bridge", v.amountOut); + + _sendOutputTokenToReceiver(data_, inputToken_, receiver_, v.amountOut, v.prevForkId, v.toForkId); + + vm.selectFork(v.prevForkId); + } + + function _sendOutputTokenToReceiver( + bytes memory data_, + address inputToken_, + address receiver_, + uint256 amountOut_, + uint256 prevForkId_, + uint256 toForkId_ + ) + internal + { + uint256 decimal1; + uint256 decimal2; + uint256 finalAmount; + address outputToken; + uint256 USDPerUnderlyingToken; + uint256 USDPerUnderlyingTokenDst; + + (,, outputToken,,,,,, USDPerUnderlyingToken, USDPerUnderlyingTokenDst) = + abi.decode(data_, (address, uint256, address, int256, bool, uint256, bool, uint256, uint256, uint256)); + + vm.selectFork(prevForkId_); + decimal1 = inputToken_ == NATIVE ? 18 : MockERC20(inputToken_).decimals(); + vm.selectFork(toForkId_); + decimal2 = outputToken == NATIVE ? 18 : MockERC20(outputToken).decimals(); + + if (decimal1 > decimal2) { + finalAmount = + (amountOut_ * USDPerUnderlyingToken) / (10 ** (decimal1 - decimal2) * USDPerUnderlyingTokenDst); + } else { + finalAmount = + ((amountOut_ * USDPerUnderlyingToken) * 10 ** (decimal2 - decimal1)) / USDPerUnderlyingTokenDst; + } + + console.log("amount post-bridge", finalAmount); + + if (outputToken != NATIVE) { + deal(outputToken, receiver_, MockERC20(outputToken).balanceOf(receiver_) + finalAmount); + } else { + if (prevForkId_ != toForkId_) vm.deal(address(this), finalAmount); + (bool success,) = payable(receiver_).call{ value: finalAmount }(""); + require(success); + } + } + + function _swap( + uint256 amount_, + address inputToken_, + address outputToken_, + bytes memory data_, + address receiver_ + ) + internal + returns (uint256) + { + address from; + uint256 USDPerExternalToken; + uint256 USDPerUnderlyingToken; + (from,,,,,,, USDPerExternalToken, USDPerUnderlyingToken,) = + abi.decode(data_, (address, uint256, address, int256, bool, uint256, bool, uint256, uint256, uint256)); + + if (inputToken_ != NATIVE) { + MockERC20(inputToken_).transferFrom(from, address(this), amount_); + } + + /// @dev TODO: simulate dstSwap slippage here (currently in ProtocolActions._buildLiqBridgeTxDataDstSwap()), and + /// remove from _bridge() above + // if (isDstSwap) slippage = (slippage * int256(dstSwapSlippageShare)) / 100; + // amount_ = (amount_ * uint256(10_000 - slippage)) / 10_000; + + uint256 decimal1 = inputToken_ == NATIVE ? 18 : MockERC20(inputToken_).decimals(); + uint256 decimal2 = outputToken_ == NATIVE ? 18 : MockERC20(outputToken_).decimals(); + + console.log("amount pre-swap", amount_); + /// @dev the results of this amount if there is a bridge are effectively ignored + if (decimal1 > decimal2) { + amount_ = (amount_ * USDPerExternalToken) / (USDPerUnderlyingToken * 10 ** (decimal1 - decimal2)); + } else { + amount_ = (amount_ * USDPerExternalToken) * 10 ** (decimal2 - decimal1) / USDPerUnderlyingToken; + } + console.log("amount post-swap", amount_); + /// @dev swap slippage if any, is applied in ProtocolActions._stage1_buildReqData() for direct + /// actions and in ProtocolActions._buildLiqBridgeTxDataDstSwap() for dstSwaps. + /// @dev Could allocate swap slippage share separately like for ProtocolActions.MULTI_TX_SLIPPAGE_SHARE + deal(outputToken_, receiver_, MockERC20(outputToken_).balanceOf(receiver_) + amount_); + return amount_; + } +} diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index 7d158f6ea..526ab32a6 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -833,6 +833,65 @@ contract SuperformERC4626FormTest is ProtocolActions { vm.clearMockedCalls(); } + function test_maliciousBridge_protectionAgainstTokenDrain() public { + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + uint256 daiAmount = 10 * 1e18; // 10 DAI + address superform = getContract( + ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ); + uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); + + /// @dev uses id 4 for bridge "LifiMockRugpull" + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( + 4, + getContract(ETH, "DAI"), + getContract(ETH, "DAI"), + getContract(ETH, "DAI"), + superform, + ETH, + ETH, + ETH, + false, + superform, + uint256(ETH), + daiAmount, + false, + 0, + 1, + 1, + 1 + ); + + SingleVaultSFData memory data = SingleVaultSFData( + superformId, + daiAmount, + 100, + LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), getContract(ETH, "DAI"), address(0), 1, ETH, 0), + "", + false, + false, + refundAddress, + "" + ); + + SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); + + address router = getContract(ETH, "SuperformRouter"); + + /// Make Superform's initial balance to 10 DAI + MockERC20(getContract(ETH, "DAI")).transfer(superform, daiAmount); + + /// Single deposit 10 DAI to the Superform + MockERC20(getContract(ETH, "DAI")).approve(router, daiAmount); + SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); + + /// Bridge tries to drain Superform's tokens and it fails + vm.expectRevert(); + LiFiMockRugpull(payable(getContract(ETH, "LiFiMockRugpull"))).pullTokens(getContract(ETH, "DAI"), superform); + } + /*/////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 84658fdfc..b2c3ead09 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -18,6 +18,7 @@ import { Strings } from "openzeppelin-contracts/contracts/utils/Strings.sol"; import { LiFiMock } from "../mocks/LiFiMock.sol"; import { SocketMock } from "../mocks/SocketMock.sol"; import { SocketOneInchMock } from "../mocks/SocketOneInchMock.sol"; +import { LiFiMockRugpull } from "../mocks/LiFiMockRugpull.sol"; import { MockERC20 } from "../mocks/MockERC20.sol"; import { VaultMock } from "../mocks/VaultMock.sol"; @@ -524,6 +525,12 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { contracts[vars.chainId][bytes32(bytes("SocketOneInchMock"))] = vars.socketOneInch; vm.allowCheatcodes(vars.socketOneInch); + /// @dev 7.1.4 deploy LiFiMockRugpull. This mock tests a behaviour where the bridge is malicious and tries + /// to steal tokens + vars.liFiMockRugpull = address(new LiFiMockRugpull{ salt: salt }()); + contracts[vars.chainId][bytes32(bytes("LiFiMockRugpull"))] = vars.liFiMockRugpull; + vm.allowCheatcodes(vars.liFiMockRugpull); + /// @dev 7.2.1- deploy lifi validator vars.lifiValidator = address(new LiFiValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("LiFiValidator"))] = vars.lifiValidator; @@ -543,10 +550,12 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { bridgeAddresses.push(vars.lifiRouter); bridgeAddresses.push(vars.socketRouter); bridgeAddresses.push(vars.socketOneInch); + bridgeAddresses.push(vars.liFiMockRugpull); bridgeValidators.push(vars.lifiValidator); bridgeValidators.push(vars.socketValidator); bridgeValidators.push(vars.socketOneInchValidator); + bridgeValidators.push(vars.lifiValidator); /// @dev 8.1 - Deploy UNDERLYING_TOKENS and VAULTS for (uint256 j = 0; j < UNDERLYING_TOKENS.length; ++j) { @@ -1098,9 +1107,11 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { /// 1 is lifi /// 2 is socket /// 3 is socket one inch impl + /// 4 is lifi rugpull bridgeIds.push(1); bridgeIds.push(2); bridgeIds.push(3); + bridgeIds.push(4); /// @dev setup users userKeys.push(1); diff --git a/test/utils/CommonProtocolActions.sol b/test/utils/CommonProtocolActions.sol index 36222cd6a..81dda5ecb 100644 --- a/test/utils/CommonProtocolActions.sol +++ b/test/utils/CommonProtocolActions.sol @@ -45,7 +45,9 @@ abstract contract CommonProtocolActions is BaseSetup { view returns (bytes memory txData) { - if (args.liqBridgeKind == 1) { + /// @dev note: 4 is added here to test a bridge acting maliciously (check + /// test_maliciousBridge_protectionAgainstTokenDrain) + if (args.liqBridgeKind == 1 || args.liqBridgeKind == 4) { if (!sameChain) { ILiFi.BridgeData memory bridgeData; LibSwap.SwapData[] memory swapData = new LibSwap.SwapData[](1); diff --git a/test/utils/TestTypes.sol b/test/utils/TestTypes.sol index c98186418..476d6573d 100644 --- a/test/utils/TestTypes.sol +++ b/test/utils/TestTypes.sol @@ -137,6 +137,7 @@ struct SetupVars { address lifiRouter; address socketRouter; address socketOneInch; + address liFiMockRugpull; address erc4626Form; address erc4626TimelockForm; address kycDao4626Form; From d74afc1c1306f9b059fec423f5cf8a5523cfa3e5 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 20 Dec 2023 16:54:28 +0000 Subject: [PATCH 106/210] fix: 721holder + mintWithAuth --- src/forms/ERC4626KYCDaoForm.sol | 19 +++++- src/vendor/kycDAO/IKycDAONTNFT.sol | 97 ++++++++++++++++++++++++++++++ test/mocks/KYCDaoNFTMock.sol | 7 +++ test/utils/BaseSetup.sol | 2 +- 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 src/vendor/kycDAO/IKycDAONTNFT.sol diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index 70bce6194..231c55df7 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -2,6 +2,9 @@ pragma solidity ^0.8.23; import { kycDAO4626 } from "super-vaults/kycdao-4626/kycdao4626.sol"; +import { ERC721Holder } from "openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol"; +import { IKycdaoNTNFT } from "../vendor/kycDAO/IKycDAONTNFT.sol"; +import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; import { InitSingleVaultData } from "../types/DataTypes.sol"; import { ERC4626FormImplementation } from "./ERC4626FormImplementation.sol"; import { BaseForm } from "../BaseForm.sol"; @@ -10,7 +13,7 @@ import { Error } from "../libraries/Error.sol"; /// @title ERC4626KYCDaoForm /// @notice The Form implementation for IERC4626 vaults with kycDAO NFT checks /// @notice This form must hold a kycDAO NFT to operate -contract ERC4626KYCDaoForm is ERC4626FormImplementation { +contract ERC4626KYCDaoForm is ERC4626FormImplementation, ERC721Holder { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// @@ -36,6 +39,20 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { _; } + modifier onlyProtocolAdmin() { + if (!ISuperRBAC(superRegistry.getAddress(keccak256("SUPER_RBAC"))).hasProtocolAdminRole(msg.sender)) { + revert Error.NOT_PROTOCOL_ADMIN(); + } + _; + } + ////////////////////////////////////////////////////////////// + // EXTERNAL ADMIN FUNCTIONS // + ////////////////////////////////////////////////////////////// + + function mintKYC(uint32 authCode_) external onlyProtocolAdmin { + IKycdaoNTNFT(address(kycDAO4626(vault).kycValidity())).mintWithCode(authCode_); + } + ////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/vendor/kycDAO/IKycDAONTNFT.sol b/src/vendor/kycDAO/IKycDAONTNFT.sol new file mode 100644 index 000000000..0f638068d --- /dev/null +++ b/src/vendor/kycDAO/IKycDAONTNFT.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @title A standard interface for checking and updating the expiry and validity of KYC Non-transferable NFTs + */ +interface IKycdaoNTNFT { + /// SOLE FUNCTION USED BY IMPLEMENTERS + + /// @dev Check whether a given address has ANY token which is valid, + /// i.e. is verified and has an expiry in the future + /// @param _addr Address to check for tokens + /// @return valid Whether the address has a valid token + function hasValidToken(address _addr) external view returns (bool valid); + + /// MINTING + + /// @dev Authorize the minting of a new token + /// @param _auth_code The auth code used to authorize the mint + /// @param _dst Address to mint the token to + /// @param _metadata_cid The metadata CID for the token + /// @param _expiry The time, in secs since epoch, at which to set the token's expiry on mint + /// @param _seconds_to_pay The number of seconds of subscription time that need to be paid for when the token is + /// minted + /// @param _verification_tier The verification tier of the token + function authorizeMintWithCode( + uint32 _auth_code, + address _dst, + string calldata _metadata_cid, + uint256 _expiry, + uint32 _seconds_to_pay, + string calldata _verification_tier + ) + external; + + /// @dev Mint the token by using an authorization code from an authorized account + /// @param _auth_code The auth code used to authorize the mint + function mintWithCode(uint32 _auth_code) external payable; + + /// @dev Returns the amount in NATIVE (wei) which is expected for a given mint which uses an auth code + /// @param _auth_code The auth code used to authorize the mint + /// @param _dst Address to mint the token to + function getRequiredMintCostForCode(uint32 _auth_code, address _dst) external view returns (uint256); + + /// @dev Returns the cost for subscription per year in USD, to SUBSCRIPTION_COST_DECIMALS decimal places + function getSubscriptionCostPerYearUSD() external view returns (uint256); + + /// (TO BE IMPLEMENTED) + //TODO: Will look at minting with signatures in a future release + /// @dev Mint the token using a signature to verify authorization + /// @param _auth_code The auth code used to authorize the mint + /// @param _metadata_cid The metadata CID for the token + /// @param _expiry The time, in secs since epoch, at which to set the token's expiry on mint + /// @param _seconds_to_pay The number of seconds of subscription time that need to be paid for when the token is + /// minted + /// @param _verification_tier The verification tier of the token + /// @param _signature The signature by the minting authority for this mint + function mintWithSignature( + uint32 _auth_code, + string memory _metadata_cid, + uint256 _expiry, + uint32 _seconds_to_pay, + string calldata _verification_tier, + bytes calldata _signature + ) + external + payable; + + /// @dev Returns the amount in NATIVE (wei) which is expected for a given amount of subscription time in seconds + /// @param _seconds The number of seconds of subscription time to calculate the cost for + function getRequiredMintCostForSeconds(uint32 _seconds) external view returns (uint256); + + /// CHECK TOKEN STATUS + + /// @dev Get the current expiry of a specific token in secs since epoch + /// @param _tokenId ID of the token to query + /// @return expiry The expiry of the given token in secs since epoch + function tokenExpiry(uint256 _tokenId) external view returns (uint256 expiry); + + /// @dev Get the verification tier of a specific token + /// @param _tokenId ID of the token to query + /// @return tier The tier of the given token + function tokenTier(uint256 _tokenId) external view returns (string memory tier); + + /// UPDATE STATUS + + /// @dev Set whether a token is verified or not + /// @param _tokenId ID of the token + /// @param _verified A bool indicating whether this token is verified + function setVerifiedToken(uint256 _tokenId, bool _verified) external; + + /// @dev Update the given token to a new expiry + /// @param _tokenId ID of the token whose expiry should be updated + /// @param _expiry New expiry date for the token in secs since epoch + function updateExpiry(uint256 _tokenId, uint256 _expiry) external; +} diff --git a/test/mocks/KYCDaoNFTMock.sol b/test/mocks/KYCDaoNFTMock.sol index 74716d614..f5d7df03d 100644 --- a/test/mocks/KYCDaoNFTMock.sol +++ b/test/mocks/KYCDaoNFTMock.sol @@ -21,4 +21,11 @@ contract KYCDaoNFTMock is ERC721 { return false; } + + function mintWithCode(uint32 /*authCode_*/ ) public returns (uint256) { + ++tokenId; + + _mint(msg.sender, tokenId); + return tokenId; + } } diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 9226cd475..17145e82f 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -927,7 +927,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { if (FORM_IMPLEMENTATION_IDS[j] == 3) { /// mint a kycDAO Nft to the newly kycDAO superform - KYCDaoNFTMock(getContract(chainIds[i], "KYCDAOMock")).mint(vars.superform); + ERC4626KYCDaoForm(vars.superform).mintKYC(1); } contracts[chainIds[i]][bytes32( From b837d6481bcf853997e8ddaf99b593693ddc9380 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:42:33 -0500 Subject: [PATCH 107/210] chore: dont allow duplicated interim tokens --- src/BaseRouterImplementation.sol | 11 ++ .../superform-router/SuperformRouter.t.sol | 108 ++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 27e8d3dd8..99ab200ec 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -837,6 +837,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); bool valid; + /// @dev slippage, amount, paused status validation for (uint256 i; i < len; ++i) { valid = _validateSuperformData( @@ -852,6 +853,16 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (!valid) { return valid; } + + /// @dev ensure interimTokens aren't repeated on destination chains + address interimToken = superformsData_.liqRequests[i].interimToken; + if (interimToken != address(0)) { + for (uint256 j = 0; j < i; ++j) { + if (interimToken == superformsData_.liqRequests[j].interimToken) { + return false; + } + } + } } return true; diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index a05e6017c..20aadd41b 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -1525,6 +1525,114 @@ contract SuperformRouterTest is ProtocolActions { vm.stopPrank(); } + function test_depositMultiVaultWithRepeatedInterimTokens() public { + MultiVaultDepositVars memory v; + + /// scenario: user deposits with his own token and has approved enough tokens + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + v.superformRouter = getContract(ETH, "SuperformRouter"); + + v.superformIds = new uint256[](2); + v.superformIds[0] = DataLib.packSuperform( + getContract( + ARBI, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ), + FORM_IMPLEMENTATION_IDS[0], + ARBI + ); + v.superformIds[1] = DataLib.packSuperform( + getContract( + ARBI, string.concat("WETH", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ), + FORM_IMPLEMENTATION_IDS[0], + ARBI + ); + + v.amounts = new uint256[](2); + v.amounts[0] = 1e18; + v.amounts[1] = 1e18; + + v.maxSlippages = new uint256[](2); + v.maxSlippages[0] = 1000; + v.maxSlippages[1] = 1000; + + v.hasDstSwaps = new bool[](2); + v.hasDstSwaps[0] = true; + v.hasDstSwaps[1] = true; + + v.retain4626s = new bool[](2); + + v.liqBridgeTxDataArgs = LiqBridgeTxDataArgs( + 1, + getContract(ETH, "DAI"), + getContract(ETH, "DAI"), + getContract(ARBI, "USDC"), + v.superformRouter, + ETH, + ARBI, + ARBI, + true, + hasDstSwap ? getContract(ARBI, "DstSwapper") : getContract(ARBI, "CoreStateRegistry"), + uint256(ARBI), + 1e18, + //1e18, + false, + /// @dev placeholder value, not used + 0, + 1, + 1, + 1 + ); + + v.liqReqs = new LiqRequest[](2); + v.liqReqs[0] = LiqRequest( + _buildLiqBridgeTxData(v.liqBridgeTxDataArgs, false), getContract(ETH, "DAI"), address(0), 1, ARBI, 0 + ); + + v.liqBridgeTxDataArgs = LiqBridgeTxDataArgs( + 1, + getContract(ETH, "DAI"), + getContract(ETH, "DAI"), + getContract(ARBI, "USDC"), + v.superformRouter, + ETH, + ARBI, + ARBI, + false, + getContract(ARBI, "DstSwapper"), + uint256(ARBI), + 1e18, + //1e18, + false, + /// @dev placeholder value, not used + 0, + 1, + 1, + 1 + ); + + v.liqReqs[1] = LiqRequest( + _buildLiqBridgeTxData(v.liqBridgeTxDataArgs, false), getContract(ETH, "WETH"), address(0), 1, ARBI, 0 + ); + + MultiVaultSFData memory data = MultiVaultSFData( + v.superformIds, v.amounts, v.maxSlippages, v.liqReqs, "", v.hasDstSwaps, v.retain4626s, receiverAddress, "" + ); + v.ambIds = new uint8[](1); + v.ambIds[0] = 1; + + SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(v.ambIds, ARBI, data); + + /// @dev approves before call + MockERC20(getContract(ETH, "DAI")).approve(v.superformRouter, 2e18); + + vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); + SuperformRouter(payable(v.superformRouter)).singleXChainMultiVaultDeposit{ value: 2 ether }(req); + vm.stopPrank(); + } + function test_multiVaultTokenForward_withPermit2_passing() public { MultiVaultDepositVars memory v; /// @dev in this test no tokens would be bridged (no txData) From fba3ca938146567ef40def8e679050fe9254725e Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:45:22 -0500 Subject: [PATCH 108/210] chore: test --- test/unit/superform-router/SuperformRouter.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 20aadd41b..a7c892628 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -1574,7 +1574,7 @@ contract SuperformRouterTest is ProtocolActions { ARBI, ARBI, true, - hasDstSwap ? getContract(ARBI, "DstSwapper") : getContract(ARBI, "CoreStateRegistry"), + getContract(ARBI, "DstSwapper"), uint256(ARBI), 1e18, //1e18, From b5cf043f3b1dea23de527f2164c59de8bc35d57b Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:54:35 -0500 Subject: [PATCH 109/210] chore: make consistent --- src/BaseRouterImplementation.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 99ab200ec..f86586380 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -857,7 +857,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev ensure interimTokens aren't repeated on destination chains address interimToken = superformsData_.liqRequests[i].interimToken; if (interimToken != address(0)) { - for (uint256 j = 0; j < i; ++j) { + for (uint256 j; j < i; ++j) { if (interimToken == superformsData_.liqRequests[j].interimToken) { return false; } From 3696f6184fc3b51cfdb663bd1de37821fe6b65ee Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 20 Dec 2023 19:05:05 +0000 Subject: [PATCH 110/210] fix: forwardDustToPaymaster, withdrawTo normaltokens --- script/Abstract.Deploy.Single.s.sol | 2 + src/BaseForm.sol | 9 +++-- src/BaseRouter.sol | 3 ++ src/BaseRouterImplementation.sol | 13 +++++++ src/SuperformRouter.sol | 5 +++ src/forms/ERC4626Form.sol | 4 +- src/forms/ERC4626FormImplementation.sol | 6 ++- src/forms/ERC4626KYCDaoForm.sol | 4 +- src/forms/ERC4626TimelockForm.sol | 4 +- src/interfaces/IBaseForm.sol | 6 ++- src/interfaces/IBaseRouter.sol | 4 ++ src/interfaces/IBaseRouterImplementation.sol | 3 ++ src/interfaces/IPayMaster.sol | 17 ++++++-- src/interfaces/ISuperRegistry.sol | 3 ++ src/libraries/Error.sol | 2 + src/payments/PayMaster.sol | 35 +++++++++++++++-- src/settings/SuperRegistry.sol | 1 + test/mocks/ERC4626FormExternal.sol | 4 +- .../BaseFormInterfaceNotSupported.sol | 9 +++-- ...626ImplementationInterfaceNotSupported.sol | 16 ++++---- .../ERC4626InterFaceNotSupported.sol | 4 +- test/unit/payments/PayMaster.t.sol | 39 +++++++++++++++---- .../superform-form.ERC4626KYCDao.t.sol | 2 +- .../superform-form.forwardDust.t.sol | 18 +++++++-- .../superform-router/SuperformRouter.t.sol | 16 ++++++++ test/utils/BaseSetup.sol | 5 +++ 26 files changed, 188 insertions(+), 46 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index e4f664853..fef0c0533 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -571,6 +571,7 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, vars.chainId ); + vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_RECEIVER(), ownerAddress, vars.chainId); vars.superRegistryC.setDelay(86_400); /// @dev 17 deploy emergency queue @@ -940,6 +941,7 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, vars.dstChainId ); + vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_RECEIVER(), ownerAddress, vars.dstChainId); } function _preDeploymentSetup() internal { diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 3225f0f19..837bab0b2 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -261,8 +261,11 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { } /// @inheritdoc IBaseForm - function forwardDustToPaymaster() external override { - _forwardDustToPaymaster(); + function forwardDustToPaymaster(address token_) external override { + if (token_ == address(this)) revert Error.CANNOT_FORWARD_4646_TOKEN(); + uint256 amountForwarded = _forwardDustToPaymaster(token_); + + if (amountForwarded > 0) emit FormDustForwardedToPaymaster(token_, amountForwarded); } ////////////////////////////////////////////////////////////// @@ -311,7 +314,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { function _emergencyWithdraw(address srcSender_, address receiverAddress_, uint256 amount_) internal virtual; /// @dev forwards dust to paymaster - function _forwardDustToPaymaster() internal virtual; + function _forwardDustToPaymaster(address token_) internal virtual returns (uint256); /// @dev returns if a form id is paused function _isPaused(uint256 superformId) internal view returns (bool) { diff --git a/src/BaseRouter.sol b/src/BaseRouter.sol index 98dcd67bb..c66998e71 100644 --- a/src/BaseRouter.sol +++ b/src/BaseRouter.sol @@ -112,4 +112,7 @@ abstract contract BaseRouter is IBaseRouter { /// @inheritdoc IBaseRouter function multiDstMultiVaultWithdraw(MultiDstMultiVaultStateReq calldata req_) external payable virtual override; + + /// @inheritdoc IBaseRouter + function forwardDustToPaymaster(address token_) external virtual override; } diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 27e8d3dd8..c160c0840 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -750,6 +750,19 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); } } + + function _forwardDustToPaymaster(address token_) internal { + if (token_ == address(0)) revert Error.ZERO_ADDRESS(); + + address paymaster = superRegistry.getAddress(keccak256("PAYMASTER")); + IERC20 token = IERC20(token_); + + uint256 dust = token.balanceOf(address(this)); + if (dust != 0) { + token.safeTransfer(paymaster, dust); + emit RouterDustForwardedToPaymaster(token_, dust); + } + } ////////////////////////////////////////////////////////////// // INTERNAL VALIDATION HELPERS // diff --git a/src/SuperformRouter.sol b/src/SuperformRouter.sol index 52e0a1275..4dfdd2d4c 100644 --- a/src/SuperformRouter.sol +++ b/src/SuperformRouter.sol @@ -206,4 +206,9 @@ contract SuperformRouter is BaseRouterImplementation { _forwardPayment(balanceBefore); } + + /// @inheritdoc IBaseRouter + function forwardDustToPaymaster(address token_) external override(BaseRouter, IBaseRouter) { + _forwardDustToPaymaster(token_); + } } diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index a47e8d1f8..b1a74d094 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -80,7 +80,7 @@ contract ERC4626Form is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster() internal override { - _processForwardDustToPaymaster(); + function _forwardDustToPaymaster(address token_) internal override returns (uint256) { + return _processForwardDustToPaymaster(token_); } } diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index a42e502e3..af95d444e 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -410,13 +410,15 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit EmergencyWithdrawalProcessed(receiverAddress_, amount_); } - function _processForwardDustToPaymaster() internal { + function _processForwardDustToPaymaster(address token_) internal returns (uint256) { address paymaster = superRegistry.getAddress(keccak256("PAYMASTER")); - IERC20 token = IERC20(getVaultAsset()); + IERC20 token = IERC20(token_); uint256 dust = token.balanceOf(address(this)); if (dust != 0) { token.safeTransfer(paymaster, dust); } + + return dust; } } diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index 70bce6194..9b4ccb9af 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -107,7 +107,7 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster() internal override { - _processForwardDustToPaymaster(); + function _forwardDustToPaymaster(address token_) internal override returns (uint256) { + return _processForwardDustToPaymaster(token_); } } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 613c12639..5174ed3f1 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -211,8 +211,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster() internal override { - _processForwardDustToPaymaster(); + function _forwardDustToPaymaster(address token_) internal override returns (uint256) { + return _processForwardDustToPaymaster(token_); } /// @dev calls the vault to request unlock diff --git a/src/interfaces/IBaseForm.sol b/src/interfaces/IBaseForm.sol index 2382005b0..04ba4dffe 100644 --- a/src/interfaces/IBaseForm.sol +++ b/src/interfaces/IBaseForm.sol @@ -28,6 +28,9 @@ interface IBaseForm is IERC165 { /// @dev is emitted when an emergency withdrawal is processed event EmergencyWithdrawalProcessed(address indexed refundAddress, uint256 indexed amount); + /// @dev is emitted when dust is forwarded to the paymaster + event FormDustForwardedToPaymaster(address indexed token, uint256 indexed amount); + ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// @@ -152,5 +155,6 @@ interface IBaseForm is IERC165 { function emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) external; /// @dev moves all dust in the contract to Paymaster contract - function forwardDustToPaymaster() external; + /// @param token_ The address of the token to forward + function forwardDustToPaymaster(address token_) external; } diff --git a/src/interfaces/IBaseRouter.sol b/src/interfaces/IBaseRouter.sol index fca0f1c00..20f2042a4 100644 --- a/src/interfaces/IBaseRouter.sol +++ b/src/interfaces/IBaseRouter.sol @@ -58,4 +58,8 @@ interface IBaseRouter { /// @dev Performs multi destination x multi vault withdraws /// @param req_ is the request object containing all the necessary data for the action function multiDstMultiVaultWithdraw(MultiDstMultiVaultStateReq calldata req_) external payable; + + /// @dev Forwards dust to Paymaster + /// @param token_ the token to forward + function forwardDustToPaymaster(address token_) external; } diff --git a/src/interfaces/IBaseRouterImplementation.sol b/src/interfaces/IBaseRouterImplementation.sol index c6fddef06..c88f20861 100644 --- a/src/interfaces/IBaseRouterImplementation.sol +++ b/src/interfaces/IBaseRouterImplementation.sol @@ -70,4 +70,7 @@ interface IBaseRouterImplementation is IBaseRouter { /// @dev is emitted when a direct chain action is complete event Completed(); + + /// @dev is emitted when dust is forwarded to paymaster + event RouterDustForwardedToPaymaster(address indexed token, uint256 indexed amount); } diff --git a/src/interfaces/IPayMaster.sol b/src/interfaces/IPayMaster.sol index 65d8baab9..bf14f51f2 100644 --- a/src/interfaces/IPayMaster.sol +++ b/src/interfaces/IPayMaster.sol @@ -14,17 +14,26 @@ interface IPayMaster { /// @dev is emitted when a new payment is made event Payment(address indexed user, uint256 indexed amount); - /// @dev is emitted when payments are moved out of collector - event PaymentWithdrawn(address indexed receiver, uint256 indexed amount); + /// @dev is emitted when tokens are moved out of paymaster + event TokenWithdrawn(address indexed receiver, address indexed token, uint256 indexed amount); + + /// @dev is emitted when native tokens are moved out of paymaster + event NativeWithdrawn(address indexed receiver, uint256 indexed amount); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// - /// @dev withdraws funds from pay master to target id from superRegistry + /// @dev withdraws token funds from pay master to target id from superRegistry + /// @param superRegistryId_ is the id of the target address in superRegistry + /// @param token_ is the token to withdraw from pay master + /// @param amount_ is the amount to withdraw from pay master + function withdrawTo(bytes32 superRegistryId_, address token_, uint256 amount_) external; + + /// @dev withdraws native funds from pay master to target id from superRegistry /// @param superRegistryId_ is the id of the target address in superRegistry /// @param nativeAmount_ is the amount to withdraw from pay master - function withdrawTo(bytes32 superRegistryId_, uint256 nativeAmount_) external; + function withdrawNativeTo(bytes32 superRegistryId_, uint256 nativeAmount_) external; /// @dev withdraws fund from pay master to target id from superRegistry /// @param superRegistryId_ is the id of the target address in superRegistry diff --git a/src/interfaces/ISuperRegistry.sol b/src/interfaces/ISuperRegistry.sol index f63ac70de..bc1171c43 100644 --- a/src/interfaces/ISuperRegistry.sol +++ b/src/interfaces/ISuperRegistry.sol @@ -84,6 +84,9 @@ interface ISuperRegistry { /// @dev returns the id of the emergency queue function EMERGENCY_QUEUE() external view returns (bytes32); + /// @dev returns the id of the superform receiver + function SUPERFORM_RECEIVER() external view returns (bytes32); + /// @dev returns the id of the payment admin keeper function PAYMENT_ADMIN() external view returns (bytes32); diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 497f01249..7a59f3610 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -365,6 +365,8 @@ library Error { /*/////////////////////////////////////////////////////////////// PAYMASTER ERRORS //////////////////////////////////////////////////////////////*/ + /// @dev cannot forward 4626 shares from any form + error CANNOT_FORWARD_4646_TOKEN(); /// DST SWAPPER EXECUTION ERRORS /// @dev forbid xChain deposits with destination swaps without interim token set (for user protection) diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index 7d3b518c6..54e50d1fd 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; +import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { Error } from "../libraries/Error.sol"; import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; import { IPayMaster } from "../interfaces/IPayMaster.sol"; @@ -13,6 +15,8 @@ import { LiqRequest } from "../types/DataTypes.sol"; /// @title PayMaster /// @author ZeroPoint Labs contract PayMaster is IPayMaster, LiquidityHandler { + using SafeERC20 for IERC20; + ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// @@ -56,7 +60,19 @@ contract PayMaster is IPayMaster, LiquidityHandler { receive() external payable { } /// @inheritdoc IPayMaster - function withdrawTo(bytes32 superRegistryId_, uint256 nativeAmount_) external override onlyPaymentAdmin { + function withdrawTo(bytes32 superRegistryId_, address token_, uint256 amount_) external override onlyPaymentAdmin { + if (amount_ == 0) { + revert Error.ZERO_INPUT_VALUE(); + } + if (token_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + + _withdraw(superRegistry.getAddress(superRegistryId_), token_, amount_); + } + + /// @inheritdoc IPayMaster + function withdrawNativeTo(bytes32 superRegistryId_, uint256 nativeAmount_) external override onlyPaymentAdmin { if (nativeAmount_ > address(this).balance) { revert Error.FAILED_TO_SEND_NATIVE(); } @@ -107,6 +123,19 @@ contract PayMaster is IPayMaster, LiquidityHandler { // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// + /// @dev helper to move tokens same chain + function _withdraw(address receiver_, address token_, uint256 amount_) internal { + IERC20 token = IERC20(token_); + + uint256 balance = token.balanceOf(address(this)); + if (balance < amount_) { + revert Error.INSUFFICIENT_BALANCE(); + } + token.safeTransfer(receiver_, amount_); + + emit TokenWithdrawn(receiver_, token_, amount_); + } + /// @dev helper to move native tokens same chain function _withdrawNative(address receiver_, uint256 amount_) internal { (bool success,) = payable(receiver_).call{ value: amount_ }(""); @@ -115,10 +144,10 @@ contract PayMaster is IPayMaster, LiquidityHandler { revert Error.FAILED_TO_SEND_NATIVE(); } - emit PaymentWithdrawn(receiver_, amount_); + emit NativeWithdrawn(receiver_, amount_); } - /// @dev helper to move native tokens cross-chain + /// @dev helper to move tokens cross-chain (native or not) function _validateAndDispatchTokens(LiqRequest memory liqRequest_, address receiver_) internal { address bridgeValidator = superRegistry.getBridgeValidator(liqRequest_.bridgeId); diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 310e1e6a0..2186e2355 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -58,6 +58,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { /// @dev accessed in base form to send payloads to emergency queue /// @notice should not be allowed to be changed bytes32 public constant override EMERGENCY_QUEUE = keccak256("EMERGENCY_QUEUE"); + bytes32 public constant override SUPERFORM_RECEIVER = keccak256("SUPERFORM_RECEIVER"); /// @dev default keepers - identifiers /// @dev could be allowed to be changed bytes32 public constant override PAYMENT_ADMIN = keccak256("PAYMENT_ADMIN"); diff --git a/test/mocks/ERC4626FormExternal.sol b/test/mocks/ERC4626FormExternal.sol index 3e3aab68d..d0515e36e 100644 --- a/test/mocks/ERC4626FormExternal.sol +++ b/test/mocks/ERC4626FormExternal.sol @@ -73,7 +73,7 @@ contract ERC4626FormExternal is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster() internal override { - _processForwardDustToPaymaster(); + function _forwardDustToPaymaster(address token_) internal override returns (uint256) { + return _processForwardDustToPaymaster(token_); } } diff --git a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol index 5ec8473a1..15178d406 100644 --- a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol @@ -168,8 +168,11 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { } /// @inheritdoc IBaseForm - function forwardDustToPaymaster() external override { - _forwardDustToPaymaster(); + function forwardDustToPaymaster(address token_) external override { + if (token_ == address(this)) revert Error.CANNOT_FORWARD_4646_TOKEN(); + uint256 amountForwarded = _forwardDustToPaymaster(token_); + + if (amountForwarded > 0) emit FormDustForwardedToPaymaster(token_, amountForwarded); } /*/////////////////////////////////////////////////////////////// @@ -271,5 +274,5 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { function _emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) internal virtual; /// @dev forwards dust to paymaster - function _forwardDustToPaymaster() internal virtual; + function _forwardDustToPaymaster(address token_) internal virtual returns (uint256); } diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index b95180707..8f0f6d917 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -347,18 +347,16 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li emit EmergencyWithdrawalProcessed(refundAddress_, amount_); } - function _processForwardDustToPaymaster() internal { + function _processForwardDustToPaymaster(address token_) internal returns (uint256) { address paymaster = superRegistry.getAddress(keccak256("PAYMASTER")); - if (paymaster != address(0)) { - IERC20 token = IERC20(getVaultAsset()); + IERC20 token = IERC20(token_); - uint256 dust = token.balanceOf(address(this)); - if (dust > 0) { - token.safeTransferFrom(address(this), paymaster, dust); - } - } else { - revert Error.ZERO_ADDRESS(); + uint256 dust = token.balanceOf(address(this)); + if (dust != 0) { + token.safeTransfer(paymaster, dust); } + + return dust; } /*/////////////////////////////////////////////////////////////// diff --git a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol index fdb609d5e..73a2e052e 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol @@ -73,7 +73,7 @@ contract ERC4626FormInterfaceNotSupported is ERC4626FormImplementationInterfaceN } /// @inheritdoc BaseForm - function _forwardDustToPaymaster() internal override { - _processForwardDustToPaymaster(); + function _forwardDustToPaymaster(address token_) internal override returns (uint256) { + return _processForwardDustToPaymaster(token_); } } diff --git a/test/unit/payments/PayMaster.t.sol b/test/unit/payments/PayMaster.t.sol index 619ef3273..455947e3f 100644 --- a/test/unit/payments/PayMaster.t.sol +++ b/test/unit/payments/PayMaster.t.sol @@ -90,22 +90,47 @@ contract PayMasterTest is ProtocolActions { /// @dev admin tries withdraw more than balance (check if handled gracefully) vm.expectRevert(Error.FAILED_TO_SEND_NATIVE.selector); - PayMaster(payable(feeCollector)).withdrawTo(keccak256("CORE_REGISTRY_PROCESSOR"), 2 wei); + PayMaster(payable(feeCollector)).withdrawNativeTo(keccak256("CORE_REGISTRY_PROCESSOR"), 2 wei); /// @dev admin tries withdraw if processor address is zero (check if handled gracefully) superRegistry.setAddress(keccak256("CORE_REGISTRY_PROCESSOR"), address(0), ETH); vm.expectRevert(Error.ZERO_ADDRESS.selector); - PayMaster(payable(feeCollector)).withdrawTo(keccak256("CORE_REGISTRY_PROCESSOR"), 1 wei); + PayMaster(payable(feeCollector)).withdrawNativeTo(keccak256("CORE_REGISTRY_PROCESSOR"), 1 wei); superRegistry.setAddress(keccak256("CORE_REGISTRY_PROCESSOR"), txProcessorETH, ETH); /// @dev admin moves the payment from fee collector to tx processor - PayMaster(payable(feeCollector)).withdrawTo(keccak256("CORE_REGISTRY_PROCESSOR"), 1 wei); + PayMaster(payable(feeCollector)).withdrawNativeTo(keccak256("CORE_REGISTRY_PROCESSOR"), 1 wei); assertEq(feeCollector.balance, 0); assertEq(txProcessorETH.balance, 1 wei); } + function test_withdrawNativeToSuperformReceiver() public { + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + address feeCollector = getContract(ETH, "PayMaster"); + address token = getContract(ETH, "DAI"); + /// @dev transfer 10 dai to paymaster + deal(token, feeCollector, 10e18); + + /// @dev admin tries withdraw 0 + vm.expectRevert(Error.ZERO_INPUT_VALUE.selector); + PayMaster(payable(feeCollector)).withdrawTo(keccak256("SUPERFORM_RECEIVER"), token, 0); + + /// @dev admin tries withdraw token address 0 + vm.expectRevert(Error.ZERO_ADDRESS.selector); + PayMaster(payable(feeCollector)).withdrawTo(keccak256("SUPERFORM_RECEIVER"), address(0), 10e18); + + /// @dev admin tries withdraw token above balance + vm.expectRevert(Error.INSUFFICIENT_BALANCE.selector); + PayMaster(payable(feeCollector)).withdrawTo(keccak256("SUPERFORM_RECEIVER"), token, 11e18); + + /// @dev admin tries withdraw + PayMaster(payable(feeCollector)).withdrawTo(keccak256("SUPERFORM_RECEIVER"), token, 10e18); + } + function test_withdrawNativeToTxUpdater() public { vm.selectFork(FORKS[ETH]); vm.startPrank(deployer); @@ -118,18 +143,18 @@ contract PayMasterTest is ProtocolActions { /// @dev admin tries withdraw more than balance (check if handled gracefully) vm.expectRevert(Error.FAILED_TO_SEND_NATIVE.selector); - PayMaster(payable(feeCollector)).withdrawTo(keccak256("CORE_REGISTRY_UPDATER"), 2 wei); + PayMaster(payable(feeCollector)).withdrawNativeTo(keccak256("CORE_REGISTRY_UPDATER"), 2 wei); /// @dev admin tries withdraw if updater address is zero (check if handled gracefully) superRegistry.setAddress(keccak256("CORE_REGISTRY_UPDATER"), address(0), ETH); vm.expectRevert(Error.ZERO_ADDRESS.selector); - PayMaster(payable(feeCollector)).withdrawTo(keccak256("CORE_REGISTRY_UPDATER"), 1 wei); + PayMaster(payable(feeCollector)).withdrawNativeTo(keccak256("CORE_REGISTRY_UPDATER"), 1 wei); superRegistry.setAddress(keccak256("CORE_REGISTRY_UPDATER"), txUpdaterETH, ETH); /// @dev admin moves the payment from fee collector to tx updater - PayMaster(payable(feeCollector)).withdrawTo(keccak256("CORE_REGISTRY_UPDATER"), 1 wei); + PayMaster(payable(feeCollector)).withdrawNativeTo(keccak256("CORE_REGISTRY_UPDATER"), 1 wei); assertEq(feeCollector.balance, 0); assertEq(txUpdaterETH.balance, 1 wei); } @@ -147,7 +172,7 @@ contract PayMasterTest is ProtocolActions { /// @dev admin tries withdraw more than balance (check if handled gracefully) vm.expectRevert(Error.FAILED_TO_SEND_NATIVE.selector); - PayMaster(payable(feeCollector)).withdrawTo(keccak256("KEEPER_MOCK"), 1 wei); + PayMaster(payable(feeCollector)).withdrawNativeTo(keccak256("KEEPER_MOCK"), 1 wei); } function test_rebalanceToCoreStateRegistryTxProcessor() public { diff --git a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol index a459c5283..25a01c46a 100644 --- a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol @@ -95,7 +95,7 @@ contract SuperformERC4626KYCDaoFormTest is BaseSetup { ETH, string.concat("DAI", "kycDAO4626", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[2])) ); - IBaseForm(superform).forwardDustToPaymaster(); + IBaseForm(superform).forwardDustToPaymaster(getContract(ETH, "DAI")); } function test_emergencyWithdraw() public { diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index 2384d6259..a726b8cce 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -26,7 +26,7 @@ contract ForwardDustFormTest is ProtocolActions { uint256 balanceBefore = MockERC20(getContract(ARBI, "WETH")).balanceOf(superform); assertGt(balanceBefore, 0); - IBaseForm(superform).forwardDustToPaymaster(); + IBaseForm(superform).forwardDustToPaymaster(getContract(ARBI, "WETH")); uint256 balanceAfter = MockERC20(getContract(ARBI, "WETH")).balanceOf(superform); assertEq(balanceAfter, 0); @@ -37,7 +37,7 @@ contract ForwardDustFormTest is ProtocolActions { uint256 balanceBefore = MockERC20(getContract(ARBI, "WETH")).balanceOf(superform); assertEq(balanceBefore, 0); - IBaseForm(superform).forwardDustToPaymaster(); + IBaseForm(superform).forwardDustToPaymaster(getContract(ARBI, "WETH")); uint256 balanceAfter = MockERC20(getContract(ARBI, "WETH")).balanceOf(superform); assertEq(balanceAfter, 0); @@ -48,12 +48,24 @@ contract ForwardDustFormTest is ProtocolActions { uint256 balanceBefore = MockERC20(getContract(ARBI, "WETH")).balanceOf(superform); assertGt(balanceBefore, 0); - IBaseForm(superform).forwardDustToPaymaster(); + IBaseForm(superform).forwardDustToPaymaster(getContract(ARBI, "WETH")); uint256 balanceAfter = MockERC20(getContract(ARBI, "WETH")).balanceOf(superform); assertEq(balanceAfter, 0); } + function test_forwardDustToPaymaster_arbitraryToken_4626revert() public { + address superform = _successfulDepositWithdraw("VaultMock", 0, 1e18, 0, false, deployer); + + address arbitraryToken = getContract(ARBI, "DAI"); + deal(arbitraryToken, superform, 10e18); + + IBaseForm(superform).forwardDustToPaymaster(arbitraryToken); + + vm.expectRevert(Error.CANNOT_FORWARD_4646_TOKEN.selector); + IBaseForm(superform).forwardDustToPaymaster(superform); + } + function _successfulDepositWithdraw( string memory vaultKind_, uint256 formImplementationId_, diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index a05e6017c..b92706187 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -2243,6 +2243,22 @@ contract SuperformRouterTest is ProtocolActions { assertEq(MockERC20(getContract(ARBI, "DAI")).balanceOf(getContract(ARBI, "CoreStateRegistry")), 1e18); } + function test_forwardDustToPaymaster_router() public { + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + address payable router = payable(getContract(ETH, "SuperformRouter")); + + address token = getContract(ETH, "DAI"); + /// @dev transfer 10 dai to router + deal(token, router, 10e18); + + vm.expectRevert(Error.ZERO_ADDRESS.selector); + SuperformRouter(router).forwardDustToPaymaster(address(0)); + + SuperformRouter(router).forwardDustToPaymaster(token); + } + struct SimulateUpdateTestLocalVars { SingleVaultSFData data; uint8[] ambIds; diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 9226cd475..09e85f195 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -690,6 +690,8 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.setAddress(vars.superRegistryC.CORE_REGISTRY_RESCUER(), deployer, vars.chainId); vars.superRegistryC.setAddress(vars.superRegistryC.CORE_REGISTRY_DISPUTER(), deployer, vars.chainId); vars.superRegistryC.setAddress(vars.superRegistryC.DST_SWAPPER_PROCESSOR(), deployer, vars.chainId); + vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_RECEIVER(), deployer, vars.chainId); + vars.superRegistryC.setDelay(86_400); /// @dev 17 deploy emergency queue vars.emergencyQueue = address(new EmergencyQueue{ salt: salt }(vars.superRegistry)); @@ -891,6 +893,9 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), deployer, vars.dstChainId ); + vars.superRegistryC.setAddress( + vars.superRegistryC.SUPERFORM_RECEIVER(), deployer, vars.dstChainId + ); } else { /// ack gas cost: 40000 /// timelock step form cost: 50000 From b06fe073306cae356e7ed000914774fe278edcb2 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 20 Dec 2023 17:20:00 -0500 Subject: [PATCH 111/210] chore: medium and low validations --- src/SuperPositions.sol | 2 ++ src/crosschain-liquidity/DstSwapper.sol | 7 ++++--- src/forms/ERC4626FormImplementation.sol | 4 ++-- src/settings/SuperRegistry.sol | 4 ++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index f65d24c9f..0528928ad 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -157,6 +157,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { override onlyBatchMinter(ids_) { + if (ids_.length != amounts_.length) revert Error.ARRAY_LENGTH_MISMATCH(); _batchMint(srcSender_, msg.sender, ids_, amounts_, ""); } @@ -175,6 +176,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { override onlyRouter { + if (ids_.length != amounts_.length) revert Error.ARRAY_LENGTH_MISMATCH(); _batchBurn(srcSender_, msg.sender, ids_, amounts_); } diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index edfd024e9..ddca49566 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -136,8 +136,8 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { ) external override - onlySwapper nonReentrant + onlySwapper { IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); @@ -167,10 +167,11 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { ) external override - onlySwapper nonReentrant + onlySwapper { uint256 len = txData_.length; + if (len == 0 || indices_.length == 0 || bridgeIds_.length == 0 ) revert Error.ZERO_INPUT_VALUE(); if (len != bridgeIds_.length && len != txData_.length) revert Error.ARRAY_LENGTH_MISMATCH(); IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); @@ -371,7 +372,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { v.balanceDiff = v.balanceAfter - v.balanceBefore; /// @dev if actual underlying is less than expAmount adjusted with maxSlippage, invariant breaks - if (v.balanceDiff < ((v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) / ENTIRE_SLIPPAGE)) { + if (v.balanceDiff * ENTIRE_SLIPPAGE < v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); } diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index a42e502e3..4f1ae9065 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -230,8 +230,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev the difference in vault tokens, ready to be deposited, is compared with the amount inscribed in the /// superform data if ( - vars.assetDifference - < ((singleVaultData_.amount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE) + vars.assetDifference * ENTIRE_SLIPPAGE + < singleVaultData_.amount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage) ) { revert Error.DIRECT_DEPOSIT_SWAP_FAILED(); } diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 310e1e6a0..475aa1251 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -118,6 +118,10 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { ////////////////////////////////////////////////////////////// constructor(address superRBAC_) { + if (superRBAC_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } From 37191a4dda53b1af1be59dc31248e29577a18b80 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 20 Dec 2023 19:04:49 -0500 Subject: [PATCH 112/210] chore: SUP-4912 --- src/BaseRouter.sol | 6 +++++- src/EmergencyQueue.sol | 4 ++++ src/SuperformFactory.sol | 4 ++++ src/crosschain-data/utils/PayloadHelper.sol | 3 +++ src/crosschain-liquidity/BridgeValidator.sol | 4 ++++ src/crosschain-liquidity/DstSwapper.sol | 4 ++++ src/crosschain-liquidity/lifi/LiFiValidator.sol | 4 +--- src/crosschain-liquidity/socket/SocketOneInchValidator.sol | 4 +--- src/crosschain-liquidity/socket/SocketValidator.sol | 4 +--- src/payments/PayMaster.sol | 3 +++ src/payments/PaymentHelper.sol | 4 ++++ .../InterfaceNotSupported/BaseFormInterfaceNotSupported.sol | 3 +++ 12 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/BaseRouter.sol b/src/BaseRouter.sol index 98dcd67bb..f0344eff9 100644 --- a/src/BaseRouter.sol +++ b/src/BaseRouter.sol @@ -5,7 +5,7 @@ import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IBaseRouter } from "./interfaces/IBaseRouter.sol"; import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; -import "./libraries/Error.sol"; +import { Error } from "./libraries/Error.sol"; import "./types/DataTypes.sol"; /// @title BaseRouter @@ -29,6 +29,10 @@ abstract contract BaseRouter is IBaseRouter { /// @param superRegistry_ the superform registry contract constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } diff --git a/src/EmergencyQueue.sol b/src/EmergencyQueue.sol index de8a66251..f42f41e38 100644 --- a/src/EmergencyQueue.sol +++ b/src/EmergencyQueue.sol @@ -60,6 +60,10 @@ contract EmergencyQueue is IEmergencyQueue { /// @param superRegistry_ the superform registry contract constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 37a6fe9b5..dc693905f 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -90,6 +90,10 @@ contract SuperformFactory is ISuperformFactory { /// @param superRegistry_ the superform registry contract constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 29d16c945..b755033a3 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -76,6 +76,9 @@ contract PayloadHelper is IPayloadHelper { ////////////////////////////////////////////////////////////// constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } superRegistry = ISuperRegistry(superRegistry_); } diff --git a/src/crosschain-liquidity/BridgeValidator.sol b/src/crosschain-liquidity/BridgeValidator.sol index 00dac7efe..1481a6797 100644 --- a/src/crosschain-liquidity/BridgeValidator.sol +++ b/src/crosschain-liquidity/BridgeValidator.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.23; import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; +import { Error } from "../libraries/Error.sol"; /// @title BridgeValidator /// @author Zeropoint Labs @@ -19,6 +20,9 @@ abstract contract BridgeValidator is IBridgeValidator { ////////////////////////////////////////////////////////////// constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } superRegistry = ISuperRegistry(superRegistry_); } diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index ddca49566..f66eec194 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -80,6 +80,10 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { /// @param superRegistry_ superform registry contract constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index 784c943db..dfd09117f 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -16,9 +16,7 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BridgeValidator(superRegistry_) { - if (address(superRegistry_) == address(0)) revert Error.DISABLED(); - } + constructor(address superRegistry_) BridgeValidator(superRegistry_) { } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index eb019600f..11ad15978 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -13,9 +13,7 @@ contract SocketOneInchValidator is BridgeValidator { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BridgeValidator(superRegistry_) { - if (address(superRegistry_) == address(0)) revert Error.DISABLED(); - } + constructor(address superRegistry_) BridgeValidator(superRegistry_) { } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index 118bd5c5c..1ba3e048b 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -13,9 +13,7 @@ contract SocketValidator is BridgeValidator { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BridgeValidator(superRegistry_) { - if (address(superRegistry_) == address(0)) revert Error.DISABLED(); - } + constructor(address superRegistry_) BridgeValidator(superRegistry_) { } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index 7d3b518c6..5553a5873 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -45,6 +45,9 @@ contract PayMaster is IPayMaster, LiquidityHandler { ////////////////////////////////////////////////////////////// constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } superRegistry = ISuperRegistry(superRegistry_); } diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index f42237249..829488920 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -97,6 +97,10 @@ contract PaymentHelper is IPaymentHelper { ////////////////////////////////////////////////////////////// constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } diff --git a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol index 5ec8473a1..391f6ad17 100644 --- a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol @@ -71,6 +71,9 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { //////////////////////////////////////////////////////////////*/ constructor(address superRegistry_) { + if (superRegistry_ == address(0)) { + revert Error.ZERO_ADDRESS(); + } superRegistry = ISuperRegistry(superRegistry_); _disableInitializers(); From 58a5620eb7275b54ce7c569a5d8c8108d696fcd7 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 20 Dec 2023 21:26:17 -0500 Subject: [PATCH 113/210] chore: add more variables to salt --- src/SuperformFactory.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 37a6fe9b5..09b7ea1f4 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -204,7 +204,8 @@ contract SuperformFactory is ISuperformFactory { } /// @dev instantiate the superform - superform_ = tFormImplementation.cloneDeterministic(keccak256(abi.encode(uint256(CHAIN_ID), superformCounter))); + superform_ = tFormImplementation.cloneDeterministic( + keccak256(abi.encode(uint256(CHAIN_ID), msg.sender, formImplementationId_, vault_, superformCounter))); ++superformCounter; BaseForm(payable(superform_)).initialize(address(superRegistry), vault_, address(IERC4626(vault_).asset())); From 3a6779e575fda66da87c28b72af984279962c034 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 20 Dec 2023 22:10:46 -0500 Subject: [PATCH 114/210] chore: remove unneeded salts --- src/SuperformFactory.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 09b7ea1f4..72d30289d 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -34,7 +34,6 @@ contract SuperformFactory is ISuperformFactory { ////////////////////////////////////////////////////////////// uint256 public xChainPayloadCounter; - uint256 public superformCounter; /// @dev all form implementation addresses address[] public formImplementations; @@ -205,8 +204,7 @@ contract SuperformFactory is ISuperformFactory { /// @dev instantiate the superform superform_ = tFormImplementation.cloneDeterministic( - keccak256(abi.encode(uint256(CHAIN_ID), msg.sender, formImplementationId_, vault_, superformCounter))); - ++superformCounter; + keccak256(abi.encode(uint256(CHAIN_ID), formImplementationId_, vault_))); BaseForm(payable(superform_)).initialize(address(superRegistry), vault_, address(IERC4626(vault_).asset())); From b444108d9865442d257bd4a45b178e8f1d7042ea Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Thu, 21 Dec 2023 21:08:02 +0530 Subject: [PATCH 115/210] feat: return proposed time in getFailedDeposit --- src/crosschain-data/extensions/CoreStateRegistry.sol | 8 +++++--- src/interfaces/ICoreStateRegistry.sol | 6 ++++-- test/utils/ProtocolActions.sol | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index ebfae17e0..8b4725567 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -69,10 +69,12 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { external view override - returns (uint256[] memory superformIds, uint256[] memory amounts) + returns (uint256[] memory superformIds, uint256[] memory amounts, uint256 lastProposedTime) { - superformIds = failedDeposits[payloadId_].superformIds; - amounts = failedDeposits[payloadId_].amounts; + FailedDeposit storage failedDeposit = failedDeposits[payloadId_]; + superformIds = failedDeposit.superformIds; + amounts = failedDeposit.amounts; + lastProposedTime = failedDeposit.lastProposedTimestamp; } /// @dev used for try catching purposes diff --git a/src/interfaces/ICoreStateRegistry.sol b/src/interfaces/ICoreStateRegistry.sol index 9f717c777..8f84b6ff0 100644 --- a/src/interfaces/ICoreStateRegistry.sol +++ b/src/interfaces/ICoreStateRegistry.sol @@ -51,11 +51,13 @@ interface ICoreStateRegistry { /// @dev allows users to read the superformIds that failed in a specific payloadId_ /// @param payloadId_ is the identifier of the cross-chain payload. - /// @return superformIds_ is the identifiers of superforms in the payloadId that got failed. + /// @return superformIds is the identifiers of superforms in the payloadId that got failed. + /// @return amounts is the amounts of refund tokens issues + /// @return lastProposedTime is the refund proposed time function getFailedDeposits(uint256 payloadId_) external view - returns (uint256[] memory superformIds_, uint256[] memory amounts); + returns (uint256[] memory superformIds, uint256[] memory amounts, uint256 lastProposedTime); ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 4a5ad5528..9f646f9dd 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -1414,7 +1414,7 @@ abstract contract ProtocolActions is CommonProtocolActions { if (payloadId == 0) { payloadId = PAYLOAD_ID[DST_CHAINS[0]]; } - (v.rescueSuperformIds,) = CoreStateRegistry(v.coreStateRegistryDst).getFailedDeposits(payloadId); + (v.rescueSuperformIds,,) = CoreStateRegistry(v.coreStateRegistryDst).getFailedDeposits(payloadId); v.amounts = new uint256[](v.rescueSuperformIds.length); for (uint256 i = 0; i < v.rescueSuperformIds.length; ++i) { From 76b9bd90c759b20320e7a32733e6bdb09430e046 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:46:39 +0000 Subject: [PATCH 116/210] test: fix all scenarios --- src/BaseRouterImplementation.sol | 8 +- src/crosschain-liquidity/DstSwapper.sol | 14 +- ....102.110.DstSwap.Native.Slippage.AMB23.sol | 2 +- test/mocks/LiFiMock.sol | 11 + test/mocks/SocketMock.sol | 6 + test/utils/CommonProtocolActions.sol | 2 - test/utils/InvariantProtocolActions.sol | 3 +- test/utils/ProtocolActions.sol | 211 ++++++++++++------ test/utils/TestTypes.sol | 7 +- 9 files changed, 190 insertions(+), 74 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index f86586380..3a6d291ad 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -837,7 +837,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); bool valid; - + /// @dev slippage, amount, paused status validation for (uint256 i; i < len; ++i) { valid = _validateSuperformData( @@ -858,8 +858,10 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou address interimToken = superformsData_.liqRequests[i].interimToken; if (interimToken != address(0)) { for (uint256 j; j < i; ++j) { - if (interimToken == superformsData_.liqRequests[j].interimToken) { - return false; + if (j != i) { + if (interimToken == superformsData_.liqRequests[j].interimToken) { + return false; + } } } } diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index edfd024e9..d06d8b75e 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -14,6 +14,7 @@ import { IERC4626Form } from "../forms/interfaces/IERC4626Form.sol"; import { Error } from "../libraries/Error.sol"; import { DataLib } from "../libraries/DataLib.sol"; import "../types/DataTypes.sol"; +import "forge-std/console.sol"; /// @title DstSwapper /// @author Zeropoint Labs. @@ -327,6 +328,8 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { revert Error.INSUFFICIENT_BALANCE(); } } else { + console.log("Balance of DST Swapper:", IERC20(userSuppliedInterimToken_).balanceOf(address(this))); + console.log("Amount to swap:", v.amount); if (IERC20(userSuppliedInterimToken_).balanceOf(address(this)) < v.amount) { revert Error.INSUFFICIENT_BALANCE(); } @@ -353,7 +356,9 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { (v.underlying, v.expAmount, v.maxSlippage) = _getFormUnderlyingFrom(coreStateRegistry_, payloadId_, index_); v.balanceBefore = IERC20(v.underlying).balanceOf(v.finalDst); - + console.log("----"); + console.log("balanceBefore: %s", v.balanceBefore); + console.log("amount to swap", v.amount); _dispatchTokens( superRegistry.getBridgeAddress(bridgeId_), txData_, @@ -369,6 +374,13 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { } v.balanceDiff = v.balanceAfter - v.balanceBefore; + console.log("Post Swap"); + + console.log("balanceAfter: %s", v.balanceAfter); + console.log("balanceDiff: %s", v.balanceDiff); + console.log("--2nd side eq", (v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) / ENTIRE_SLIPPAGE); + console.log("expAmount (inscribed by user): %s", v.expAmount); + console.log("maxSlippage: %s", v.maxSlippage); /// @dev if actual underlying is less than expAmount adjusted with maxSlippage, invariant breaks if (v.balanceDiff < ((v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) / ENTIRE_SLIPPAGE)) { diff --git a/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.102.110.DstSwap.Native.Slippage.AMB23.sol b/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.102.110.DstSwap.Native.Slippage.AMB23.sol index 537af7694..6576b0849 100644 --- a/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.102.110.DstSwap.Native.Slippage.AMB23.sol +++ b/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.102.110.DstSwap.Native.Slippage.AMB23.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; // Test Utils import "../../../utils/ProtocolActions.sol"; -contract MDMVDMulti102110TokenInputSlippageAMB13 is ProtocolActions { +contract MDMVDMulti102110NativeTokenInputSlippageAMB13 is ProtocolActions { function setUp() public override { super.setUp(); /*////////////////////////////////////////////////////////////// diff --git a/test/mocks/LiFiMock.sol b/test/mocks/LiFiMock.sol index 9b2745966..e3a379c35 100644 --- a/test/mocks/LiFiMock.sol +++ b/test/mocks/LiFiMock.sol @@ -141,6 +141,12 @@ contract LiFiMock is Test { console.log("amount post-bridge", finalAmount); if (outputToken != NATIVE) { + console.log("AFTER BRIDGE ON DST: ---------"); + console.log("FORK: ", toForkId_); + console.log("outputToken : ", outputToken); + console.log("receiver_ : ", receiver_); + console.log("amount_ : ", MockERC20(outputToken).balanceOf(receiver_) + finalAmount); + deal(outputToken, receiver_, MockERC20(outputToken).balanceOf(receiver_) + finalAmount); } else { if (prevForkId_ != toForkId_) vm.deal(address(this), finalAmount); @@ -177,6 +183,11 @@ contract LiFiMock is Test { uint256 decimal1 = inputToken_ == NATIVE ? 18 : MockERC20(inputToken_).decimals(); uint256 decimal2 = outputToken_ == NATIVE ? 18 : MockERC20(outputToken_).decimals(); + console.log("inputToken", inputToken_); + console.log("outputToken", outputToken_); + console.log("decimal1", decimal1); + console.log("decimal2", decimal2); + console.log("amount pre-swap", amount_); /// @dev the results of this amount if there is a bridge are effectively ignored if (decimal1 > decimal2) { diff --git a/test/mocks/SocketMock.sol b/test/mocks/SocketMock.sol index 6f38110bc..f03177c2e 100644 --- a/test/mocks/SocketMock.sol +++ b/test/mocks/SocketMock.sol @@ -118,6 +118,12 @@ contract SocketMock is ISocketRegistry, Test { vm.selectFork(vars.toForkId); if (vars.outputToken != NATIVE) { + console.log("AFTER BRIDGE ON DST: ---------"); + console.log("FORK: ", vars.toForkId); + console.log("outputToken : ", vars.outputToken); + console.log("receiver_ : ", receiver_); // 0xf51d8717cf4fA841498495dba9Fe866c3b5C8818 + console.log("amount_ : ", MockERC20(vars.outputToken).balanceOf(receiver_) + vars.finalAmount); + deal(vars.outputToken, receiver_, MockERC20(vars.outputToken).balanceOf(receiver_) + vars.finalAmount); } else { vm.deal(receiver_, vars.finalAmount); diff --git a/test/utils/CommonProtocolActions.sol b/test/utils/CommonProtocolActions.sol index 36222cd6a..f2dcf16c1 100644 --- a/test/utils/CommonProtocolActions.sol +++ b/test/utils/CommonProtocolActions.sol @@ -296,9 +296,7 @@ abstract contract CommonProtocolActions is BaseSetup { address(0), /// @dev callTo (approveTo) sendingTokenDst_, - /// @dev in dst swap, assumes a swap between same token - FIXME receivingTokenDst_, - /// @dev in dst swap, assumes a swap between same token - FIXME amount_, /// @dev _buildLiqBridgeTxDataDstSwap() will only be called when DstSwap is true /// @dev and dstswap means cross-chain (last arg) diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index a7755481b..0927b8652 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -272,6 +272,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vars.toDst[0], vars.underlyingSrcToken[0], vars.underlyingDstToken[0], + address(0), vars.targetSuperformIds[0], finalAmount, vars.liqBridges[0], @@ -718,7 +719,6 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { /// @dev dst swap is performed to ensure tokens reach CoreStateRegistry on deposits if (action.multiVaults) { - vars.amounts = vars.targetAmounts[i]; _batchProcessDstSwap( vars.liqBridges, vars.CHAIN_0, @@ -899,6 +899,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { args.toDst[i], args.underlyingTokens[i], args.underlyingTokensDst[i], + address(0), args.superformIds[i], finalAmounts[i], args.liqBridges[i], diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 4a5ad5528..cb5a46d0b 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -460,6 +460,7 @@ abstract contract ProtocolActions is CommonProtocolActions { vars.toDst[0], vars.underlyingSrcToken[0], vars.underlyingDstToken[0], + action.dstSwap ? getContract(DST_CHAINS[i], UNDERLYING_TOKENS[0]) : address(0), vars.targetSuperformIds[0], finalAmount, vars.liqBridges[0], @@ -948,16 +949,17 @@ abstract contract ProtocolActions is CommonProtocolActions { _targetVaults(CHAIN_0, DST_CHAINS[i], actionIndex, i); vars.liqBridges = LIQ_BRIDGES[DST_CHAINS[i]][actionIndex]; + vars.amounts = AMOUNTS[DST_CHAINS[i]][actionIndex]; + + vars.underlyingWithBridgeSlippages = new uint256[](vars.amounts.length); /// @dev dst swap is performed to ensure tokens reach CoreStateRegistry on deposits if (action.multiVaults) { - vars.amounts = AMOUNTS[DST_CHAINS[i]][actionIndex]; - - vars.underlyingWith0Slippages = new uint256[](vars.amounts.length); for (uint256 j = 0; j < vars.amounts.length; ++j) { - vars.underlyingWith0Slippages[j] = _updateAmountWithPricedSwapsAndSlippage( + vars.underlyingWithBridgeSlippages[j] = _updateAmountWithPricedSwapsAndSlippage( AMOUNTS[DST_CHAINS[i]][actionIndex][j], - 0, - vars.underlyingDstToken[j], + vars.multiVaultsPayloadArg.slippage, + getContract(DST_CHAINS[i], UNDERLYING_TOKENS[j]), + /// @dev substituting this to become the interim token action.externalToken == 3 ? NATIVE_TOKEN : getContract(CHAIN_0, UNDERLYING_TOKENS[action.externalToken]), @@ -966,20 +968,20 @@ abstract contract ProtocolActions is CommonProtocolActions { DST_CHAINS[i] ); } + /// bridged amount with full slippage (inc. dstSwap slippage here) _batchProcessDstSwap( vars.liqBridges, CHAIN_0, aV[i].toChainId, vars.underlyingDstToken, - vars.multiVaultsPayloadArg.amounts, action.slippage, - vars.underlyingWith0Slippages + vars.underlyingWithBridgeSlippages ); } else { - vars.underlyingWith0Slippage = _updateAmountWithPricedSwapsAndSlippage( + vars.underlyingWithBridgeSlippage = _updateAmountWithPricedSwapsAndSlippage( AMOUNTS[DST_CHAINS[i]][actionIndex][0], - 0, - vars.underlyingDstToken[0], + vars.singleVaultsPayloadArg.slippage, + getContract(DST_CHAINS[i], UNDERLYING_TOKENS[0]), action.externalToken == 3 ? NATIVE_TOKEN : getContract(CHAIN_0, UNDERLYING_TOKENS[action.externalToken]), @@ -992,8 +994,8 @@ abstract contract ProtocolActions is CommonProtocolActions { CHAIN_0, aV[i].toChainId, vars.underlyingDstToken[0], - vars.singleVaultsPayloadArg.amount, - action.slippage + action.slippage, + vars.underlyingWithBridgeSlippage ); } } @@ -1001,9 +1003,13 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev this is the step where the amounts are updated taking into account the final /// slippage if (action.multiVaults) { - _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + _updateMultiVaultDepositPayload( + vars.multiVaultsPayloadArg, vars.underlyingWithBridgeSlippages + ); } else if (singleSuperformsData.length > 0) { - _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, vars.underlyingWithBridgeSlippage + ); } vm.recordLogs(); @@ -1018,9 +1024,13 @@ abstract contract ProtocolActions is CommonProtocolActions { } else if (action.testType == TestType.RevertProcessPayload) { /// @dev this logic is essentially repeated from above if (action.multiVaults) { - _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + _updateMultiVaultDepositPayload( + vars.multiVaultsPayloadArg, vars.underlyingWithBridgeSlippages + ); } else if (singleSuperformsData.length > 0) { - _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, vars.underlyingWithBridgeSlippage + ); } /// @dev process payload will revert in here success = _processPayload(PAYLOAD_ID[aV[i].toChainId], aV[i].toChainId, action.testType); @@ -1033,9 +1043,13 @@ abstract contract ProtocolActions is CommonProtocolActions { ) { /// @dev branch used just for reverts of updatePayload (process payload is not even called) if (action.multiVaults) { - success = _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + success = _updateMultiVaultDepositPayload( + vars.multiVaultsPayloadArg, vars.underlyingWithBridgeSlippages + ); } else { - success = _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + success = _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, vars.underlyingWithBridgeSlippage + ); } if (!success) { @@ -1303,6 +1317,7 @@ abstract contract ProtocolActions is CommonProtocolActions { int256 slippage; } + /// this function calculates the bridged amount with full slippage (but maybe could include only bridge slippage) function _updateAmountWithPricedSwapsAndSlippage( uint256 amount_, int256 slippage_, @@ -1355,11 +1370,15 @@ abstract contract ProtocolActions is CommonProtocolActions { } v.slippage = slippage_; - if (srcChainId_ == dstChainId_) v.slippage = 0; + if (srcChainId_ == dstChainId_) { + v.slippage = 0; + } + /// @dev add just bridge slippage here (pre-dst swap) + else { + v.slippage = (v.slippage * int256(100 - MULTI_TX_SLIPPAGE_SHARE)) / 100; + console.log("applied slippage in pre dst swap"); + } - /// @dev applying 100% x-chain slippage at once i.e. bridge + dstSwap slippage (as opposed to 2 steps in - /// LiFiMock) coz this code will only be executed once (as opposed to twice in LiFiMock, once for bridge - /// and other for dstSwap) amount_ = (amount_ * uint256(10_000 - v.slippage)) / 10_000; console.log("test amount pre-bridge, post-slippage", amount_); @@ -1518,8 +1537,13 @@ abstract contract ProtocolActions is CommonProtocolActions { if (len == 0) revert LEN_MISMATCH(); uint256[] memory finalAmounts = new uint256[](len); uint256[] memory maxSlippageTemp = new uint256[](len); + address uniqueInterimToken; for (uint256 i = 0; i < len; ++i) { finalAmounts[i] = args.amounts[i]; + if (i < 3 && args.dstSwap && args.action != Actions.Withdraw) { + /// @dev hack to support unique interim tokens -assuming dst swap scenario cases have less than 3 vaults + uniqueInterimToken = getContract(args.toChainId, UNDERLYING_TOKENS[i]); + } /// @dev FOR TESTING AND MAINNET:: in sameChain actions, slippage is encoded in the request with the amount /// (extracted from bridge api) @@ -1544,6 +1568,7 @@ abstract contract ProtocolActions is CommonProtocolActions { args.toDst[i], args.underlyingTokens[i], args.underlyingTokensDst[i], + uniqueInterimToken, args.superformIds[i], finalAmounts[i], args.liqBridges[i], @@ -1567,6 +1592,7 @@ abstract contract ProtocolActions is CommonProtocolActions { } liqRequests[i] = superformData.liqRequest; + if (args.dstSwap && args.action != Actions.Withdraw) liqRequests[i].interimToken = uniqueInterimToken; maxSlippageTemp[i] = args.maxSlippage; v.totalAmount += finalAmounts[i]; @@ -1615,8 +1641,13 @@ abstract contract ProtocolActions is CommonProtocolActions { uint256 decimal1; uint256 decimal2; uint256 decimal3; + uint256 decimal4; uint256 amountTemp; uint256 amount; + int256 USDPerUnderlyingOrInterimTokenDst; + int256 USDPerUnderlyingTokenDst; + int256 USDPerExternalToken; + int256 USDPerUnderlyingToken; LiqRequest liqReq; } @@ -1634,16 +1665,35 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev build permit2 calldata vm.selectFork(FORKS[args.toChainId]); - v.decimal2 = args.underlyingTokenDst != NATIVE_TOKEN ? MockERC20(args.underlyingTokenDst).decimals() : 18; - (, int256 USDPerUnderlyingTokenDst,,,) = - AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.underlyingTokenDst]).latestRoundData(); + + /// @dev decimals of interimToken in case it exists (dstSwaps), otherwise decimals of final token + /// (underlyingToken) + /// @dev hack for when args.dstSwap == true + if (args.uniqueInterimToken != address(0)) { + v.decimal2 = args.uniqueInterimToken != NATIVE_TOKEN ? MockERC20(args.uniqueInterimToken).decimals() : 18; + + (, v.USDPerUnderlyingOrInterimTokenDst,,,) = + AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.uniqueInterimToken]).latestRoundData(); + + v.decimal4 = args.underlyingTokenDst != NATIVE_TOKEN ? MockERC20(args.underlyingTokenDst).decimals() : 18; + + (, v.USDPerUnderlyingTokenDst,,,) = + AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.underlyingTokenDst]).latestRoundData(); + } else { + v.decimal2 = args.underlyingTokenDst != NATIVE_TOKEN ? MockERC20(args.underlyingTokenDst).decimals() : 18; + + (, v.USDPerUnderlyingOrInterimTokenDst,,,) = + AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.underlyingTokenDst]).latestRoundData(); + } vm.selectFork(FORKS[args.srcChainId]); + /// @dev decimals of externalToken v.decimal1 = args.externalToken != NATIVE_TOKEN ? MockERC20(args.externalToken).decimals() : 18; + /// @dev decimals of underlyingToken on source v.decimal3 = args.underlyingToken != NATIVE_TOKEN ? MockERC20(args.underlyingToken).decimals() : 18; - (, int256 USDPerExternalToken,,,) = + (, v.USDPerExternalToken,,,) = AggregatorV3Interface(tokenPriceFeeds[args.srcChainId][args.externalToken]).latestRoundData(); - (, int256 USDPerUnderlyingToken,,,) = + (, v.USDPerUnderlyingToken,,,) = AggregatorV3Interface(tokenPriceFeeds[args.srcChainId][args.underlyingToken]).latestRoundData(); /// @dev this is to attach v.amount pre dst slippage with the correct decimals to avoid intermediary truncation @@ -1662,7 +1712,7 @@ abstract contract ProtocolActions is CommonProtocolActions { args.liqBridge, args.externalToken, args.underlyingToken, - args.underlyingTokenDst, + args.uniqueInterimToken != address(0) ? args.uniqueInterimToken : args.underlyingTokenDst, v.from, args.srcChainId, args.toChainId, @@ -1674,9 +1724,9 @@ abstract contract ProtocolActions is CommonProtocolActions { //v.amount, false, args.slippage, - uint256(USDPerExternalToken), - uint256(USDPerUnderlyingTokenDst), - uint256(USDPerUnderlyingToken) + uint256(v.USDPerExternalToken), + uint256(v.USDPerUnderlyingOrInterimTokenDst), + uint256(v.USDPerUnderlyingToken) ); v.txData = _buildLiqBridgeTxData(liqBridgeTxDataArgs, args.srcChainId == args.toChainId); @@ -1696,12 +1746,10 @@ abstract contract ProtocolActions is CommonProtocolActions { } /// @dev the actual liq request struct inscription - /// @notice adding dummy liqRequestToken as interim token if there is dstSwap because we are not - /// @notice testing failed deposits here v.liqReq = LiqRequest( v.txData, liqRequestToken, - args.dstSwap ? args.underlyingTokenDst : address(0), + args.dstSwap ? args.uniqueInterimToken : address(0), args.liqBridge, args.toChainId, liqRequestToken == NATIVE_TOKEN ? args.amount : 0 @@ -1725,6 +1773,11 @@ abstract contract ProtocolActions is CommonProtocolActions { } } + /// @dev the next steps are to create the user intent amount that goes in the state request. + /// @dev the values here have to be calculated in terms of decimal differences and slippage in the different + /// stages + /// @dev this calculation would be done automatically by Superform Protocol API on mainnet + /// @dev for e.g. externalToken = DAI, underlyingTokenDst = USDC, daiAmount = 100 /// => usdcAmount = ((USDPerDai / 10e18) / (USDPerUsdc / 10e6)) * daiAmount console.log("test amount pre-swap", args.amount); @@ -1739,11 +1792,11 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev decimal1 = decimals of args.externalToken (src chain), decimal2 = decimals of args.underlyingToken /// (src chain) if (decimal1 > decimal2) { - args.amount = (args.amount * uint256(USDPerExternalToken)) - / (uint256(USDPerUnderlyingToken) * 10 ** (decimal1 - decimal2)); + args.amount = (args.amount * uint256(v.USDPerExternalToken)) + / (uint256(v.USDPerUnderlyingToken) * 10 ** (decimal1 - decimal2)); } else { - args.amount = ((args.amount * uint256(USDPerExternalToken)) * 10 ** (decimal2 - decimal1)) - / uint256(USDPerUnderlyingToken); + args.amount = ((args.amount * uint256(v.USDPerExternalToken)) * 10 ** (decimal2 - decimal1)) + / uint256(v.USDPerUnderlyingToken); } console.log("test amount post-swap", args.amount); } @@ -1752,23 +1805,38 @@ abstract contract ProtocolActions is CommonProtocolActions { /// and _updateMultiVaultDepositPayload() int256 slippage = args.slippage; if (args.srcChainId == args.toChainId) slippage = 0; - else if (args.dstSwap) slippage = (slippage * int256(100 - MULTI_TX_SLIPPAGE_SHARE)) / 100; + /// @dev REMOVE THIS LINE IF THEORY IS CORRECT (this is full amount) + // else if (args.dstSwap) slippage = (slippage * int256(100 - MULTI_TX_SLIPPAGE_SHARE)) / 100; args.amount = (args.amount * uint256(10_000 - slippage)) / 10_000; console.log("test amount pre-bridge, post-slippage", v.amount); /// @dev if args.externalToken == args.underlyingToken, USDPerExternalToken == USDPerUnderlyingToken /// @dev v.decimal3 = decimals of args.underlyingToken (args.externalToken too if above holds true) (src chain), - /// v.decimal2 = decimals of args.underlyingTokenDst (dst chain) + /// v.decimal2 = decimals of args.underlyingTokenDst (dst chain) - interimToken in case of dstSwap if (v.decimal3 > v.decimal2) { - v.amount = (args.amount * uint256(USDPerUnderlyingToken)) - / (uint256(USDPerUnderlyingTokenDst) * 10 ** (v.decimal3 - v.decimal2)); + v.amount = (args.amount * uint256(v.USDPerUnderlyingToken)) + / (uint256(v.USDPerUnderlyingOrInterimTokenDst) * 10 ** (v.decimal3 - v.decimal2)); } else { - v.amount = (args.amount * uint256(USDPerUnderlyingToken) * 10 ** (v.decimal2 - v.decimal3)) - / uint256(USDPerUnderlyingTokenDst); + v.amount = (args.amount * uint256(v.USDPerUnderlyingToken) * 10 ** (v.decimal2 - v.decimal3)) + / uint256(v.USDPerUnderlyingOrInterimTokenDst); } + console.log("test amount post-bridge", v.amount); + /// @dev extra step to convert interim token on dst to underlying token on dst (if there is a dst Swap) + if (args.uniqueInterimToken != address(0)) { + if (v.decimal2 > v.decimal4) { + v.amount = (v.amount * uint256(v.USDPerUnderlyingOrInterimTokenDst)) + / (uint256(v.USDPerUnderlyingTokenDst) * 10 ** (v.decimal2 - v.decimal4)); + } else { + v.amount = (v.amount * uint256(v.USDPerUnderlyingOrInterimTokenDst) * 10 ** (v.decimal4 - v.decimal2)) + / uint256(v.USDPerUnderlyingTokenDst); + } + } + + console.log("test amount post-dst swap --", v.amount); + vm.selectFork(v.initialFork); /// @dev extraData is unused here so false is encoded (it is currently used to send in the partialWithdraw @@ -2081,7 +2149,13 @@ abstract contract ProtocolActions is CommonProtocolActions { } } - function _updateMultiVaultDepositPayload(updateMultiVaultDepositPayloadArgs memory args) internal returns (bool) { + function _updateMultiVaultDepositPayload( + updateMultiVaultDepositPayloadArgs memory args, + uint256[] memory finalAmountsThatReachedCSR + ) + internal + returns (bool) + { uint256 initialFork = vm.activeFork(); vm.selectFork(FORKS[args.targetChainId]); @@ -2093,12 +2167,14 @@ abstract contract ProtocolActions is CommonProtocolActions { for (uint256 i = 0; i < len; ++i) { finalAmounts[i] = args.amounts[i]; if (args.slippage > 0) { - /// @dev bridge slippage is already applied in _buildSingleVaultDepositCallData() - // finalAmounts[i] = (finalAmounts[i] * uint256(10_000 - args.slippage)) / 10_000; - + /// @dev finalAmounts[i] has full slippage applied (final user expectedAmount) + uint256 amountPostDstSwap; if (args.isdstSwap) { dstSwapSlippage = (args.slippage * int256(MULTI_TX_SLIPPAGE_SHARE)) / 100; - finalAmounts[i] = (finalAmounts[i] * uint256(10_000 - dstSwapSlippage)) / 10_000; + amountPostDstSwap = (finalAmountsThatReachedCSR[i] * uint256(10_000 - dstSwapSlippage)) / 10_000; + if (amountPostDstSwap < finalAmounts[i]) { + finalAmounts[i] = amountPostDstSwap; + } } } } @@ -2139,7 +2215,10 @@ abstract contract ProtocolActions is CommonProtocolActions { return true; } - function _updateSingleVaultDepositPayload(updateSingleVaultDepositPayloadArgs memory args) + function _updateSingleVaultDepositPayload( + updateSingleVaultDepositPayloadArgs memory args, + uint256 finalAmountsThatReachedCSR + ) internal returns (bool) { @@ -2152,11 +2231,14 @@ abstract contract ProtocolActions is CommonProtocolActions { int256 dstSwapSlippage; - // finalAmount = (finalAmount * uint256(10_000 - args.slippage)) / 10_000; - if (args.isdstSwap) { dstSwapSlippage = (args.slippage * int256(MULTI_TX_SLIPPAGE_SHARE)) / 100; - finalAmount = (finalAmount * uint256(10_000 - dstSwapSlippage)) / 10_000; + uint256 amountPostDstSwap; + + amountPostDstSwap = (finalAmountsThatReachedCSR * uint256(10_000 - dstSwapSlippage)) / 10_000; + if (amountPostDstSwap < finalAmount) { + finalAmount = amountPostDstSwap; + } } /// @dev if test type is RevertProcessPayload, revert is further down the call chain @@ -2319,8 +2401,8 @@ abstract contract ProtocolActions is CommonProtocolActions { uint64, /*srcChainId_*/ uint64 targetChainId_, address underlyingTokenDst_, - uint256 amount_, - int256 slippage_ + int256 slippage_, + uint256 underlyingWithBridgeSlippage_ ) internal { @@ -2335,11 +2417,11 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev liqData is rebuilt here to perform to send the tokens from dstSwapProcessor to CoreStateRegistry bytes memory txData = _buildLiqBridgeTxDataDstSwap( liqBridgeKind_, - underlyingTokenDst_, + getContract(targetChainId_, UNDERLYING_TOKENS[0]), underlyingTokenDst_, getContract(targetChainId_, "DstSwapper"), targetChainId_, - amount_, + underlyingWithBridgeSlippage_, slippage_ ); @@ -2353,9 +2435,8 @@ abstract contract ProtocolActions is CommonProtocolActions { uint64, /*srcChainId_*/ uint64 targetChainId_, address[] memory underlyingTokensDst_, - uint256[] memory amounts_, int256 slippage_, - uint256[] memory /*underlyingWith0Slippages*/ + uint256[] memory underlyingWithBridgeSlippages_ ) internal { @@ -2370,22 +2451,24 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev liqData is rebuilt here to perform to send the tokens from dstSwapProcessor to CoreStateRegistry for (uint256 i = 0; i < underlyingTokensDst_.length; ++i) { + /// @dev hack: sending token corresponds to what was set in the buildMultiVault step. Only works if vaults + /// <= 3 txDatas[i] = _buildLiqBridgeTxDataDstSwap( liqBridgeKinds_[i], - underlyingTokensDst_[i], + getContract(targetChainId_, UNDERLYING_TOKENS[i]), underlyingTokensDst_[i], getContract(targetChainId_, "DstSwapper"), targetChainId_, - amounts_[i], + underlyingWithBridgeSlippages_[i], slippage_ ); } vm.prank(deployer); - uint256[] memory indices = new uint256[](amounts_.length); + uint256[] memory indices = new uint256[](underlyingWithBridgeSlippages_.length); - for (uint256 i; i < amounts_.length; ++i) { + for (uint256 i; i < underlyingWithBridgeSlippages_.length; ++i) { indices[i] = i; } diff --git a/test/utils/TestTypes.sol b/test/utils/TestTypes.sol index c98186418..8b97c6bca 100644 --- a/test/utils/TestTypes.sol +++ b/test/utils/TestTypes.sol @@ -70,8 +70,10 @@ struct StagesLocalVars { uint8[] AMBs; uint64 CHAIN_0; uint64[] DST_CHAINS; - uint256 underlyingWith0Slippage; - uint256[] underlyingWith0Slippages; + uint256 underlyingWithBridgeSlippage; + uint256[] underlyingWithBridgeSlippages; + uint256[] amountsBeforeCSR; + uint256[] finalAmountsThatReachedCSR; } struct MessagingAssertVars { @@ -187,6 +189,7 @@ struct SingleVaultCallDataArgs { address toDst; address underlyingToken; address underlyingTokenDst; + address uniqueInterimToken; uint256 superformId; uint256 amount; uint8 liqBridge; From 1c4922341aac963d98ab02a2bb94f41c15d07fbb Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:52:09 +0000 Subject: [PATCH 117/210] fix: optimization --- src/crosschain-liquidity/LiquidityHandler.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index 443cd70cf..2514a3177 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -59,7 +59,8 @@ abstract contract LiquidityHandler { if (!success) revert Error.FAILED_TO_EXECUTE_TXDATA(token_); if (token_ != NATIVE) { - IERC20(token_).forceApprove(bridge_, 0); + IERC20(token_) token; + if (token.allowance(bridge_) > 0) token.forceApprove(bridge_, 0); } } } From ac5a84f8fe77af38dd0a1eb02053b554affd046f Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:55:48 +0000 Subject: [PATCH 118/210] fix: all tests --- src/crosschain-liquidity/DstSwapper.sol | 13 ------------- test/mocks/LiFiMock.sol | 6 ------ test/mocks/SocketMock.sol | 6 ------ test/unit/superform-router/SuperformRouter.t.sol | 14 ++++++++++++-- 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index d06d8b75e..f04f04e96 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -14,7 +14,6 @@ import { IERC4626Form } from "../forms/interfaces/IERC4626Form.sol"; import { Error } from "../libraries/Error.sol"; import { DataLib } from "../libraries/DataLib.sol"; import "../types/DataTypes.sol"; -import "forge-std/console.sol"; /// @title DstSwapper /// @author Zeropoint Labs. @@ -328,8 +327,6 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { revert Error.INSUFFICIENT_BALANCE(); } } else { - console.log("Balance of DST Swapper:", IERC20(userSuppliedInterimToken_).balanceOf(address(this))); - console.log("Amount to swap:", v.amount); if (IERC20(userSuppliedInterimToken_).balanceOf(address(this)) < v.amount) { revert Error.INSUFFICIENT_BALANCE(); } @@ -356,9 +353,6 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { (v.underlying, v.expAmount, v.maxSlippage) = _getFormUnderlyingFrom(coreStateRegistry_, payloadId_, index_); v.balanceBefore = IERC20(v.underlying).balanceOf(v.finalDst); - console.log("----"); - console.log("balanceBefore: %s", v.balanceBefore); - console.log("amount to swap", v.amount); _dispatchTokens( superRegistry.getBridgeAddress(bridgeId_), txData_, @@ -374,13 +368,6 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { } v.balanceDiff = v.balanceAfter - v.balanceBefore; - console.log("Post Swap"); - - console.log("balanceAfter: %s", v.balanceAfter); - console.log("balanceDiff: %s", v.balanceDiff); - console.log("--2nd side eq", (v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) / ENTIRE_SLIPPAGE); - console.log("expAmount (inscribed by user): %s", v.expAmount); - console.log("maxSlippage: %s", v.maxSlippage); /// @dev if actual underlying is less than expAmount adjusted with maxSlippage, invariant breaks if (v.balanceDiff < ((v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) / ENTIRE_SLIPPAGE)) { diff --git a/test/mocks/LiFiMock.sol b/test/mocks/LiFiMock.sol index e3a379c35..eb4ab3728 100644 --- a/test/mocks/LiFiMock.sol +++ b/test/mocks/LiFiMock.sol @@ -141,12 +141,6 @@ contract LiFiMock is Test { console.log("amount post-bridge", finalAmount); if (outputToken != NATIVE) { - console.log("AFTER BRIDGE ON DST: ---------"); - console.log("FORK: ", toForkId_); - console.log("outputToken : ", outputToken); - console.log("receiver_ : ", receiver_); - console.log("amount_ : ", MockERC20(outputToken).balanceOf(receiver_) + finalAmount); - deal(outputToken, receiver_, MockERC20(outputToken).balanceOf(receiver_) + finalAmount); } else { if (prevForkId_ != toForkId_) vm.deal(address(this), finalAmount); diff --git a/test/mocks/SocketMock.sol b/test/mocks/SocketMock.sol index f03177c2e..6f38110bc 100644 --- a/test/mocks/SocketMock.sol +++ b/test/mocks/SocketMock.sol @@ -118,12 +118,6 @@ contract SocketMock is ISocketRegistry, Test { vm.selectFork(vars.toForkId); if (vars.outputToken != NATIVE) { - console.log("AFTER BRIDGE ON DST: ---------"); - console.log("FORK: ", vars.toForkId); - console.log("outputToken : ", vars.outputToken); - console.log("receiver_ : ", receiver_); // 0xf51d8717cf4fA841498495dba9Fe866c3b5C8818 - console.log("amount_ : ", MockERC20(vars.outputToken).balanceOf(receiver_) + vars.finalAmount); - deal(vars.outputToken, receiver_, MockERC20(vars.outputToken).balanceOf(receiver_) + vars.finalAmount); } else { vm.deal(receiver_, vars.finalAmount); diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index a7c892628..bea060b9c 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -1588,7 +1588,12 @@ contract SuperformRouterTest is ProtocolActions { v.liqReqs = new LiqRequest[](2); v.liqReqs[0] = LiqRequest( - _buildLiqBridgeTxData(v.liqBridgeTxDataArgs, false), getContract(ETH, "DAI"), address(0), 1, ARBI, 0 + _buildLiqBridgeTxData(v.liqBridgeTxDataArgs, false), + getContract(ETH, "DAI"), + getContract(ARBI, "DAI"), + 1, + ARBI, + 0 ); v.liqBridgeTxDataArgs = LiqBridgeTxDataArgs( @@ -1614,7 +1619,12 @@ contract SuperformRouterTest is ProtocolActions { ); v.liqReqs[1] = LiqRequest( - _buildLiqBridgeTxData(v.liqBridgeTxDataArgs, false), getContract(ETH, "WETH"), address(0), 1, ARBI, 0 + _buildLiqBridgeTxData(v.liqBridgeTxDataArgs, false), + getContract(ETH, "WETH"), + getContract(ARBI, "DAI"), + 1, + ARBI, + 0 ); MultiVaultSFData memory data = MultiVaultSFData( From 0a29484001bf898506c5ad0bda1e633ea90d2f50 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:59:45 +0000 Subject: [PATCH 119/210] fix: allowance check --- src/crosschain-liquidity/LiquidityHandler.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index 2514a3177..c6478b29e 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -59,8 +59,8 @@ abstract contract LiquidityHandler { if (!success) revert Error.FAILED_TO_EXECUTE_TXDATA(token_); if (token_ != NATIVE) { - IERC20(token_) token; - if (token.allowance(bridge_) > 0) token.forceApprove(bridge_, 0); + IERC20 token = IERC20(token_); + if (token.allowance(address(this), bridge_) > 0) token.forceApprove(bridge_, 0); } } } From a29785d11e9553588d0d6388ce62463272c0056d Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Thu, 21 Dec 2023 19:58:14 +0000 Subject: [PATCH 120/210] fix: tests --- src/forms/ERC4626FormImplementation.sol | 19 +++++++++++-------- src/forms/ERC4626TimelockForm.sol | 9 ++++++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 1a997bfc2..53338c4ec 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -238,7 +238,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev notice that vars.assetDifference is deposited regardless if txData exists or not /// @dev this presumes no dust is left in the superform IERC20(vars.asset).safeIncreaseAllowance(vault, vars.assetDifference); - + /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); @@ -292,12 +292,14 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.receiver = vars.len1 == 0 ? singleVaultData_.receiverAddress : address(this); IERC4626 v = IERC4626(vault); - vars.asset = address(asset); + vars.asset = asset; + + IERC20 assetERC = IERC20(vars.asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = v.balanceOf(vars.receiver); - assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = v.balanceOf(vars.receiver); + uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); // 1840510681728394401 + assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); // 9843788488587 + uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); // 0 if (assetsBalanceAfter - assetsBalanceBefore != assets) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -364,12 +366,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.receiver = len == 0 ? singleVaultData_.receiverAddress : address(this); IERC4626 v = IERC4626(vault); - vars.asset = address(asset); + vars.asset = asset; + IERC20 assetERC = IERC20(vars.asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = v.balanceOf(vars.receiver); + uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = v.balanceOf(vars.receiver); + uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); if (assetsBalanceAfter - assetsBalanceBefore != assets) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 1bdeee872..0bd3ca4d1 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -93,8 +93,15 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { vars.receiver = vars.len1 == 0 ? p_.data.receiverAddress : address(this); /// @dev redeem from vault - vars.asset = address(asset); + vars.asset = asset; + IERC20 assetERC = IERC20(vars.asset); + + uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); assets = v.redeem(p_.data.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); + if (assetsBalanceAfter - assetsBalanceBefore != assets) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); /// @dev validate and dispatches the tokens From 3e9672e9c7f3c0815d7a51ea3a6f813540e43d47 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:09:48 -0500 Subject: [PATCH 121/210] chore: consistent logic --- src/forms/ERC4626FormImplementation.sol | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 53338c4ec..19d4898f3 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -292,14 +292,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.receiver = vars.len1 == 0 ? singleVaultData_.receiverAddress : address(this); IERC4626 v = IERC4626(vault); - vars.asset = asset; - - IERC20 assetERC = IERC20(vars.asset); + IERC20 a = IERC20(asset); + vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); // 1840510681728394401 - assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); // 9843788488587 - uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); // 0 + uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); + assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); if (assetsBalanceAfter - assetsBalanceBefore != assets) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -366,13 +365,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.receiver = len == 0 ? singleVaultData_.receiverAddress : address(this); IERC4626 v = IERC4626(vault); - vars.asset = asset; - IERC20 assetERC = IERC20(vars.asset); + IERC20 a = IERC20(asset); + vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); + uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); + uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); if (assetsBalanceAfter - assetsBalanceBefore != assets) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } From 7dfeacaa142d6c5ccca8772aa2d6867421c93d03 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 22 Dec 2023 13:47:38 +0530 Subject: [PATCH 122/210] feat: fix onlyMinter and _validateStateSyncer validations --- script/Abstract.Deploy.Single.s.sol | 7 +++--- src/SuperPositions.sol | 14 +++++++---- src/SuperformFactory.sol | 17 +++++++++++-- src/interfaces/ISuperformFactory.sol | 20 ++++++++++++++-- .../TwoStepsFormStateRegistry.t.sol | 12 ++++++---- .../super-positions/super-positions.t.sol | 6 ++--- .../superform-factory.addImplementation.sol | 19 ++++++++------- ...erform-factory.changeFormPauseStatus.t.sol | 8 +++---- .../superform-factory.createSuperforms.t.sol | 8 +++---- .../superform-form.ERC4626Form.t.sol | 24 +++++++++---------- test/utils/BaseSetup.sol | 8 ++++--- test/utils/ProtocolActions.sol | 1 - 12 files changed, 91 insertions(+), 53 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index e4f664853..6a259a899 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -486,11 +486,12 @@ abstract contract AbstractDeploySingle is Script { contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; /// @dev 9 - Add newly deployed form implementations to Factory, formImplementationId 1 - ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0]); + ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0], 0); - ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1]); + /// passing 2 cuz timelock state registry id is 2 + ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1], 2); - ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2]); + ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 0); /// @dev 10 - Deploy SuperformRouter vars.superformRouter = address(new SuperformRouter{ salt: salt }(vars.superRegistry)); diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index f65d24c9f..de2735f27 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -69,12 +69,14 @@ contract SuperPositions is ISuperPositions, ERC1155A { modifier onlyMinter(uint256 superformId) { address router = superRegistry.getAddress(keccak256("SUPERFORM_ROUTER")); - /// if msg.sender isn't superformRouter then it must be state registry for that superform + /// if msg.sender isn't superformRouter then it must be state registry of that form if (msg.sender != router) { - (, uint32 formImplementationId,) = DataLib.getSuperform(superformId); uint8 registryId = superRegistry.getStateRegistryId(msg.sender); - if (uint32(registryId) != formImplementationId) { + (address superform,,) = DataLib.getSuperform(superformId); + uint8 formRegistryId = IBaseForm(superform).getStateRegistryId(); + + if (registryId != formRegistryId) { revert Error.NOT_MINTER(); } } @@ -322,7 +324,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { } } - function _isValidStateSyncer(uint8 registryId_, uint256 superformId_) internal pure { + function _isValidStateSyncer(uint8 registryId_, uint256 superformId_) internal view { /// @dev Directly check if the registryId is 0 or doesn't match the allowed cases. if (registryId_ == 0) { revert Error.NOT_MINTER_STATE_REGISTRY_ROLE(); @@ -335,8 +337,10 @@ contract SuperPositions is ISuperPositions, ERC1155A { } (, uint32 formImplementationId,) = DataLib.getSuperform(superformId_); + uint8 formRegistryId = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))) + .getFormStateRegistryId(formImplementationId); - if (uint32(registryId_) != formImplementationId) { + if (registryId_ != formRegistryId) { revert Error.NOT_MINTER_STATE_REGISTRY_ROLE(); } } diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 37a6fe9b5..26a691850 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -48,6 +48,8 @@ contract SuperformFactory is ISuperformFactory { /// @dev each form implementation address can correspond only to a single formImplementationId mapping(address formImplementationAddress => uint32 formImplementationId) public formImplementationIds; + /// @dev this mapping is used only for crosschain cases and should be same across all the chains + mapping(uint32 formImplementationId => uint8 formRegistryId) public formStateRegistryId; mapping(uint32 formImplementationId => PauseStatus) public formImplementationPaused; @@ -117,6 +119,11 @@ contract SuperformFactory is ISuperformFactory { return formImplementation[formImplementationId_]; } + /// @inheritdoc ISuperformFactory + function getFormStateRegistryId(uint32 formImplementationId_) external view override returns (uint8) { + return formStateRegistryId[formImplementationId_]; + } + /// @inheritdoc ISuperformFactory function isFormImplementationPaused(uint32 formImplementationId_) external view override returns (bool) { return formImplementationPaused[formImplementationId_] == PauseStatus.PAUSED; @@ -155,7 +162,8 @@ contract SuperformFactory is ISuperformFactory { /// @inheritdoc ISuperformFactory function addFormImplementation( address formImplementation_, - uint32 formImplementationId_ + uint32 formImplementationId_, + uint8 formStateRegistryId_ ) public override @@ -178,9 +186,14 @@ contract SuperformFactory is ISuperformFactory { formImplementation[formImplementationId_] = formImplementation_; formImplementationIds[formImplementation_] = formImplementationId_; + /// @dev formStateRegistryId can also be zero if the form requires no additional state registry + if (formStateRegistryId_ != 0) { + formStateRegistryId[formImplementationId_] = formStateRegistryId_; + } + formImplementations.push(formImplementation_); - emit FormImplementationAdded(formImplementation_, formImplementationId_); + emit FormImplementationAdded(formImplementation_, formImplementationId_, formStateRegistryId_); } /// @inheritdoc ISuperformFactory diff --git a/src/interfaces/ISuperformFactory.sol b/src/interfaces/ISuperformFactory.sol index ad4a2237f..26fc5632e 100644 --- a/src/interfaces/ISuperformFactory.sol +++ b/src/interfaces/ISuperformFactory.sol @@ -21,7 +21,10 @@ interface ISuperformFactory { /// @dev emitted when a new formImplementation is entered into the factory /// @param formImplementation is the address of the new form implementation /// @param formImplementationId is the id of the formImplementation - event FormImplementationAdded(address indexed formImplementation, uint256 indexed formImplementationId); + /// @param formStateRegistryId is any additional state registry id of the formImplementation + event FormImplementationAdded( + address indexed formImplementation, uint256 indexed formImplementationId, uint8 indexed formStateRegistryId + ); /// @dev emitted when a new Superform is created /// @param formImplementationId is the id of the form implementation @@ -58,6 +61,11 @@ interface ISuperformFactory { /// @return formImplementation_ is the address of the form implementation function getFormImplementation(uint32 formImplementationId_) external view returns (address formImplementation_); + /// @dev returns the form state registry id of a form implementation + /// @param formImplementationId_ is the id of the form implementation + /// @return stateRegistryId_ is the additional state registry id of the form + function getFormStateRegistryId(uint32 formImplementationId_) external view returns (uint8 stateRegistryId_); + /// @dev returns the paused status of form implementation /// @param formImplementationId_ is the id of the form implementation /// @return paused_ is the current paused status of the form formImplementationId_ @@ -94,7 +102,15 @@ interface ISuperformFactory { /// @dev allows an admin to add a Form implementation to the factory /// @param formImplementation_ is the address of a form implementation /// @param formImplementationId_ is the id of the form implementation (generated off-chain and equal in all chains) - function addFormImplementation(address formImplementation_, uint32 formImplementationId_) external; + /// @param formStateRegistryId_ is the id of any additional state registry for that form + /// @dev formStateRegistryId_ 1 is default for all form implementations, pass in formStateRegistryId_ only if an + /// additional state registry is required + function addFormImplementation( + address formImplementation_, + uint32 formImplementationId_, + uint8 formStateRegistryId_ + ) + external; /// @dev To add new vaults to Form implementations, fusing them together into Superforms /// @param formImplementationId_ is the form implementation we want to attach the vault to diff --git a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol index 411d95c1c..fab3bdf62 100644 --- a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol @@ -17,7 +17,7 @@ contract TimelockStateRegistryTest is ProtocolActions { function test_updateTxDataBranch() external { /// @dev mocks receive payload as a form vm.selectFork(FORKS[ETH]); - (address superform, uint256 superformId) = _legacySuperformPackWithShift(); + (address superform, uint256 superformId) = _legacySuperformPackWithShift(ETH); LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( 1, @@ -137,7 +137,7 @@ contract TimelockStateRegistryTest is ProtocolActions { function test_processPayloadMintPositionBranch() external { /// @dev mocks receive payload as a form vm.selectFork(FORKS[AVAX]); - (, uint256 superformId) = _legacySuperformPackWithShift(); + (, uint256 superformId) = _legacySuperformPackWithShift(AVAX); bytes memory _message = abi.encode( AMBMessage( @@ -172,9 +172,11 @@ contract TimelockStateRegistryTest is ProtocolActions { timelockStateRegistry.dispatchPayload(address(420), ambIds, uint64(1), bytes(""), bytes("")); } - function _legacySuperformPackWithShift() internal view returns (address superform, uint256 superformId_) { - uint64 chainId_ = ETH; - + function _legacySuperformPackWithShift(uint64 chainId_) + internal + view + returns (address superform, uint256 superformId_) + { superform = getContract( chainId_, string.concat("DAI", "ERC4626TimelockMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[1])) diff --git a/test/unit/super-positions/super-positions.t.sol b/test/unit/super-positions/super-positions.t.sol index 38c2f725d..0f2588dd4 100644 --- a/test/unit/super-positions/super-positions.t.sol +++ b/test/unit/super-positions/super-positions.t.sol @@ -30,7 +30,7 @@ contract SuperPositionsTest is BaseSetup { vault = getContract(ETH, VAULT_NAMES[0][0]); vm.prank(deployer); SuperformFactory(getContract(ETH, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); } @@ -101,10 +101,10 @@ contract SuperPositionsTest is BaseSetup { function test_revert_stateSync_NotMinterStateRegistry_InvalidRegistryId() public { uint256 txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0), ETH); address superform = getContract( - ARBI, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) ); - uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ARBI); + uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, superformId, 100); AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); diff --git a/test/unit/superform-factory/superform-factory.addImplementation.sol b/test/unit/superform-factory/superform-factory.addImplementation.sol index 99538fb31..b4513c935 100644 --- a/test/unit/superform-factory/superform-factory.addImplementation.sol +++ b/test/unit/superform-factory/superform-factory.addImplementation.sol @@ -12,7 +12,9 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { /// @param formImplementation is the address of the new form implementation /// @param formImplementationId is the id of the formImplementation - event FormImplementationAdded(address indexed formImplementation, uint256 indexed formImplementationId); + event FormImplementationAdded( + address indexed formImplementation, uint256 indexed formImplementationId, uint8 indexed formStateRegistryId + ); function setUp() public override { super.setUp(); @@ -28,10 +30,9 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { vm.startPrank(deployer); /// @dev Event With Implementation vm.expectEmit(true, true, true, true); - emit FormImplementationAdded(formImplementation, formImplementationId); - + emit FormImplementationAdded(formImplementation, formImplementationId, 0); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); } @@ -46,18 +47,18 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { vm.startPrank(deployer); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId + formImplementation1, formImplementationId, 0 ); address imp = SuperformFactory(getContract(chainId, "SuperformFactory")).getFormImplementation(formImplementationId); assertEq(imp, formImplementation1); vm.expectRevert(Error.FORM_IMPLEMENTATION_ALREADY_EXISTS.selector); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation2, formImplementationId + formImplementation2, formImplementationId, 0 ); vm.expectRevert(Error.FORM_IMPLEMENTATION_ID_ALREADY_EXISTS.selector); - SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(formImplementation1, 555); + SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(formImplementation1, 555, 0); } /// @dev Testing adding form with form address 0 @@ -70,7 +71,7 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { vm.prank(deployer); vm.expectRevert(Error.ZERO_ADDRESS.selector); - SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(form, formId); + SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(form, formId, 2); } /// @dev Testing adding becon with wrong form @@ -83,6 +84,6 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { vm.prank(deployer); vm.expectRevert(Error.ERC165_UNSUPPORTED.selector); - SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(form, formId); + SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(form, formId, 2); } } diff --git a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol index d29fe6566..83a3620be 100644 --- a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol +++ b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol @@ -28,7 +28,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId + formImplementation1, formImplementationId, 0 ); SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus( @@ -55,7 +55,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId + formImplementation1, formImplementationId, 0 ); SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus( @@ -83,7 +83,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { /// @dev Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId + formImplementation1, formImplementationId, 0 ); /// @dev Invalid Form Implementation For Pausing @@ -106,7 +106,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId + formImplementation1, formImplementationId, 0 ); vm.expectRevert(Error.MSG_VALUE_NOT_ZERO.selector); diff --git a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol index 17e17e56f..3ae5c0d72 100644 --- a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol +++ b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol @@ -91,7 +91,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); uint256 totalSuperformsBefore = SuperformFactory(getContract(chainId, "SuperformFactory")).getSuperformCount(); @@ -124,7 +124,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { /// Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId + formImplementation1, formImplementationId, 0 ); /// @dev Creating superform using form @@ -145,7 +145,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using form @@ -170,7 +170,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested vm.expectRevert(Error.FORM_INTERFACE_UNSUPPORTED.selector); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); } diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index 7d158f6ea..7e88ec81a 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -43,7 +43,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -74,7 +74,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -104,7 +104,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -135,7 +135,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -165,7 +165,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -195,7 +195,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -225,7 +225,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -255,7 +255,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -285,7 +285,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -315,7 +315,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -345,7 +345,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId + formImplementation, formImplementationId, 0 ); /// @dev Creating superform using formImplementationId and vault @@ -661,7 +661,7 @@ contract SuperformERC4626FormTest is ProtocolActions { VaultMock vault = new VaultMock(asset, "Mock Vault", "Mock"); /// @dev Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested - superformFactory.addFormImplementation(formImplementation, formImplementationId); + superformFactory.addFormImplementation(formImplementation, formImplementationId, 0); /// @dev should revert as superRegistry coming from SuperformFactory does not /// match the one set in the ERC4626Form diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 9226cd475..a64274583 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -631,11 +631,13 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; /// @dev 11 - Add newly deployed form implementations to Factory - ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0]); + ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0], 0); - ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1]); + ISuperformFactory(vars.factory).addFormImplementation( + vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1], 2 + ); - ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2]); + ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 0); /// @dev 12 - Deploy SuperformRouter vars.superformRouter = address(new SuperformRouter{ salt: salt }(vars.superRegistry)); diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 4a5ad5528..101123de9 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -2278,7 +2278,6 @@ abstract contract ProtocolActions is CommonProtocolActions { returns (bool) { uint256 initialFork = vm.activeFork(); - vm.selectFork(FORKS[targetChainId_]); /// @dev tries to increase quorum and check if quorum validations are good From 4f6ac087408469a80a8477e6f7777f9a06c205f8 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 22 Dec 2023 14:58:15 +0530 Subject: [PATCH 123/210] chore: refund excess in broadcast payload --- src/crosschain-data/BroadcastRegistry.sol | 14 ++++- .../crosschain-data/BroadcastRegistry.t.sol | 51 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 test/unit/crosschain-data/BroadcastRegistry.t.sol diff --git a/src/crosschain-data/BroadcastRegistry.sol b/src/crosschain-data/BroadcastRegistry.sol index 62a45439b..37be9b48e 100644 --- a/src/crosschain-data/BroadcastRegistry.sol +++ b/src/crosschain-data/BroadcastRegistry.sol @@ -99,6 +99,16 @@ contract BroadcastRegistry is IBroadcastRegistry { onlySender { _broadcastPayload(srcSender_, ambId_, gasFee_, message_, extraData_); + + /// @dev refunds any overpaid msg.value + uint256 refundAmt = msg.value - gasFee_; + if (refundAmt > 0) { + (bool success,) = payable(srcSender_).call{ value: refundAmt }(""); + + if (!success) { + revert Error.FAILED_TO_SEND_NATIVE(); + } + } } /// @inheritdoc IBroadcastRegistry @@ -143,13 +153,13 @@ contract BroadcastRegistry is IBroadcastRegistry { function _broadcastPayload( address srcSender_, uint8 ambId_, - uint256 gasToPay_, + uint256 gasFee_, bytes memory message_, bytes memory extraData_ ) internal { - IBroadcastAmbImplementation(superRegistry.getAmbAddress(ambId_)).broadcastPayload{ value: gasToPay_ }( + IBroadcastAmbImplementation(superRegistry.getAmbAddress(ambId_)).broadcastPayload{ value: gasFee_ }( srcSender_, message_, extraData_ ); } diff --git a/test/unit/crosschain-data/BroadcastRegistry.t.sol b/test/unit/crosschain-data/BroadcastRegistry.t.sol new file mode 100644 index 000000000..3d47cdf5e --- /dev/null +++ b/test/unit/crosschain-data/BroadcastRegistry.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Unlicense +pragma solidity ^0.8.23; + +import "test/utils/BaseSetup.sol"; +import { BroadcastRegistry } from "src/crosschain-data/BroadcastRegistry.sol"; + +contract InvalidReceiver { + receive() external payable { + revert(); + } +} + +contract BroadcastRegistryTest is BaseSetup { + BroadcastRegistry public broadcastRegistry; + address caller; + address invalidReceiver; + + function setUp() public override { + super.setUp(); + + vm.selectFork(FORKS[ETH]); + broadcastRegistry = BroadcastRegistry(payable(getContract(ETH, "BroadcastRegistry"))); + invalidReceiver = address(new InvalidReceiver()); + + /// @dev caller + caller = address(420); + vm.deal(caller, 100 ether); + vm.deal(invalidReceiver, 100 ether); + + vm.startPrank(deployer); + SuperRBAC rbac = SuperRBAC(getContract(ETH, "SuperRBAC")); + rbac.grantRole(rbac.BROADCASTER_ROLE(), caller); + rbac.grantRole(rbac.BROADCASTER_ROLE(), invalidReceiver); + vm.stopPrank(); + } + + function test_broadcastRefunds() public { + vm.startPrank(caller); + broadcastRegistry.broadcastPayload{ value: 100 ether }(caller, 4, 0, bytes("testmepls"), bytes("")); + assertEq(address(broadcastRegistry).balance, 0); + assertEq(caller.balance, 100 ether); + } + + function test_revertOnFailedRefunds() public { + vm.startPrank(invalidReceiver); + vm.expectRevert(Error.FAILED_TO_SEND_NATIVE.selector); + broadcastRegistry.broadcastPayload{ value: 100 ether }(invalidReceiver, 4, 0, bytes("testmepls"), bytes("")); + assertEq(address(broadcastRegistry).balance, 0); + assertEq(invalidReceiver.balance, 100 ether); + } +} From fe61e2624b1828c3cd2fcf0798839a270dc0c99e Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 22 Dec 2023 10:04:51 +0000 Subject: [PATCH 124/210] fix: comments --- src/BaseRouterImplementation.sol | 22 ++++++--------------- src/crosschain-data/utils/PayloadHelper.sol | 4 ++-- src/interfaces/IPayloadHelper.sol | 4 ++-- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 28a6f8053..0fc439c72 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -5,6 +5,7 @@ import { BaseRouter } from "./BaseRouter.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; +import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol"; import { IBaseStateRegistry } from "./interfaces/IBaseStateRegistry.sol"; import { IBaseRouterImplementation } from "./interfaces/IBaseRouterImplementation.sol"; @@ -1105,23 +1106,12 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } /// @dev implementation copied from OpenZeppelin 5.0 and stripped down - function _doSafeTransferAcceptanceCheck(address to) private { + function _doSafeTransferAcceptanceCheck(address to) private view { if (to.code.length > 0) { - try IERC1155Receiver(to).onERC1155Received(address(0), address(0), 0, 0, "") returns (bytes4 response) { - if (response != IERC1155Receiver.onERC1155Received.selector) { - // Tokens rejected - revert IERC1155Errors.ERC1155InvalidReceiver(to); - } - } catch (bytes memory reason) { - if (reason.length == 0) { - // non-IERC1155Receiver implementer - revert IERC1155Errors.ERC1155InvalidReceiver(to); - } else { - /// @solidity memory-safe-assembly - assembly { - revert(add(32, reason), mload(reason)) - } - } + try IERC165(to).supportsInterface(type(IERC1155Receiver).interfaceId) returns (bool supported) { + if (!supported) revert IERC1155Errors.ERC1155InvalidReceiver(to); + } catch { + revert IERC1155Errors.ERC1155InvalidReceiver(to); } } } diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 2c6a6c4bd..54e84b3a8 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -171,12 +171,12 @@ contract PayloadHelper is IPayloadHelper { uint8 callbackType, uint8 multi, address srcSender, - address receiverAddress, + address receiverAddressSP, uint64 srcChainId ) { uint256 txInfo; - (txInfo, receiverAddress) = + (txInfo, receiverAddressSP) = ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).txHistory(srcPayloadId_); if (txInfo == 0) { diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index 9d0d8f8af..a8d198db2 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -68,7 +68,7 @@ interface IPayloadHelper { /// @return callbackType is the type of payload. check {CallbackType} enum in DataTypes.sol /// @return isMulti indicates if the transaction involves operations to multiple vaults /// @return srcSender is the user who initiated the transaction on the srcChain - /// @return receiverAddress is the address to be used for receiving assets + /// @return receiverAddressSP is the address to be used for receiving Super Positions /// @return srcChainId is the unique identifier of the srcChain function decodePayloadHistory(uint256 srcPayloadId_) external @@ -78,7 +78,7 @@ interface IPayloadHelper { uint8 callbackType, uint8 isMulti, address srcSender, - address receiverAddress, + address receiverAddressSP, uint64 srcChainId ); From 596d3eee01570f46241810e0ab0cb02edcf378fe Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:06:27 +0000 Subject: [PATCH 125/210] fix: all comments --- src/BaseForm.sol | 8 +++----- src/BaseRouterImplementation.sol | 12 ++++++------ src/forms/ERC4626Form.sol | 4 ++-- src/forms/ERC4626FormImplementation.sol | 7 ++++--- src/forms/ERC4626KYCDaoForm.sol | 4 ++-- src/forms/ERC4626TimelockForm.sol | 4 ++-- src/payments/PayMaster.sol | 8 ++++---- test/mocks/ERC4626FormExternal.sol | 4 ++-- .../BaseFormInterfaceNotSupported.sol | 8 +++----- .../ERC4626ImplementationInterfaceNotSupported.sol | 7 ++++--- .../ERC4626InterFaceNotSupported.sol | 4 ++-- .../superform-forms/superform-form.forwardDust.t.sol | 7 +++++-- 12 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 837bab0b2..180e8b9b4 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -262,10 +262,8 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { /// @inheritdoc IBaseForm function forwardDustToPaymaster(address token_) external override { - if (token_ == address(this)) revert Error.CANNOT_FORWARD_4646_TOKEN(); - uint256 amountForwarded = _forwardDustToPaymaster(token_); - - if (amountForwarded > 0) emit FormDustForwardedToPaymaster(token_, amountForwarded); + if (token_ == vault) revert Error.CANNOT_FORWARD_4646_TOKEN(); + _forwardDustToPaymaster(token_); } ////////////////////////////////////////////////////////////// @@ -314,7 +312,7 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { function _emergencyWithdraw(address srcSender_, address receiverAddress_, uint256 amount_) internal virtual; /// @dev forwards dust to paymaster - function _forwardDustToPaymaster(address token_) internal virtual returns (uint256); + function _forwardDustToPaymaster(address token_) internal virtual; /// @dev returns if a form id is paused function _isPaused(uint256 superformId) internal view returns (bool) { diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index c160c0840..51780da97 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -117,7 +117,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.extraFormData ); - /// @dev same chain action & forward residual payment to payment collector + /// @dev same chain action & forward residual payment to payment cctor _directSingleDeposit(msg.sender, req_.superformData.permit2data, vaultData); emit Completed(); } @@ -221,7 +221,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.extraFormData ); - /// @dev same chain action & forward residual payment to payment collector + /// @dev same chain action & forward residual payment to Paymaster _directMultiDeposit(msg.sender, req_.superformData.permit2data, vaultData); emit Completed(); } @@ -429,7 +429,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.extraFormData ); - /// @dev same chain action & forward residual payment to payment collector + /// @dev same chain action & forward residual payment to Paymaster _directMultiWithdraw(vaultData, msg.sender); emit Completed(); } @@ -750,7 +750,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); } } - + function _forwardDustToPaymaster(address token_) internal { if (token_ == address(0)) revert Error.ZERO_ADDRESS(); @@ -874,9 +874,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou // INTERNAL FEE FORWARDING HELPERS // ////////////////////////////////////////////////////////////// - /// @dev forwards the residual payment to payment collector + /// @dev forwards the residual payment to Paymaster function _forwardPayment(uint256 _balanceBefore) internal virtual { - /// @dev deducts what's already available sends what's left in msg.value to payment collector + /// @dev deducts what's already available sends what's left in msg.value to Paymaster uint256 residualPayment = address(this).balance - _balanceBefore; if (residualPayment != 0) { diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index b1a74d094..af9bf5279 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -80,7 +80,7 @@ contract ERC4626Form is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster(address token_) internal override returns (uint256) { - return _processForwardDustToPaymaster(token_); + function _forwardDustToPaymaster(address token_) internal override { + _processForwardDustToPaymaster(token_); } } diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index af95d444e..a305d7f85 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -410,15 +410,16 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit EmergencyWithdrawalProcessed(receiverAddress_, amount_); } - function _processForwardDustToPaymaster(address token_) internal returns (uint256) { + function _processForwardDustToPaymaster(address token_) internal { + if (token_ == address(0)) revert Error.ZERO_ADDRESS(); + address paymaster = superRegistry.getAddress(keccak256("PAYMASTER")); IERC20 token = IERC20(token_); uint256 dust = token.balanceOf(address(this)); if (dust != 0) { token.safeTransfer(paymaster, dust); + emit FormDustForwardedToPaymaster(token_, dust); } - - return dust; } } diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index 9b4ccb9af..e3fcb24c1 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -107,7 +107,7 @@ contract ERC4626KYCDaoForm is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster(address token_) internal override returns (uint256) { - return _processForwardDustToPaymaster(token_); + function _forwardDustToPaymaster(address token_) internal override { + _processForwardDustToPaymaster(token_); } } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 5174ed3f1..29310195b 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -211,8 +211,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster(address token_) internal override returns (uint256) { - return _processForwardDustToPaymaster(token_); + function _forwardDustToPaymaster(address token_) internal override { + _processForwardDustToPaymaster(token_); } /// @dev calls the vault to request unlock diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index 54e50d1fd..67565bd19 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -73,10 +73,6 @@ contract PayMaster is IPayMaster, LiquidityHandler { /// @inheritdoc IPayMaster function withdrawNativeTo(bytes32 superRegistryId_, uint256 nativeAmount_) external override onlyPaymentAdmin { - if (nativeAmount_ > address(this).balance) { - revert Error.FAILED_TO_SEND_NATIVE(); - } - _withdrawNative(superRegistry.getAddress(superRegistryId_), nativeAmount_); } @@ -138,6 +134,10 @@ contract PayMaster is IPayMaster, LiquidityHandler { /// @dev helper to move native tokens same chain function _withdrawNative(address receiver_, uint256 amount_) internal { + if (address(this).balance < amount_) { + revert Error.FAILED_TO_SEND_NATIVE(); + } + (bool success,) = payable(receiver_).call{ value: amount_ }(""); if (!success) { diff --git a/test/mocks/ERC4626FormExternal.sol b/test/mocks/ERC4626FormExternal.sol index d0515e36e..3343e50d9 100644 --- a/test/mocks/ERC4626FormExternal.sol +++ b/test/mocks/ERC4626FormExternal.sol @@ -73,7 +73,7 @@ contract ERC4626FormExternal is ERC4626FormImplementation { } /// @inheritdoc BaseForm - function _forwardDustToPaymaster(address token_) internal override returns (uint256) { - return _processForwardDustToPaymaster(token_); + function _forwardDustToPaymaster(address token_) internal override { + _processForwardDustToPaymaster(token_); } } diff --git a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol index 15178d406..b4bdbca71 100644 --- a/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/BaseFormInterfaceNotSupported.sol @@ -169,10 +169,8 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { /// @inheritdoc IBaseForm function forwardDustToPaymaster(address token_) external override { - if (token_ == address(this)) revert Error.CANNOT_FORWARD_4646_TOKEN(); - uint256 amountForwarded = _forwardDustToPaymaster(token_); - - if (amountForwarded > 0) emit FormDustForwardedToPaymaster(token_, amountForwarded); + if (token_ == vault) revert Error.CANNOT_FORWARD_4646_TOKEN(); + _forwardDustToPaymaster(token_); } /*/////////////////////////////////////////////////////////////// @@ -274,5 +272,5 @@ abstract contract BaseForm is Initializable, ERC165, IBaseForm { function _emergencyWithdraw(address srcSender_, address refundAddress_, uint256 amount_) internal virtual; /// @dev forwards dust to paymaster - function _forwardDustToPaymaster(address token_) internal virtual returns (uint256); + function _forwardDustToPaymaster(address token_) internal virtual; } diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index 8f0f6d917..3372ba524 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -347,16 +347,17 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li emit EmergencyWithdrawalProcessed(refundAddress_, amount_); } - function _processForwardDustToPaymaster(address token_) internal returns (uint256) { + function _processForwardDustToPaymaster(address token_) internal { + if (token_ == address(0)) revert Error.ZERO_ADDRESS(); + address paymaster = superRegistry.getAddress(keccak256("PAYMASTER")); IERC20 token = IERC20(token_); uint256 dust = token.balanceOf(address(this)); if (dust != 0) { token.safeTransfer(paymaster, dust); + emit FormDustForwardedToPaymaster(token_, dust); } - - return dust; } /*/////////////////////////////////////////////////////////////// diff --git a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol index 73a2e052e..b1ea95b27 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626InterFaceNotSupported.sol @@ -73,7 +73,7 @@ contract ERC4626FormInterfaceNotSupported is ERC4626FormImplementationInterfaceN } /// @inheritdoc BaseForm - function _forwardDustToPaymaster(address token_) internal override returns (uint256) { - return _processForwardDustToPaymaster(token_); + function _forwardDustToPaymaster(address token_) internal override { + _processForwardDustToPaymaster(token_); } } diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index a726b8cce..2bbf2e540 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -61,9 +61,12 @@ contract ForwardDustFormTest is ProtocolActions { deal(arbitraryToken, superform, 10e18); IBaseForm(superform).forwardDustToPaymaster(arbitraryToken); - + address vaultAddress = IBaseForm(superform).getVaultAddress(); vm.expectRevert(Error.CANNOT_FORWARD_4646_TOKEN.selector); - IBaseForm(superform).forwardDustToPaymaster(superform); + IBaseForm(superform).forwardDustToPaymaster(vaultAddress); + + vm.expectRevert(Error.ZERO_ADDRESS.selector); + IBaseForm(superform).forwardDustToPaymaster(address(0)); } function _successfulDepositWithdraw( From 66876e76a6e5812738d67818f5faa0c9a998cf07 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:12:59 +0000 Subject: [PATCH 126/210] fix: build error --- src/libraries/Error.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 8202a709b..b96ac4060 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -362,9 +362,6 @@ library Error { /// @dev thrown when redeeming from vault yields zero collateral error WITHDRAW_ZERO_COLLATERAL(); - /// @dev thrown if a state registry id is 0 - error INVALID_REGISTRY_ID(); - /*/////////////////////////////////////////////////////////////// PAYMASTER ERRORS //////////////////////////////////////////////////////////////*/ @@ -413,9 +410,6 @@ library Error { /// @dev thrown if withdrawal tx data is not updated error WITHDRAW_TX_DATA_NOT_UPDATED(); - /// @dev thrown when redeeming from vault yields zero collateral - error WITHDRAW_ZERO_COLLATERAL(); - /// PAYMENT HELPER EXECUTION ERRORS /// @dev thrown if chainlink is reporting an improper price error CHAINLINK_MALFUNCTION(); From 69a1ed7b9bbd10805a22f0548d3c3e0c5f88d4fb Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 22 Dec 2023 14:14:33 +0000 Subject: [PATCH 127/210] chore: typo fix --- src/BaseRouterImplementation.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 68d63c9db..2c293c55d 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -117,7 +117,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.extraFormData ); - /// @dev same chain action & forward residual payment to payment cctor + /// @dev same chain action & forward residual payment to Paymaster _directSingleDeposit(msg.sender, req_.superformData.permit2data, vaultData); emit Completed(); } From b3bb14bda5578cebbffa828327be98797074058f Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 22 Dec 2023 14:26:21 +0000 Subject: [PATCH 128/210] chore: handle return of _revokeRole --- src/libraries/Error.sol | 3 +++ src/settings/SuperRBAC.sol | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 705f6437f..2948a7aff 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -31,6 +31,9 @@ library Error { /// @dev thrown if indices have duplicates error DUPLICATE_INDEX(); + /// @dev thrown if a role to be revoked is not assigned + error ROLE_NOT_ASSIGNED(); + ////////////////////////////////////////////////////////////// // AUTHORIZATION ERRORS // ////////////////////////////////////////////////////////////// diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 41bc0ff42..9e96139fc 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -171,12 +171,15 @@ contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { role_ == PROTOCOL_ADMIN_ROLE || role_ == EMERGENCY_ADMIN_ROLE || role_ == BROADCASTER_ROLE || role_ == WORMHOLE_VAA_RELAYER_ROLE ) revert Error.CANNOT_REVOKE_NON_BROADCASTABLE_ROLES(); - _revokeRole(role_, superRegistry.getAddress(superRegistryAddressId_)); - if (extraData_.length != 0) { - BroadcastMessage memory rolesPayload = BroadcastMessage( - "SUPER_RBAC", SYNC_REVOKE, abi.encode(++xChainPayloadCounter, role_, superRegistryAddressId_) - ); - _broadcast(abi.encode(rolesPayload), extraData_); + if (_revokeRole(role_, superRegistry.getAddress(superRegistryAddressId_))) { + if (extraData_.length != 0) { + BroadcastMessage memory rolesPayload = BroadcastMessage( + "SUPER_RBAC", SYNC_REVOKE, abi.encode(++xChainPayloadCounter, role_, superRegistryAddressId_) + ); + _broadcast(abi.encode(rolesPayload), extraData_); + } + } else { + revert Error.ROLE_NOT_ASSIGNED(); } } @@ -194,7 +197,11 @@ contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { role == PROTOCOL_ADMIN_ROLE || role == EMERGENCY_ADMIN_ROLE || role == BROADCASTER_ROLE || role == WORMHOLE_VAA_RELAYER_ROLE ) - ) _revokeRole(role, superRegistry.getAddress(superRegistryAddressId)); + ) { + if (!_revokeRole(role, superRegistry.getAddress(superRegistryAddressId))) { + revert Error.ROLE_NOT_ASSIGNED(); + } + } } ////////////////////////////////////////////////////////////// From 9296e4163219980314b78ab8dafb720e2d95bf10 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 22 Dec 2023 20:07:39 +0530 Subject: [PATCH 129/210] chore: replace proof length to 96 in extraData generation --- src/payments/PaymentHelper.sol | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index f42237249..d34b2a472 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -32,6 +32,7 @@ contract PaymentHelper is IPaymentHelper { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// + uint256 private constant PROOF_LENGTH = 96; ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; @@ -653,16 +654,13 @@ contract PaymentHelper is IPaymentHelper { uint256 gasReqPerByte = gasPerByte[dstChainId_]; uint256 totalDstGasReqInWei = abi.encode(ambIdEncodedMessage).length * gasReqPerByte; - AMBMessage memory decodedMessage = abi.decode(message_, (AMBMessage)); - decodedMessage.params = message_.computeProofBytes(); - - uint256 totalDstGasReqInWeiForProof = abi.encode(decodedMessage).length * gasReqPerByte; + /// @dev proof length is always 96 + uint256 totalDstGasReqInWeiForProof = PROOF_LENGTH * gasReqPerByte; extraDataPerAMB = new bytes[](len); for (uint256 i; i < len; ++i) { uint256 gasReq = i != 0 ? totalDstGasReqInWeiForProof : totalDstGasReqInWei; - /// @dev amb id 1: layerzero /// @dev amb id 2: hyperlane /// @dev amb id 3: wormhole From e12904e4beec98b782a38961ca2627a88cf859ba Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 22 Dec 2023 20:08:54 +0530 Subject: [PATCH 130/210] chore: opt validateLiqReq --- src/libraries/PayloadUpdaterLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/PayloadUpdaterLib.sol b/src/libraries/PayloadUpdaterLib.sol index a46be73b5..adc66395f 100644 --- a/src/libraries/PayloadUpdaterLib.sol +++ b/src/libraries/PayloadUpdaterLib.sol @@ -34,7 +34,7 @@ library PayloadUpdaterLib { function validateLiqReq(LiqRequest memory req_) internal pure { /// revert if token is address(0) -> user wants settlement without any liq data /// revert if token is not address(0) and txData is already present - if (req_.token == address(0) || (req_.token != address(0) && req_.txData.length != 0)) { + if (req_.token == address(0) || req_.txData.length != 0) { revert Error.CANNOT_UPDATE_WITHDRAW_TX_DATA(); } } From 9a656065c4c6c2ae7fe94ef8f72796d787e3a626 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Fri, 22 Dec 2023 20:41:18 +0530 Subject: [PATCH 131/210] chore: restrict price feeds to 8 decimals --- src/libraries/Error.sol | 5 ++- src/payments/PaymentHelper.sol | 31 +++++++++++++++--- test/unit/payments/PaymentHelper.t.sol | 44 ++++++++++++++++++-------- 3 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 705f6437f..6f9221448 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -400,7 +400,7 @@ library Error { /// @dev thrown if withdrawal tx data is not updated error WITHDRAW_TX_DATA_NOT_UPDATED(); - + /// @dev thrown when redeeming from vault yields zero collateral error WITHDRAW_ZERO_COLLATERAL(); @@ -411,6 +411,9 @@ library Error { /// @dev thrown if chainlink is reporting an incomplete round error CHAINLINK_INCOMPLETE_ROUND(); + /// @dev thrown if feed decimals is not 8 + error CHAINLINK_UNSUPPORTED_DECIMAL(); + /// EMERGENCY QUEUE EXECUTION ERRORS /// @dev thrown if emergency withdraw is not queued diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index f42237249..988b4f771 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -32,11 +32,12 @@ contract PaymentHelper is IPaymentHelper { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// + uint8 private constant SUPPORTED_FEED_PRECISION = 8; + uint32 private constant TIMELOCK_FORM_ID = 2; + uint256 private constant MAX_UINT256 = type(uint256).max; ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; - uint32 private constant TIMELOCK_FORM_ID = 2; - uint256 private constant MAX_UINT256 = type(uint256).max; ////////////////////////////////////////////////////////////// // STATE VARIABLES // @@ -534,10 +535,18 @@ contract PaymentHelper is IPaymentHelper { { if (config_.nativeFeedOracle != address(0)) { nativeFeedOracle[chainId_] = AggregatorV3Interface(config_.nativeFeedOracle); + + if (nativeFeedOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION) { + revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); + } } if (config_.gasPriceOracle != address(0)) { gasPriceOracle[chainId_] = AggregatorV3Interface(config_.gasPriceOracle); + + if (gasPriceOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION) { + revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); + } } swapGasUsed[chainId_] = config_.swapGasUsed; @@ -566,12 +575,26 @@ contract PaymentHelper is IPaymentHelper { { /// @dev Type 1: DST TOKEN PRICE FEED ORACLE if (configType_ == 1) { - nativeFeedOracle[chainId_] = AggregatorV3Interface(abi.decode(config_, (address))); + address nativeFeedOracleAddress = abi.decode(config_, (address)); + nativeFeedOracle[chainId_] = AggregatorV3Interface(nativeFeedOracleAddress); + + if ( + nativeFeedOracleAddress != address(0) + && nativeFeedOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION + ) { + revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); + } } /// @dev Type 2: DST GAS PRICE ORACLE if (configType_ == 2) { - gasPriceOracle[chainId_] = AggregatorV3Interface(abi.decode(config_, (address))); + address gasPriceOracleAddress = abi.decode(config_, (address)); + gasPriceOracle[chainId_] = AggregatorV3Interface(gasPriceOracleAddress); + + if (gasPriceOracleAddress != address(0) && gasPriceOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION) + { + revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); + } } /// @dev Type 3: SWAP GAS USED diff --git a/test/unit/payments/PaymentHelper.t.sol b/test/unit/payments/PaymentHelper.t.sol index 70c2fce4f..ceaa13d51 100644 --- a/test/unit/payments/PaymentHelper.t.sol +++ b/test/unit/payments/PaymentHelper.t.sol @@ -11,11 +11,30 @@ contract MockGasPriceOracle { { return (0, 28 gwei, block.timestamp, block.timestamp, 28 gwei); } + + function decimals() external view returns (uint8) { + return 8; + } +} + +contract MalFunctioningPriceOracle { + function latestRoundData() + external + view + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (0, 0, block.timestamp, block.timestamp, 0); + } + + function decimals() external view returns (uint8) { + return 8; + } } contract PaymentHelperTest is ProtocolActions { PaymentHelper public paymentHelper; MockGasPriceOracle public mockGasPriceOracle; + MalFunctioningPriceOracle public malFunctioningOracle; address native = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address receiverAddress = address(444); @@ -26,11 +45,12 @@ contract PaymentHelperTest is ProtocolActions { vm.selectFork(FORKS[ETH]); paymentHelper = PaymentHelper(getContract(ETH, "PaymentHelper")); mockGasPriceOracle = new MockGasPriceOracle(); + malFunctioningOracle = new MalFunctioningPriceOracle(); } function test_getGasPrice_chainlink_malfunction() public { vm.prank(deployer); - paymentHelper.updateRemoteChain(1, 2, abi.encode(address(0x222))); + paymentHelper.updateRemoteChain(1, 2, abi.encode(address(malFunctioningOracle))); address gasPriceOracle = address(paymentHelper.gasPriceOracle(ETH)); vm.mockCall( @@ -64,7 +84,7 @@ contract PaymentHelperTest is ProtocolActions { function test_getGasPrice_chainlink_incomplete_round() public { vm.prank(deployer); - paymentHelper.updateRemoteChain(1, 2, abi.encode(address(0x222))); + paymentHelper.updateRemoteChain(1, 2, abi.encode(address(malFunctioningOracle))); address gasPriceOracle = address(paymentHelper.gasPriceOracle(ETH)); @@ -539,17 +559,17 @@ contract PaymentHelperTest is ProtocolActions { /// set config type: 1 vm.prank(deployer); - paymentHelper.updateRemoteChain(1, 1, abi.encode(address(420))); + paymentHelper.updateRemoteChain(1, 1, abi.encode(address(mockGasPriceOracle))); address result1 = address(paymentHelper.nativeFeedOracle(1)); - assertEq(result1, address(420)); + assertEq(result1, address(mockGasPriceOracle)); /// set config type: 2 vm.prank(deployer); - paymentHelper.updateRemoteChain(1, 2, abi.encode(address(421))); + paymentHelper.updateRemoteChain(1, 2, abi.encode(address(mockGasPriceOracle))); address result2 = address(paymentHelper.gasPriceOracle(1)); - assertEq(result2, address(421)); + assertEq(result2, address(mockGasPriceOracle)); /// set config type: 3 vm.prank(deployer); @@ -619,9 +639,7 @@ contract PaymentHelperTest is ProtocolActions { vm.prank(deployer); paymentHelper.addRemoteChain( 420, - IPaymentHelper.PaymentHelperConfig( - address(420), address(421), 422, 423, 424, 425, 426, 427, 428, 429, 430, 431 - ) + IPaymentHelper.PaymentHelperConfig(address(0), address(0), 422, 423, 424, 425, 426, 427, 428, 429, 430, 431) ); } @@ -630,17 +648,17 @@ contract PaymentHelperTest is ProtocolActions { /// set config type: 1 vm.prank(deployer); - paymentHelper.updateRemoteChain(420, 1, abi.encode(address(420))); + paymentHelper.updateRemoteChain(420, 1, abi.encode(address(mockGasPriceOracle))); address result1 = address(paymentHelper.nativeFeedOracle(420)); - assertEq(result1, address(420)); + assertEq(result1, address(mockGasPriceOracle)); /// set config type: 2 vm.prank(deployer); - paymentHelper.updateRemoteChain(420, 2, abi.encode(address(421))); + paymentHelper.updateRemoteChain(420, 2, abi.encode(address(mockGasPriceOracle))); address result2 = address(paymentHelper.gasPriceOracle(420)); - assertEq(result2, address(421)); + assertEq(result2, address(mockGasPriceOracle)); /// set config type: 3 vm.prank(deployer); From a88a7e690634d808083a175fc0b20b0e3fcd7a3e Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:18:53 +0000 Subject: [PATCH 132/210] feat: add retain4626 for withdraws --- src/BaseRouterImplementation.sol | 8 +- src/forms/ERC4626FormImplementation.sol | 167 ++++++++++-------- src/forms/ERC4626TimelockForm.sol | 82 +++++---- .../superform-router/SuperformRouter.AA.t.sol | 131 ++++++++++---- 4 files changed, 232 insertions(+), 156 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 000f2a772..014fb03ce 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -326,7 +326,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippage, req_.superformData.liqRequest, false, - false, + req_.superformData.retain4626, req_.superformData.receiverAddress, req_.superformData.extraFormData ); @@ -374,7 +374,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippage, req_.superformData.liqRequest, false, - false, + req_.superformData.retain4626, req_.superformData.receiverAddress, req_.superformData.extraFormData ); @@ -424,7 +424,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.maxSlippages, req_.superformData.liqRequests, new bool[](req_.superformData.superformIds.length), - new bool[](req_.superformData.superformIds.length), + req_.superformData.retain4626s, req_.superformData.receiverAddress, req_.superformData.extraFormData ); @@ -461,7 +461,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformsData.maxSlippages, req_.superformsData.liqRequests, new bool[](req_.superformsData.amounts.length), - new bool[](req_.superformsData.amounts.length), + req_.superformsData.retain4626s, req_.superformsData.receiverAddress, req_.superformsData.extraFormData ); diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 19d4898f3..e088d4e5d 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -293,49 +293,57 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC4626 v = IERC4626(vault); IERC20 a = IERC20(asset); - vars.asset = address(asset); - - /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); - assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); - if (assetsBalanceAfter - assetsBalanceBefore != assets) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } - - if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); - - if (vars.len1 != 0) { - vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); - vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); - /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + if (!singleVaultData_.retain4626) { + vars.asset = address(asset); - vars.chainId = CHAIN_ID; + /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior + uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); + assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); + if (assetsBalanceAfter - assetsBalanceBefore != assets) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } - /// @dev validate and perform the swap to desired output token and send to beneficiary - IBridgeValidator(vars.bridgeValidator).validateTxData( - IBridgeValidator.ValidateTxDataArgs( + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + + if (vars.len1 != 0) { + vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); + vars.amount = + IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); + + /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault + if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + + vars.chainId = CHAIN_ID; + + /// @dev validate and perform the swap to desired output token and send to beneficiary + IBridgeValidator(vars.bridgeValidator).validateTxData( + IBridgeValidator.ValidateTxDataArgs( + singleVaultData_.liqData.txData, + vars.chainId, + vars.chainId, + singleVaultData_.liqData.liqDstChainId, + false, + address(this), + singleVaultData_.receiverAddress, + vars.asset, + address(0) + ) + ); + + _dispatchTokens( + superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), singleVaultData_.liqData.txData, - vars.chainId, - vars.chainId, - singleVaultData_.liqData.liqDstChainId, - false, - address(this), - singleVaultData_.receiverAddress, vars.asset, - address(0) - ) - ); - - _dispatchTokens( - superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), - singleVaultData_.liqData.txData, - vars.asset, - vars.amount, - singleVaultData_.liqData.nativeAmount - ); + vars.amount, + singleVaultData_.liqData.nativeAmount + ); + } + } else { + /// transfer shares to user and do not withdraw + v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); + return 0; } } @@ -366,47 +374,54 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC4626 v = IERC4626(vault); IERC20 a = IERC20(asset); - vars.asset = address(asset); - - /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); - assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); - if (assetsBalanceAfter - assetsBalanceBefore != assets) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } - - if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); - - if (len != 0) { - vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); - vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); - - /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > assets) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); + if (!singleVaultData_.retain4626) { + vars.asset = address(asset); + + /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior + uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); + assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); + if (assetsBalanceAfter - assetsBalanceBefore != assets) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } - /// @dev validate and perform the swap to desired output token and send to beneficiary - IBridgeValidator(vars.bridgeValidator).validateTxData( - IBridgeValidator.ValidateTxDataArgs( + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + + if (len != 0) { + vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); + vars.amount = + IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); + + /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault + if (vars.amount > assets) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); + + /// @dev validate and perform the swap to desired output token and send to beneficiary + IBridgeValidator(vars.bridgeValidator).validateTxData( + IBridgeValidator.ValidateTxDataArgs( + singleVaultData_.liqData.txData, + vars.dstChainId, + srcChainId_, + singleVaultData_.liqData.liqDstChainId, + false, + address(this), + singleVaultData_.receiverAddress, + vars.asset, + address(0) + ) + ); + + _dispatchTokens( + superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), singleVaultData_.liqData.txData, - vars.dstChainId, - srcChainId_, - singleVaultData_.liqData.liqDstChainId, - false, - address(this), - singleVaultData_.receiverAddress, vars.asset, - address(0) - ) - ); - - _dispatchTokens( - superRegistry.getBridgeAddress(singleVaultData_.liqData.bridgeId), - singleVaultData_.liqData.txData, - vars.asset, - vars.amount, - singleVaultData_.liqData.nativeAmount - ); + vars.amount, + singleVaultData_.liqData.nativeAmount + ); + } + } else { + /// transfer shares to user and do not withdraw + v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); + return 0; } emit Processed(srcChainId_, vars.dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vault); diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 0bd3ca4d1..5a92135e9 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -17,6 +17,7 @@ import { Error } from "../libraries/Error.sol"; /// @notice Form implementation to handle timelock extension for ERC4626 vaults contract ERC4626TimelockForm is ERC4626FormImplementation { using SafeERC20 for IERC20; + using SafeERC20 for IERC4626TimelockVault; using DataLib for uint256; ////////////////////////////////////////////////////////////// @@ -96,46 +97,53 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { vars.asset = asset; IERC20 assetERC = IERC20(vars.asset); - uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); - assets = v.redeem(p_.data.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); - if (assetsBalanceAfter - assetsBalanceBefore != assets) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } - if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); - - /// @dev validate and dispatches the tokens - if (vars.len1 != 0) { - vars.bridgeValidator = superRegistry.getBridgeValidator(vars.liqData.bridgeId); - vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(vars.liqData.txData, false); - - /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); - - vars.chainId = CHAIN_ID; - - /// @dev validate and perform the swap to desired output token and send to beneficiary - IBridgeValidator(superRegistry.getBridgeValidator(vars.liqData.bridgeId)).validateTxData( - IBridgeValidator.ValidateTxDataArgs( + if (!p_.data.retain4626) { + uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); + assets = v.redeem(p_.data.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); + if (assetsBalanceAfter - assetsBalanceBefore != assets) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + + /// @dev validate and dispatches the tokens + if (vars.len1 != 0) { + vars.bridgeValidator = superRegistry.getBridgeValidator(vars.liqData.bridgeId); + vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(vars.liqData.txData, false); + + /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault + if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + + vars.chainId = CHAIN_ID; + + /// @dev validate and perform the swap to desired output token and send to beneficiary + IBridgeValidator(superRegistry.getBridgeValidator(vars.liqData.bridgeId)).validateTxData( + IBridgeValidator.ValidateTxDataArgs( + vars.liqData.txData, + vars.chainId, + p_.isXChain == 1 ? p_.srcChainId : vars.chainId, + vars.liqData.liqDstChainId, + false, + address(this), + p_.data.receiverAddress, + vars.asset, + address(0) + ) + ); + + _dispatchTokens( + superRegistry.getBridgeAddress(vars.liqData.bridgeId), vars.liqData.txData, - vars.chainId, - p_.isXChain == 1 ? p_.srcChainId : vars.chainId, - vars.liqData.liqDstChainId, - false, - address(this), - p_.data.receiverAddress, vars.asset, - address(0) - ) - ); + vars.amount, + vars.liqData.nativeAmount + ); + } + } else { + /// @dev if the 4626 is to be retained, the 4626 is sent directly to the receiver + v.safeTransfer(p_.data.receiverAddress, p_.data.amount); - _dispatchTokens( - superRegistry.getBridgeAddress(vars.liqData.bridgeId), - vars.liqData.txData, - vars.asset, - vars.amount, - vars.liqData.nativeAmount - ); + return 0; } } diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index f221dfbc7..3bf8a0d59 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -61,7 +61,7 @@ contract SuperformRouterAATest is ProtocolActions { function test_withdrawWithSmartContractWallet() public { _xChainDeposit_SmartContractWallet(false, true, "VaultMock", 0); - _xChainWithdraw_SmartContractWallet(ETH, address(walletDestination), false, "VaultMock", 0); + _xChainWithdraw_SmartContractWallet(ETH, address(walletDestination), false, "VaultMock", 0, false); } function test_withdrawWithSmartContractWallet_3rdChainId() public { @@ -71,13 +71,13 @@ contract SuperformRouterAATest is ProtocolActions { SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") ); - _xChainWithdraw_SmartContractWallet(AVAX, address(walletDestinationAVAX), false, "VaultMock", 0); + _xChainWithdraw_SmartContractWallet(AVAX, address(walletDestinationAVAX), false, "VaultMock", 0, false); } function test_withdrawWithSmartContractWallet_timelock() public { _xChainDeposit_SmartContractWallet(false, true, "ERC4626TimelockMock", 1); - _xChainWithdraw_SmartContractWallet(ETH, address(walletDestination), false, "ERC4626TimelockMock", 1); + _xChainWithdraw_SmartContractWallet(ETH, address(walletDestination), false, "ERC4626TimelockMock", 1, false); } function test_withdrawWithSmartContractWallet_3rdChainId_timelock() public { @@ -87,7 +87,41 @@ contract SuperformRouterAATest is ProtocolActions { SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") ); - _xChainWithdraw_SmartContractWallet(AVAX, address(walletDestinationAVAX), false, "ERC4626TimelockMock", 1); + _xChainWithdraw_SmartContractWallet( + AVAX, address(walletDestinationAVAX), false, "ERC4626TimelockMock", 1, false + ); + } + + function test_withdrawWithSmartContractWallet_retain4626() public { + _xChainDeposit_SmartContractWallet(false, true, "VaultMock", 0); + + _xChainWithdraw_SmartContractWallet(ARBI, address(walletDestination), false, "VaultMock", 0, true); + } + + function test_withdrawWithSmartContractWallet_3rdChainId_retain4626() public { + _xChainDeposit_SmartContractWallet(false, true, "VaultMock", 0); + vm.selectFork(FORKS[AVAX]); + SmartContractWallet walletDestinationAVAX = new SmartContractWallet( + SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") + ); + + _xChainWithdraw_SmartContractWallet(ARBI, address(walletDestinationAVAX), false, "VaultMock", 0, true); + } + + function test_withdrawWithSmartContractWallet_timelock_retain4626() public { + _xChainDeposit_SmartContractWallet(false, true, "ERC4626TimelockMock", 1); + + _xChainWithdraw_SmartContractWallet(ARBI, address(walletDestination), false, "ERC4626TimelockMock", 1, true); + } + + function test_withdrawWithSmartContractWallet_3rdChainId_timelock_retain4626() public { + _xChainDeposit_SmartContractWallet(false, true, "ERC4626TimelockMock", 1); + vm.selectFork(FORKS[AVAX]); + SmartContractWallet walletDestinationAVAX = new SmartContractWallet( + SuperformRouter(payable(getContract(AVAX, "SuperformRouter"))), getContract(AVAX, "DAI") + ); + + _xChainWithdraw_SmartContractWallet(ARBI, address(walletDestinationAVAX), false, "ERC4626TimelockMock", 1, true); } function _xChainDeposit_SmartContractWallet( @@ -228,58 +262,67 @@ contract SuperformRouterAATest is ProtocolActions { } } + struct XChainWithdrawsInternalVars { + address superform; + uint256 superformId; + } + function _xChainWithdraw_SmartContractWallet( uint64 liqDstChainId_, address scWalletAtLiqDst_, bool sameChainTxData_, string memory vaultKind, - uint256 formImplId + uint256 formImplId, + bool receive4626_ ) internal { /// scenario: user deposits with his own collateral and has approved enough tokens vm.selectFork(FORKS[ETH]); - - address superformRouter = getContract(ETH, "SuperformRouter"); - - address superform = getContract( + XChainWithdrawsInternalVars memory v; + v.superform = getContract( ARBI, string.concat("DAI", vaultKind, "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[formImplId])) ); - uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[formImplId], ARBI); - - bytes memory txData = _buildLiqBridgeTxData( - LiqBridgeTxDataArgs( - 1, - getContract(ARBI, "DAI"), - getContract(ARBI, "DAI"), - getContract(liqDstChainId_, "DAI"), - superform, - ARBI, - ETH, - liqDstChainId_, - false, - scWalletAtLiqDst_, - uint256(liqDstChainId_), - 1e18, - true, - /// @dev placeholder value, not used - 0, - 1, - 1, - 1 - ), - sameChainTxData_ - ); + v.superformId = DataLib.packSuperform(v.superform, FORM_IMPLEMENTATION_IDS[formImplId], ARBI); SingleVaultSFData memory data = SingleVaultSFData( - superformId, + v.superformId, 1e18, 1000, - LiqRequest(txData, getContract(ARBI, "DAI"), address(0), 1, liqDstChainId_, 0), + LiqRequest( + _buildLiqBridgeTxData( + LiqBridgeTxDataArgs( + 1, + getContract(ARBI, "DAI"), + getContract(ARBI, "DAI"), + getContract(liqDstChainId_, "DAI"), + v.superform, + ARBI, + ETH, + liqDstChainId_, + false, + scWalletAtLiqDst_, + uint256(liqDstChainId_), + 1e18, + true, + /// @dev placeholder value, not used + 0, + 1, + 1, + 1 + ), + sameChainTxData_ + ), + getContract(ARBI, "DAI"), + address(0), + 1, + liqDstChainId_, + 0 + ), "", false, - false, + receive4626_, liqDstChainId_ != ETH ? scWalletAtLiqDst_ : address(walletDestination), "" ); @@ -288,11 +331,15 @@ contract SuperformRouterAATest is ProtocolActions { ambIds_[0] = 1; ambIds_[1] = 2; + console.log("receiverAddress", data.receiverAddress); + SingleXChainSingleVaultStateReq memory req = SingleXChainSingleVaultStateReq(ambIds_, ARBI, data); /// @dev approves before call vm.prank(address(walletSource)); - SuperPositions(getContract(ETH, "SuperPositions")).increaseAllowance(superformRouter, superformId, 1e18); + SuperPositions(getContract(ETH, "SuperPositions")).increaseAllowance( + getContract(ETH, "SuperformRouter"), v.superformId, 1e18 + ); vm.recordLogs(); vm.prank(deployer); @@ -326,8 +373,14 @@ contract SuperformRouterAATest is ProtocolActions { TimelockStateRegistry(getContract(ARBI, "TimelockStateRegistry")).finalizePayload{ value: 2 ether }(1, ""); } + + if (receive4626_) { + console.log("scWalletAtLiqDst_", scWalletAtLiqDst_); + + assertGt(IERC4626(IBaseForm(v.superform).getVaultAddress()).balanceOf(scWalletAtLiqDst_), 0); + } vm.selectFork(FORKS[ETH]); - assertEq(SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(address(walletSource), superformId), 0); + assertEq(SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(address(walletSource), v.superformId), 0); } } From 27c47a6f135cc7f430c22619f22c3c308ea26428 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:22:33 -0600 Subject: [PATCH 133/210] chore: nitpick formatting --- src/forms/ERC4626FormImplementation.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index e088d4e5d..8cb22681a 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -341,7 +341,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ); } } else { - /// transfer shares to user and do not withdraw + /// @dev transfer shares to user and do not withdraw v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); return 0; } @@ -419,7 +419,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ); } } else { - /// transfer shares to user and do not withdraw + /// @dev transfer shares to user and do not withdraw v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); return 0; } @@ -428,15 +428,15 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { } function _processEmergencyWithdraw(address receiverAddress_, uint256 amount_) internal { - IERC4626 vaultContract = IERC4626(vault); + IERC4626 v = IERC4626(vault); - if (vaultContract.balanceOf(address(this)) < amount_) { + if (v.balanceOf(address(this)) < amount_) { revert Error.INSUFFICIENT_BALANCE(); } if (receiverAddress_ == address(0)) revert Error.ZERO_ADDRESS(); - vaultContract.safeTransfer(receiverAddress_, amount_); + v.safeTransfer(receiverAddress_, amount_); emit EmergencyWithdrawalProcessed(receiverAddress_, amount_); } From df0b75326349795236060d6b190fd01d19acb5b7 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:24:46 -0600 Subject: [PATCH 134/210] chore: consistent comments --- src/forms/ERC4626FormImplementation.sol | 4 ++-- src/forms/ERC4626TimelockForm.sol | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 8cb22681a..d261d0ff5 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -341,7 +341,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ); } } else { - /// @dev transfer shares to user and do not withdraw + /// @dev transfer shares to user and do not redeem shares for assets v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); return 0; } @@ -419,7 +419,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ); } } else { - /// @dev transfer shares to user and do not withdraw + /// @dev transfer shares to user and do not redeem shares for assets v.safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); return 0; } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 5a92135e9..1df6d0628 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -140,9 +140,8 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { ); } } else { - /// @dev if the 4626 is to be retained, the 4626 is sent directly to the receiver + /// @dev transfer shares to user and do not redeem shares for assets v.safeTransfer(p_.data.receiverAddress, p_.data.amount); - return 0; } } From 07a23a599a398fbf88ef7891b2bc6c6ff6e558f9 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:31:18 -0600 Subject: [PATCH 135/210] chore: clean logic --- src/crosschain-liquidity/DstSwapper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index f66eec194..e4faa95d8 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -175,7 +175,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { onlySwapper { uint256 len = txData_.length; - if (len == 0 || indices_.length == 0 || bridgeIds_.length == 0 ) revert Error.ZERO_INPUT_VALUE(); + if (len == 0) revert Error.ZERO_INPUT_VALUE(); if (len != bridgeIds_.length && len != txData_.length) revert Error.ARRAY_LENGTH_MISMATCH(); IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); From 8f3e4ae07e3e1897cc9f047ca7b2c906081f47ca Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Sat, 23 Dec 2023 11:32:08 +0000 Subject: [PATCH 136/210] fix: merge issue --- test/unit/superform-router/SuperformRouter.t.sol | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 81c2341bb..a349f7bd9 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -1802,7 +1802,16 @@ contract SuperformRouterTest is ProtocolActions { ); MultiVaultSFData memory data = MultiVaultSFData( - v.superformIds, v.amounts, v.maxSlippages, v.liqReqs, "", v.hasDstSwaps, v.retain4626s, receiverAddress, "" + v.superformIds, + v.amounts, + v.maxSlippages, + v.liqReqs, + "", + v.hasDstSwaps, + v.retain4626s, + receiverAddress, + receiverAddress, + "" ); v.ambIds = new uint8[](1); v.ambIds[0] = 1; From fa04d60499eb03d207ee72811d8376c983142469 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Sat, 23 Dec 2023 13:24:00 +0000 Subject: [PATCH 137/210] fix: amended retain4626 timelock, fix flag --- src/BaseRouterImplementation.sol | 5 +- src/forms/ERC4626TimelockForm.sol | 114 ++++++------ .../adapters/LayerzeroImplementation.t.sol | 5 +- .../superform-router/SuperformRouter.AA.t.sol | 166 +++++++++++++++++- 4 files changed, 234 insertions(+), 56 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 014fb03ce..4f5442383 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -685,6 +685,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou uint256 amount_, uint256 maxSlippage_, LiqRequest memory liqData_, + bool retain4626_, address receiverAddress_, bytes memory extraFormData_, address srcSender_ @@ -701,7 +702,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou maxSlippage_, liqData_, false, - false, + retain4626_, receiverAddress_, extraFormData_ ), @@ -722,6 +723,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vaultData_.amount, vaultData_.maxSlippage, vaultData_.liqData, + vaultData_.retain4626, vaultData_.receiverAddress, vaultData_.extraFormData, srcSender_ @@ -744,6 +746,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vaultData_.amounts[i], vaultData_.maxSlippages[i], vaultData_.liqData[i], + vaultData_.retain4626s[i], vaultData_.receiverAddress, vaultData_.extraFormData, srcSender_ diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 1df6d0628..2f512092e 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -62,6 +62,9 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { ////////////////////////////////////////////////////////////// /// @dev this function is called when the timelock deposit is ready to be withdrawn after being unlocked + /// @dev retain4626 flag is not added in this implementation unlike in ERC4626Implementation.sol because + /// @dev if a vault fails to redeem at this stage, superPositions are minted back to the user and he can + /// @dev try again with retain4626 flag set and take their shares directly /// @param p_ the payload data function withdrawAfterCoolDown(TimelockPayload memory p_) external @@ -97,52 +100,46 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { vars.asset = asset; IERC20 assetERC = IERC20(vars.asset); - if (!p_.data.retain4626) { - uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); - assets = v.redeem(p_.data.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); - if (assetsBalanceAfter - assetsBalanceBefore != assets) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } - if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); - - /// @dev validate and dispatches the tokens - if (vars.len1 != 0) { - vars.bridgeValidator = superRegistry.getBridgeValidator(vars.liqData.bridgeId); - vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(vars.liqData.txData, false); - - /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); - - vars.chainId = CHAIN_ID; - - /// @dev validate and perform the swap to desired output token and send to beneficiary - IBridgeValidator(superRegistry.getBridgeValidator(vars.liqData.bridgeId)).validateTxData( - IBridgeValidator.ValidateTxDataArgs( - vars.liqData.txData, - vars.chainId, - p_.isXChain == 1 ? p_.srcChainId : vars.chainId, - vars.liqData.liqDstChainId, - false, - address(this), - p_.data.receiverAddress, - vars.asset, - address(0) - ) - ); - - _dispatchTokens( - superRegistry.getBridgeAddress(vars.liqData.bridgeId), + uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); + assets = v.redeem(p_.data.amount, vars.receiver, address(this)); + uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); + if (assetsBalanceAfter - assetsBalanceBefore != assets) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + + /// @dev validate and dispatches the tokens + if (vars.len1 != 0) { + vars.bridgeValidator = superRegistry.getBridgeValidator(vars.liqData.bridgeId); + vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(vars.liqData.txData, false); + + /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault + if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + + vars.chainId = CHAIN_ID; + + /// @dev validate and perform the swap to desired output token and send to beneficiary + IBridgeValidator(superRegistry.getBridgeValidator(vars.liqData.bridgeId)).validateTxData( + IBridgeValidator.ValidateTxDataArgs( vars.liqData.txData, + vars.chainId, + p_.isXChain == 1 ? p_.srcChainId : vars.chainId, + vars.liqData.liqDstChainId, + false, + address(this), + p_.data.receiverAddress, vars.asset, - vars.amount, - vars.liqData.nativeAmount - ); - } - } else { - /// @dev transfer shares to user and do not redeem shares for assets - v.safeTransfer(p_.data.receiverAddress, p_.data.amount); - return 0; + address(0) + ) + ); + + _dispatchTokens( + superRegistry.getBridgeAddress(vars.liqData.bridgeId), + vars.liqData.txData, + vars.asset, + vars.amount, + vars.liqData.nativeAmount + ); } } @@ -179,7 +176,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { /// @inheritdoc BaseForm /// @dev this is the step-1 for timelock form withdrawal, direct case - /// @dev will mandatorily process unlock + /// @dev will mandatorily process unlock unless the retain4626 flag is set /// @return shares is always 0 function _directWithdrawFromVault( InitSingleVaultData memory singleVaultData_, @@ -190,16 +187,21 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { override returns (uint256) { - /// @dev after requesting the unlock, the information with the time of full unlock is saved and sent to timelock - /// @dev state registry for re-processing at a later date - _storePayload(0, CHAIN_ID, _requestUnlock(singleVaultData_.amount), singleVaultData_); - + if (!singleVaultData_.retain4626) { + /// @dev after requesting the unlock, the information with the time of full unlock is saved and sent to + /// timelock + /// @dev state registry for re-processing at a later date + _storePayload(0, CHAIN_ID, _requestUnlock(singleVaultData_.amount), singleVaultData_); + } else { + /// @dev transfer shares to user and do not redeem shares for assets + IERC4626TimelockVault(vault).safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); + } return 0; } /// @inheritdoc BaseForm /// @dev this is the step-1 for timelock form withdrawal, xchain case - /// @dev will mandatorily process unlock + /// @dev will mandatorily process unlock unless the retain4626 flag is set /// @return shares is always 0 function _xChainWithdrawFromVault( InitSingleVaultData memory singleVaultData_, @@ -211,9 +213,15 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { override returns (uint256) { - /// @dev after requesting the unlock, the information with the time of full unlock is saved and sent to timelock - /// @dev state registry for re-processing at a later date - _storePayload(1, srcChainId_, _requestUnlock(singleVaultData_.amount), singleVaultData_); + if (!singleVaultData_.retain4626) { + /// @dev after requesting the unlock, the information with the time of full unlock is saved and sent to + /// timelock + /// @dev state registry for re-processing at a later date + _storePayload(1, srcChainId_, _requestUnlock(singleVaultData_.amount), singleVaultData_); + } else { + /// @dev transfer shares to user and do not redeem shares for assets + IERC4626TimelockVault(vault).safeTransfer(singleVaultData_.receiverAddress, singleVaultData_.amount); + } return 0; } diff --git a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol index 4888927cc..e98377cbe 100644 --- a/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/LayerzeroImplementation.t.sol @@ -324,7 +324,10 @@ contract LayerzeroImplementationTest is BaseSetup { (ambMessage, ambExtraData, coreStateRegistry) = _setupBroadcastPayloadAMBData(users[userIndex]); vm.expectRevert(Error.NOT_STATE_REGISTRY.selector); - + vm.assume( + malice_ != getContract(ETH, "CoreStateRegistry") && malice_ != getContract(ETH, "TimelockStateRegistry") + && malice_ != getContract(ETH, "BroadcastRegistry") + ); vm.deal(malice_, 100 ether); vm.prank(malice_); layerzeroImplementation.dispatchPayload{ value: 0.1 ether }( diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index 3bf8a0d59..a2cd0c7e5 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -25,6 +25,16 @@ contract SmartContractWallet is ERC1155Holder { function singleXChainSingleVaultWithdraw(SingleXChainSingleVaultStateReq memory req) external payable { router.singleXChainSingleVaultWithdraw{ value: msg.value }(req); } + + function singleDirectSingleVaultDeposit(SingleDirectSingleVaultStateReq memory req) external payable { + MockERC20(dai).approve(address(router), req.superformData.amount); + + router.singleDirectSingleVaultDeposit{ value: msg.value }(req); + } + + function singleDirectSingleVaultWithdraw(SingleDirectSingleVaultStateReq memory req) external payable { + router.singleDirectSingleVaultWithdraw{ value: msg.value }(req); + } } contract SuperformRouterAATest is ProtocolActions { @@ -124,6 +134,78 @@ contract SuperformRouterAATest is ProtocolActions { _xChainWithdraw_SmartContractWallet(ARBI, address(walletDestinationAVAX), false, "ERC4626TimelockMock", 1, true); } + function test_direct_withdrawWithSmartContractWallet_retain4626() public { + _directDeposit_SmartContractWallet(false, true, "VaultMock", 0); + + _directWithdraw_SmartContractWallet(ARBI, address(walletDestination), false, "VaultMock", 0, true); + } + + function test_direct_withdrawWithSmartContractWallet_timelock_retain4626() public { + _directDeposit_SmartContractWallet(false, true, "ERC4626TimelockMock", 1); + + _directWithdraw_SmartContractWallet(ARBI, address(walletDestination), false, "ERC4626TimelockMock", 1, true); + } + + function _directDeposit_SmartContractWallet( + bool receive4626_, + bool receiveAddress_, + string memory vaultKind, + uint256 formImplId + ) + internal + { + address superform = getContract( + ARBI, string.concat("DAI", vaultKind, "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[formImplId])) + ); + + uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[formImplId], ARBI); + vm.startPrank(deployer); + + vm.selectFork(FORKS[ARBI]); + + SingleVaultSFData memory data = SingleVaultSFData( + superformId, + 1e18, + 10_000, + /// @dev invalid slippage + LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ARBI, 0), + "", + false, + receive4626_, + receiveAddress_ ? address(walletDestination) : address(0), + "" + ); + + SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); + + vm.deal(address(walletDestination), 2 ether); + deal(getContract(ARBI, "DAI"), address(walletDestination), 1e18); + + /// @dev approves before call + MockERC20(getContract(ARBI, "DAI")).approve(address(walletDestination), 1e18); + vm.stopPrank(); + + vm.recordLogs(); + + vm.prank(deployer); + + if (!receiveAddress_) { + vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); + /// @dev msg sender is wallet, tx origin is deployer + walletDestination.singleDirectSingleVaultDeposit{ value: 2 ether }(req); + return; + } + /// @dev msg sender is wallet, tx origin is deployer + walletDestination.singleDirectSingleVaultDeposit{ value: 2 ether }(req); + + if (!receive4626_) { + assertGt( + SuperPositions(getContract(ARBI, "SuperPositions")).balanceOf(address(walletDestination), superformId), + 0 + ); + } + } + function _xChainDeposit_SmartContractWallet( bool receive4626_, bool receiveAddress_, @@ -267,6 +349,88 @@ contract SuperformRouterAATest is ProtocolActions { uint256 superformId; } + function _directWithdraw_SmartContractWallet( + uint64 liqDstChainId_, + address scWalletAtLiqDst_, + bool sameChainTxData_, + string memory vaultKind, + uint256 formImplId, + bool receive4626_ + ) + internal + { + /// scenario: user deposits with his own collateral and has approved enough tokens + vm.selectFork(FORKS[ARBI]); + XChainWithdrawsInternalVars memory v; + v.superform = getContract( + ARBI, string.concat("DAI", vaultKind, "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[formImplId])) + ); + + v.superformId = DataLib.packSuperform(v.superform, FORM_IMPLEMENTATION_IDS[formImplId], ARBI); + + SingleVaultSFData memory data = SingleVaultSFData( + v.superformId, + 1e18, + 1000, + LiqRequest( + _buildLiqBridgeTxData( + LiqBridgeTxDataArgs( + 1, + getContract(ARBI, "DAI"), + getContract(ARBI, "DAI"), + getContract(liqDstChainId_, "DAI"), + v.superform, + ARBI, + ARBI, + liqDstChainId_, + false, + scWalletAtLiqDst_, + uint256(liqDstChainId_), + 1e18, + true, + /// @dev placeholder value, not used + 0, + 1, + 1, + 1 + ), + sameChainTxData_ + ), + getContract(ARBI, "DAI"), + address(0), + 1, + liqDstChainId_, + 0 + ), + "", + false, + receive4626_, + liqDstChainId_ != ETH ? scWalletAtLiqDst_ : address(walletDestination), + "" + ); + + console.log("receiverAddress", data.receiverAddress); + + SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); + + /// @dev approves before call + vm.prank(address(walletDestination)); + SuperPositions(getContract(ARBI, "SuperPositions")).increaseAllowance( + getContract(ARBI, "SuperformRouter"), v.superformId, 1e18 + ); + vm.recordLogs(); + + vm.prank(deployer); + vm.deal(deployer, 2 ether); + walletDestination.singleDirectSingleVaultWithdraw{ value: 2 ether }(req); + + if (receive4626_) { + console.log("scWalletAtLiqDst_", scWalletAtLiqDst_); + + assertGt(IERC4626(IBaseForm(v.superform).getVaultAddress()).balanceOf(scWalletAtLiqDst_), 0); + } + } + function _xChainWithdraw_SmartContractWallet( uint64 liqDstChainId_, address scWalletAtLiqDst_, @@ -367,7 +531,7 @@ contract SuperformRouterAATest is ProtocolActions { vm.prank(deployer); CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).processPayload(2); - if (formImplId == 1) { + if (formImplId == 1 && !receive4626_) { vm.warp(block.timestamp + (86_400 * 5)); vm.prank(deployer); From 24f91f30f2e349aacaeded3ac432baa1cab7a638 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 12:26:24 -0600 Subject: [PATCH 138/210] chore: fix comparison --- src/crosschain-liquidity/DstSwapper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index e4faa95d8..74bc150a1 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -176,7 +176,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { { uint256 len = txData_.length; if (len == 0) revert Error.ZERO_INPUT_VALUE(); - if (len != bridgeIds_.length && len != txData_.length) revert Error.ARRAY_LENGTH_MISMATCH(); + if (len != indices_.length && len != bridgeIds_.length) revert Error.ARRAY_LENGTH_MISMATCH(); IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); _isValidPayloadId(payloadId_, coreStateRegistry); From 0038b26d873d8aecc0cc09a7486a2a587b0bdcce Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 20:50:25 -0600 Subject: [PATCH 139/210] chore: slippage checks on deposit and redeem --- src/forms/ERC4626FormImplementation.sol | 20 ++++++++++++++++---- src/forms/ERC4626TimelockForm.sol | 6 +++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index f72fdcbde..1f67b2a58 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -242,9 +242,12 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); + uint256 sharesExpected = v.convertToShares(vars.assetDifference); shares = v.deposit(vars.assetDifference, sharesReceiver); uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); - if (sharesBalanceAfter - sharesBalanceBefore != shares) { + if ((sharesBalanceAfter - sharesBalanceBefore != shares) || + (shares < ((sharesExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } } @@ -274,9 +277,12 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); + uint256 sharesExpected = v.convertToShares(singleVaultData_.amount); shares = v.deposit(singleVaultData_.amount, sharesReceiver); uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); - if (sharesBalanceAfter - sharesBalanceBefore != shares) { + if ((sharesBalanceAfter - sharesBalanceBefore != shares) || + (shares < ((sharesExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -299,9 +305,12 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); + uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); - if (assetsBalanceAfter - assetsBalanceBefore != assets) { + if ((assetsBalanceAfter - assetsBalanceBefore != assets) || + (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -379,9 +388,12 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); + uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); - if (assetsBalanceAfter - assetsBalanceBefore != assets) { + if ((assetsBalanceAfter - assetsBalanceBefore != assets) || + (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index e121d9218..303f87be3 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -25,6 +25,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { ////////////////////////////////////////////////////////////// uint8 constant stateRegistryId = 2; // TimelockStateRegistry + uint256 private constant ENTIRE_SLIPPAGE = 10_000; ////////////////////////////////////////////////////////////// // STRUCTS // @@ -100,9 +101,12 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { IERC20 assetERC = IERC20(vars.asset); uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); + uint256 assetsExpected = v.convertToAssets(p_.data.amount); assets = v.redeem(p_.data.amount, vars.receiver, address(this)); uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); - if (assetsBalanceAfter - assetsBalanceBefore != assets) { + if ((assetsBalanceAfter - assetsBalanceBefore != assets) || + (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - p_.data.maxSlippage)) / ENTIRE_SLIPPAGE)) + ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); From caf2efd1b48ac1e73e3c0721e7f3de5b6f4b3f3c Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 22:46:36 -0600 Subject: [PATCH 140/210] chore: SUP-4947 --- src/BaseRouterImplementation.sol | 12 ++++++------ src/payments/PaymentHelper.sol | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 43f4194bc..2e0c4cc70 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -289,10 +289,10 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev this loop is what allows to deposit to >1 different underlying on destination /// @dev if a loop fails in a validation the whole chain should be reverted - for (uint256 j; j < len; ++j) { - vars.liqRequest = req_.superformsData.liqRequests[j]; + for (uint256 i; i < len; ++i) { + vars.liqRequest = req_.superformsData.liqRequests[i]; - (superform,,) = req_.superformsData.superformIds[j].getSuperform(); + (superform,,) = req_.superformsData.superformIds[i].getSuperform(); /// @dev dispatch liquidity data if ( @@ -301,7 +301,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.liqRequest, superform, vars.srcChainId, req_.dstChainId, msg.sender, true ) ) - ) ambData.liqData[j].interimToken = vars.liqRequest.interimToken; + ) ambData.liqData[i].interimToken = vars.liqRequest.interimToken; } /// @dev dispatch message information, notice multiVaults is set to 1 @@ -1126,9 +1126,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev approves individual final targets if needed here v.targetLen = targets_.length; - for (uint256 j; j < v.targetLen; ++j) { + for (uint256 i; i < v.targetLen; ++i) { /// @dev approves the superform - v.token.safeIncreaseAllowance(targets_[j], v.amountsIn[j]); + v.token.safeIncreaseAllowance(targets_[i], v.amountsIn[i]); } } diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 18350c13e..2b060232c 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -304,8 +304,8 @@ contract PaymentHelper is IPaymentHelper { uint256 arrLen = req_.superformsData.retain4626s.length; uint256 ackLen; - for (uint256 j; j < arrLen; ++j) { - if (!req_.superformsData.retain4626s[j]) ++ackLen; + for (uint256 i; i < arrLen; ++i) { + if (!req_.superformsData.retain4626s[i]) ++ackLen; } /// @dev step 3: estimation execution cost of acknowledgement From fe797d3d7dc21b5a8cc6a74637cb60788be1f00e Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 22:49:41 -0600 Subject: [PATCH 141/210] chore: SUP-4831 --- src/crosschain-liquidity/socket/SocketOneInchValidator.sol | 2 +- src/crosschain-liquidity/socket/SocketValidator.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index eb019600f..da39be389 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -44,7 +44,7 @@ contract SocketOneInchValidator is BridgeValidator { if (decodedReq.receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } - /// @dev FIXME: add 3. token validations + /// @dev 3. token validations if (args_.liqDataToken != decodedReq.fromToken) revert Error.INVALID_TXDATA_TOKEN(); return false; diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index 118bd5c5c..57ac8aa1b 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -67,7 +67,7 @@ contract SocketValidator is BridgeValidator { if (decodedReq.receiverAddress != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); } - /// @dev FIXME: add 3. token validations + /// @dev token validations if ( (decodedReq.middlewareRequest.id == 0 && args_.liqDataToken != decodedReq.bridgeRequest.inputToken) || (decodedReq.middlewareRequest.id != 0 && args_.liqDataToken != decodedReq.middlewareRequest.inputToken) From ffc6b621d41186f2ef0dff19d19daf6b067aa212 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 22:52:24 -0600 Subject: [PATCH 142/210] chore: SUP-4928 --- src/crosschain-liquidity/BridgeValidator.sol | 2 +- src/crosschain-liquidity/LiquidityHandler.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/crosschain-liquidity/BridgeValidator.sol b/src/crosschain-liquidity/BridgeValidator.sol index 00dac7efe..1d1c9862c 100644 --- a/src/crosschain-liquidity/BridgeValidator.sol +++ b/src/crosschain-liquidity/BridgeValidator.sol @@ -12,7 +12,7 @@ abstract contract BridgeValidator is IBridgeValidator { // CONSTANTS // ////////////////////////////////////////////////////////////// ISuperRegistry public immutable superRegistry; - address constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address immutable NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index c6478b29e..6f4f5fee8 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -15,10 +15,10 @@ abstract contract LiquidityHandler { using SafeERC20 for IERC20; ////////////////////////////////////////////////////////////// - // CONSTANTS // + // CONSTANTS // ////////////////////////////////////////////////////////////// - address constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address immutable NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; ////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS // From f79b5739eea9f19e843eb05512bffdf91ac1bf0a Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:07:41 -0600 Subject: [PATCH 143/210] chore: SUP-4926 --- .../adapters/hyperlane/HyperlaneImplementation.sol | 2 ++ src/interfaces/ISuperPositions.sol | 1 + src/interfaces/ISuperRBAC.sol | 10 ++++++++++ src/settings/SuperRBAC.sol | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index 9a9a6e554..8a732db15 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -201,6 +201,8 @@ contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { } authorizedImpl[domain_] = authorizedImpl_; + + emit AuthorizedImplAdded(domain_, authorizedImpl_); } /// @inheritdoc IMessageRecipient diff --git a/src/interfaces/ISuperPositions.sol b/src/interfaces/ISuperPositions.sol index 460449041..65c736dfc 100644 --- a/src/interfaces/ISuperPositions.sol +++ b/src/interfaces/ISuperPositions.sol @@ -16,6 +16,7 @@ interface ISuperPositions is IERC1155A { uint256 txInfo; address receiverAddressSP; } + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ISuperRBAC.sol b/src/interfaces/ISuperRBAC.sol index c14785dff..5aca2d92b 100644 --- a/src/interfaces/ISuperRBAC.sol +++ b/src/interfaces/ISuperRBAC.sol @@ -25,6 +25,16 @@ interface ISuperRBAC is IAccessControl { address csrDisputer; } + ////////////////////////////////////////////////////////////// + // EVENTS // + ////////////////////////////////////////////////////////////// + + /// @dev is emitted when superRegistry is set + event SuperRegistrySet(address indexed superRegistry); + + /// @dev is emitted when an admin is set for a role + event RoleAdminSet(bytes32 role, bytes32 adminRole); + ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 9e96139fc..580b20f62 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -147,11 +147,15 @@ contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { if (superRegistry_ == address(0)) revert Error.ZERO_ADDRESS(); superRegistry = ISuperRegistry(superRegistry_); + + emit SuperRegistrySet(superRegistry_); } /// @inheritdoc ISuperRBAC function setRoleAdmin(bytes32 role_, bytes32 adminRole_) external override onlyRole(PROTOCOL_ADMIN_ROLE) { _setRoleAdmin(role_, adminRole_); + + emit RoleAdminSet(role_, adminRole_); } /// @inheritdoc ISuperRBAC From 3ed383b3ce7184e2e17e773ac8e03cfb238ade26 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:14:30 -0600 Subject: [PATCH 144/210] chore: fix license --- src/settings/SuperRBAC.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 580b20f62..22c89e021 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -1,4 +1,4 @@ -//SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol"; From 8431cb7284d788ce18a39ca857180b63ab929ef8 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:17:58 -0600 Subject: [PATCH 145/210] chore: SUP-4923,SUP-4932 --- src/crosschain-data/utils/PayloadHelper.sol | 4 ---- src/crosschain-liquidity/lifi/LiFiValidator.sol | 1 - 2 files changed, 5 deletions(-) diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 54e84b3a8..819673f92 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -393,8 +393,6 @@ contract PayloadHelper is IPayloadHelper { nativeAmounts[i] = imvd.liqData[i].nativeAmount; } - - return (bridgeIds, txDatas, tokens, interimTokens, liqDstChainIds, amountsIn, nativeAmounts); } function _decodeSingleLiqData( @@ -441,7 +439,5 @@ contract PayloadHelper is IPayloadHelper { nativeAmounts = new uint256[](1); nativeAmounts[0] = isvd.liqData.nativeAmount; - - return (bridgeIds, txDatas, tokens, interimTokens, liqDstChainIds, amountsIn, nativeAmounts); } } diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index fe23caea3..1dbec98ab 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -257,6 +257,5 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { sendingAssetId = swapData[0].sendingAssetId; amount = swapData[0].fromAmount; receivingAssetId = swapData[swapData.length - 1].receivingAssetId; - return (sendingAssetId, amount, receiver, receivingAssetId, receivingAmount); } } From 9e357f545b15106af22fc6cf9f25c7b89db8f18a Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:31:40 -0600 Subject: [PATCH 146/210] chore: SUP-4927 --- src/crosschain-data/extensions/CoreStateRegistry.sol | 3 ++- src/interfaces/ICoreStateRegistry.sol | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index d22a8b4a2..1e4a31164 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -77,7 +77,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { lastProposedTime = failedDeposit.lastProposedTimestamp; } - /// @dev used for try catching purposes + /// @inheritdoc ICoreStateRegistry function validateSlippage(uint256 finalAmount_, uint256 amount_, uint256 maxSlippage_) public view returns (bool) { // only internal transaction if (msg.sender != address(this)) { @@ -86,6 +86,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { return PayloadUpdaterLib.validateSlippage(finalAmount_, amount_, maxSlippage_); } + ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ICoreStateRegistry.sol b/src/interfaces/ICoreStateRegistry.sol index 4d2767fcf..119706f34 100644 --- a/src/interfaces/ICoreStateRegistry.sol +++ b/src/interfaces/ICoreStateRegistry.sol @@ -59,6 +59,15 @@ interface ICoreStateRegistry { view returns (uint256[] memory superformIds, uint256[] memory amounts, uint256 lastProposedTime); + /// @dev used internally for try/catching + /// @param finalAmount_ is the final amount of tokens received + /// @param amount_ is the indicated amount of tokens to be received + /// @param maxSlippage_ is the amount of acceptable slippage for the transaction + function validateSlippage(uint256 finalAmount_, uint256 amount_, uint256 maxSlippage_) + external + view + returns (bool); + ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// From 0eed7ba1398a2e3f733d80d2ae2093f3f5935c74 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:33:36 -0600 Subject: [PATCH 147/210] chore: SUP-4935 --- src/forms/ERC4626FormImplementation.sol | 12 ++++++------ src/forms/ERC4626TimelockForm.sol | 4 ++-- .../ERC4626ImplementationInterfaceNotSupported.sol | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index f72fdcbde..848d31808 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -30,7 +30,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { // STRUCTS // ////////////////////////////////////////////////////////////// - struct directDepositLocalVars { + struct DirectDepositLocalVars { uint64 chainId; address asset; address bridgeValidator; @@ -43,7 +43,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { bytes signature; } - struct directWithdrawLocalVars { + struct DirectWithdrawLocalVars { uint64 chainId; address asset; address receiver; @@ -52,7 +52,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { uint256 amount; } - struct xChainWithdrawLocalVars { + struct XChainWithdrawLocalVars { uint64 dstChainId; address receiver; address asset; @@ -154,7 +154,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ////////////////////////////////////////////////////////////// function _processDirectDeposit(InitSingleVaultData memory singleVaultData_) internal returns (uint256 shares) { - directDepositLocalVars memory vars; + DirectDepositLocalVars memory vars; IERC4626 v = IERC4626(vault); vars.asset = address(asset); @@ -284,7 +284,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { } function _processDirectWithdraw(InitSingleVaultData memory singleVaultData_) internal returns (uint256 assets) { - directWithdrawLocalVars memory vars; + DirectWithdrawLocalVars memory vars; vars.len1 = singleVaultData_.liqData.txData.length; /// @dev if there is no txData, on withdraws the receiver is receiverAddress, otherwise it @@ -354,7 +354,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { internal returns (uint256 assets) { - xChainWithdrawLocalVars memory vars; + XChainWithdrawLocalVars memory vars; uint256 len = singleVaultData_.liqData.txData.length; /// @dev a case where the withdraw req liqData has a valid token and tx data is not updated by the keeper diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index e121d9218..24b44c01b 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -30,7 +30,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { // STRUCTS // ////////////////////////////////////////////////////////////// - struct withdrawAfterCoolDownLocalVars { + struct WithdrawAfterCoolDownLocalVars { uint256 len1; address bridgeValidator; uint64 chainId; @@ -78,7 +78,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { return 0; } - withdrawAfterCoolDownLocalVars memory vars; + WithdrawAfterCoolDownLocalVars memory vars; IERC4626TimelockVault v = IERC4626TimelockVault(vault); diff --git a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol index 4d01f6283..d532826ec 100644 --- a/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol +++ b/test/mocks/InterfaceNotSupported/ERC4626ImplementationInterfaceNotSupported.sol @@ -97,7 +97,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li //////////////////////////////////////////////////////////////*/ /// @dev to avoid stack too deep errors - struct directDepositLocalVars { + struct DirectDepositLocalVars { uint64 chainId; address asset; address bridgeValidator; @@ -110,7 +110,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li } function _processDirectDeposit(InitSingleVaultData memory singleVaultData_) internal returns (uint256 shares) { - directDepositLocalVars memory vars; + DirectDepositLocalVars memory vars; IERC4626 v = IERC4626(vault); vars.asset = address(v.asset()); @@ -263,7 +263,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li emit Processed(srcChainId, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); } - struct xChainWithdrawLocalVars { + struct XChainWithdrawLocalVars { uint64 dstChainId; address receiver; address asset; @@ -288,7 +288,7 @@ abstract contract ERC4626FormImplementationInterfaceNotSupported is BaseForm, Li revert Error.WITHDRAW_TX_DATA_NOT_UPDATED(); } - xChainWithdrawLocalVars memory vars; + XChainWithdrawLocalVars memory vars; (,, vars.dstChainId) = singleVaultData_.superformId.getSuperform(); /// @dev if there is no txData, on withdraws the receiver is the original beneficiary (srcSender), otherwise it From 4c4a82853c65c3d0aa7e5eb5f5eb51b009c5539f Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 11:40:52 +0530 Subject: [PATCH 148/210] feat: add withdraw tx data slippage protections --- src/forms/ERC4626FormImplementation.sol | 31 ++++++++++++++++--- src/forms/ERC4626TimelockForm.sol | 5 ++- .../superform-form.ERC4626Timelock.t.sol | 2 +- .../superform-form.forwardDust.t.sol | 5 ++- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 19d4898f3..28989f504 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -24,7 +24,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ////////////////////////////////////////////////////////////// uint8 internal immutable STATE_REGISTRY_ID; - uint256 private constant ENTIRE_SLIPPAGE = 10_000; + uint256 internal constant ENTIRE_SLIPPAGE = 10_000; ////////////////////////////////////////////////////////////// // STRUCTS // @@ -296,7 +296,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); + uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); if (assetsBalanceAfter - assetsBalanceBefore != assets) { @@ -307,10 +307,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { if (vars.len1 != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); + /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault + /// @dev if less it should be within the slippage limit specified by the user vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); - /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) { + revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + } vars.chainId = CHAIN_ID; @@ -383,7 +386,10 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > assets) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); + /// @dev if less it should be within the slippage limit specified by the user + if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) { + revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); + } /// @dev validate and perform the swap to desired output token and send to beneficiary IBridgeValidator(vars.bridgeValidator).validateTxData( @@ -412,6 +418,21 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit Processed(srcChainId_, vars.dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vault); } + function _isWithdrawTxDataAmountInvalid( + uint256 bridgeDecodedAmount_, + uint256 redeemedAmount_, + uint256 slippage_ + ) + internal + pure + returns (bool isInvalid_) + { + if ( + bridgeDecodedAmount_ > redeemedAmount_ + || bridgeDecodedAmount_ < ((redeemedAmount_ * (ENTIRE_SLIPPAGE - slippage_)) / ENTIRE_SLIPPAGE) + ) return true; + } + function _processEmergencyWithdraw(address receiverAddress_, uint256 amount_) internal { IERC4626 vaultContract = IERC4626(vault); diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 0bd3ca4d1..74973837f 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -110,7 +110,10 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(vars.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault - if (vars.amount > assets) revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, p_.data.maxSlippage)) { + if (p_.isXChain == 1) revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); + revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); + } vars.chainId = CHAIN_ID; diff --git a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol index 6f6d9323b..96e7b5e52 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol @@ -191,7 +191,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { vm.prank(getContract(ETH, "CoreStateRegistry")); IBaseForm(superform).xChainWithdrawFromVault(data, deployer, ARBI); - vm.expectRevert(Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST.selector); + vm.expectRevert(Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST.selector); vm.prank(getContract(ETH, "TimelockStateRegistry")); ERC4626TimelockForm(payable(superform)).withdrawAfterCoolDown( TimelockPayload(1, ETH, block.timestamp, data, TimelockStatus.PENDING) diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index 2384d6259..e8ddd3ef4 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -119,8 +119,8 @@ contract ForwardDustFormTest is ProtocolActions { superform, ARBI, ETH, - nasty_ ? 0.2e18 : IBaseForm(superform).previewRedeemFrom(superPositionBalance), // nastiness - // here + nasty_ ? 0.99e18 : IBaseForm(superform).previewRedeemFrom(superPositionBalance), // nastiness + // here within slippage limit refundAddress, false ) @@ -140,7 +140,6 @@ contract ForwardDustFormTest is ProtocolActions { if (formImplementationId_ != 1) { vm.prank(getContract(ARBI, "CoreStateRegistry")); - IBaseForm(superform).xChainWithdrawFromVault(data2, user, ETH); } else { vm.prank(getContract(ARBI, "TimelockStateRegistry")); From 8dce010eb4d8c93de49ed585e49e7635539060c4 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 11:46:55 +0530 Subject: [PATCH 149/210] chore: merge develop --- test/unit/superform-forms/superform-form.forwardDust.t.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index 99d0a2c08..c7c8071a9 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -136,15 +136,9 @@ contract ForwardDustFormTest is ProtocolActions { superform, ARBI, ETH, -<<<<<<< HEAD nasty_ ? 0.99e18 : IBaseForm(superform).previewRedeemFrom(superPositionBalance), // nastiness // here within slippage limit refundAddress, -======= - nasty_ ? 0.2e18 : IBaseForm(superform).previewRedeemFrom(superPositionBalance), // nastiness - // here - receiverAddress, ->>>>>>> origin/develop false ) ), From 106d7b0c09fdd8ecdf3421b39017c22ea8b35408 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 11:53:46 +0530 Subject: [PATCH 150/210] fix: tests after merging with develop --- test/unit/superform-forms/superform-form.forwardDust.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index c7c8071a9..da92a5d79 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -137,8 +137,8 @@ contract ForwardDustFormTest is ProtocolActions { ARBI, ETH, nasty_ ? 0.99e18 : IBaseForm(superform).previewRedeemFrom(superPositionBalance), // nastiness - // here within slippage limit - refundAddress, + // here + receiverAddress, false ) ), From fdeb5503894e7cc819e52794ec8648277e4e708c Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 14:06:12 +0530 Subject: [PATCH 151/210] fix: gas opt to addRemoteChain and updateRemoteChain --- src/payments/PaymentHelper.sol | 36 +++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 988b4f771..9dd1d529d 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -534,19 +534,21 @@ contract PaymentHelper is IPaymentHelper { onlyProtocolAdmin { if (config_.nativeFeedOracle != address(0)) { - nativeFeedOracle[chainId_] = AggregatorV3Interface(config_.nativeFeedOracle); - - if (nativeFeedOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION) { + AggregatorV3Interface nativeFeedOracleContract = AggregatorV3Interface(config_.nativeFeedOracle); + if (nativeFeedOracleContract.decimals() != SUPPORTED_FEED_PRECISION) { revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); } + + nativeFeedOracle[chainId_] = nativeFeedOracleContract; } if (config_.gasPriceOracle != address(0)) { - gasPriceOracle[chainId_] = AggregatorV3Interface(config_.gasPriceOracle); - - if (gasPriceOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION) { + AggregatorV3Interface gasPriceOracleContract = AggregatorV3Interface(config_.nativeFeedOracle); + if (gasPriceOracleContract.decimals() != SUPPORTED_FEED_PRECISION) { revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); } + + gasPriceOracle[chainId_] = gasPriceOracleContract; } swapGasUsed[chainId_] = config_.swapGasUsed; @@ -575,26 +577,28 @@ contract PaymentHelper is IPaymentHelper { { /// @dev Type 1: DST TOKEN PRICE FEED ORACLE if (configType_ == 1) { - address nativeFeedOracleAddress = abi.decode(config_, (address)); - nativeFeedOracle[chainId_] = AggregatorV3Interface(nativeFeedOracleAddress); - + AggregatorV3Interface nativeFeedOracleContract = AggregatorV3Interface(abi.decode(config_, (address))); if ( - nativeFeedOracleAddress != address(0) - && nativeFeedOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION + address(nativeFeedOracleContract) != address(0) + && nativeFeedOracleContract.decimals() != SUPPORTED_FEED_PRECISION ) { revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); } + + nativeFeedOracle[chainId_] = nativeFeedOracleContract; } /// @dev Type 2: DST GAS PRICE ORACLE if (configType_ == 2) { - address gasPriceOracleAddress = abi.decode(config_, (address)); - gasPriceOracle[chainId_] = AggregatorV3Interface(gasPriceOracleAddress); - - if (gasPriceOracleAddress != address(0) && gasPriceOracle[chainId_].decimals() != SUPPORTED_FEED_PRECISION) - { + AggregatorV3Interface gasPriceOracleContract = AggregatorV3Interface(abi.decode(config_, (address))); + if ( + address(gasPriceOracleContract) != address(0) + && gasPriceOracleContract.decimals() != SUPPORTED_FEED_PRECISION + ) { revert Error.CHAINLINK_UNSUPPORTED_DECIMAL(); } + + gasPriceOracle[chainId_] = gasPriceOracleContract; } /// @dev Type 3: SWAP GAS USED From 6d9463df19a86a56668cd99639f602c03906f4ef Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 14:09:14 +0530 Subject: [PATCH 152/210] chore: remove duplicate error message --- src/libraries/Error.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index b9e2fcf1b..934703d79 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -416,9 +416,6 @@ library Error { /// @dev thrown if withdrawal tx data is not updated error WITHDRAW_TX_DATA_NOT_UPDATED(); - /// @dev thrown when redeeming from vault yields zero collateral - error WITHDRAW_ZERO_COLLATERAL(); - /// PAYMENT HELPER EXECUTION ERRORS /// @dev thrown if chainlink is reporting an improper price error CHAINLINK_MALFUNCTION(); From 83d859bbc42a6c561d3367389ccbd83498e3e7d1 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 14:11:15 +0530 Subject: [PATCH 153/210] chore: optimize broadcast refunds --- src/crosschain-data/BroadcastRegistry.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/crosschain-data/BroadcastRegistry.sol b/src/crosschain-data/BroadcastRegistry.sol index 37be9b48e..08feada89 100644 --- a/src/crosschain-data/BroadcastRegistry.sol +++ b/src/crosschain-data/BroadcastRegistry.sol @@ -101,9 +101,8 @@ contract BroadcastRegistry is IBroadcastRegistry { _broadcastPayload(srcSender_, ambId_, gasFee_, message_, extraData_); /// @dev refunds any overpaid msg.value - uint256 refundAmt = msg.value - gasFee_; - if (refundAmt > 0) { - (bool success,) = payable(srcSender_).call{ value: refundAmt }(""); + if (msg.value > gasFee_) { + (bool success,) = payable(srcSender_).call{ value: msg.value - gasFee_ }(""); if (!success) { revert Error.FAILED_TO_SEND_NATIVE(); From 65523fd9e12251acf36bcb9350e798c32d23d077 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 14:44:32 +0530 Subject: [PATCH 154/210] chore: fix gerard suggestions --- src/SuperPositions.sol | 10 +++++----- src/SuperformFactory.sol | 10 ++++++++-- src/libraries/Error.sol | 3 +++ .../unit/super-positions/super-positions.t.sol | 18 +++++++++++++++++- test/utils/BaseSetup.sol | 2 +- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index de2735f27..875b3f333 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -30,6 +30,8 @@ contract SuperPositions is ISuperPositions, ERC1155A { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// + uint8 internal constant CORE_STATE_REGISTRY_ID = 1; + ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; bytes32 constant DEPLOY_NEW_AERC20 = keccak256("DEPLOY_NEW_AERC20"); @@ -325,14 +327,12 @@ contract SuperPositions is ISuperPositions, ERC1155A { } function _isValidStateSyncer(uint8 registryId_, uint256 superformId_) internal view { - /// @dev Directly check if the registryId is 0 or doesn't match the allowed cases. - if (registryId_ == 0) { - revert Error.NOT_MINTER_STATE_REGISTRY_ROLE(); - } + /// @dev registryId_ zero check is done in superRegistry.getStateRegistryId() + /// @dev If registryId is 1, meaning CoreStateRegistry, no further checks are necessary. /// @dev This is because CoreStateRegistry is the default minter for all kinds of forms /// @dev In case registryId is > 1, we need to check if the registryId matches the formImplementationId - if (registryId_ == 1) { + if (registryId_ == CORE_STATE_REGISTRY_ID) { return; } diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 26a691850..751fdbc1f 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -120,8 +120,14 @@ contract SuperformFactory is ISuperformFactory { } /// @inheritdoc ISuperformFactory - function getFormStateRegistryId(uint32 formImplementationId_) external view override returns (uint8) { - return formStateRegistryId[formImplementationId_]; + function getFormStateRegistryId(uint32 formImplementationId_) + external + view + override + returns (uint8 formStateRegistryId_) + { + formStateRegistryId_ = formStateRegistryId[formImplementationId_]; + if (formStateRegistryId_ == 0) revert Error.INVALID_FORM_REGISTRY_ID(); } /// @inheritdoc ISuperformFactory diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 497f01249..21d016f94 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -362,6 +362,9 @@ library Error { /// @dev thrown if a state registry id is 0 error INVALID_REGISTRY_ID(); + /// @dev thrown if a form state registry id is 0 + error INVALID_FORM_REGISTRY_ID(); + /*/////////////////////////////////////////////////////////////// PAYMASTER ERRORS //////////////////////////////////////////////////////////////*/ diff --git a/test/unit/super-positions/super-positions.t.sol b/test/unit/super-positions/super-positions.t.sol index 0f2588dd4..1dc3508ce 100644 --- a/test/unit/super-positions/super-positions.t.sol +++ b/test/unit/super-positions/super-positions.t.sol @@ -99,6 +99,22 @@ contract SuperPositionsTest is BaseSetup { } function test_revert_stateSync_NotMinterStateRegistry_InvalidRegistryId() public { + uint256 txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0), ETH); + address superform = getContract( + ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[2])) + ); + + uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[2], ETH); + + ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, superformId, 100); + AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); + + vm.broadcast(getContract(ETH, "TimelockStateRegistry")); + vm.expectRevert(Error.NOT_MINTER_STATE_REGISTRY_ROLE.selector); + superPositions.stateSync(maliciousMessage); + } + + function test_revert_stateSync_InvalidFormRegistryId() public { uint256 txInfo = DataLib.packTxInfo(0, 2, 0, 1, address(0), ETH); address superform = getContract( ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) @@ -110,7 +126,7 @@ contract SuperPositionsTest is BaseSetup { AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); vm.broadcast(getContract(ETH, "TimelockStateRegistry")); - vm.expectRevert(Error.NOT_MINTER_STATE_REGISTRY_ROLE.selector); + vm.expectRevert(Error.INVALID_FORM_REGISTRY_ID.selector); superPositions.stateSync(maliciousMessage); } diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index a64274583..550cdcdb0 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -637,7 +637,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1], 2 ); - ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 0); + ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 1); /// @dev 12 - Deploy SuperformRouter vars.superformRouter = address(new SuperformRouter{ salt: salt }(vars.superRegistry)); From 0aed5bed625c79456e81aec92d57119f5771d145 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 15:07:24 +0530 Subject: [PATCH 155/210] chore: disallow adding for form state registry id --- script/Abstract.Deploy.Single.s.sol | 4 ++-- src/SuperformFactory.sol | 11 ++++++--- .../super-positions/super-positions.t.sol | 5 ++-- .../superform-factory.addImplementation.sol | 22 +++++++++++++---- ...erform-factory.changeFormPauseStatus.t.sol | 8 +++---- .../superform-factory.createSuperforms.t.sol | 8 +++---- .../superform-form.ERC4626Form.t.sol | 24 +++++++++---------- test/utils/BaseSetup.sol | 2 +- 8 files changed, 52 insertions(+), 32 deletions(-) diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index 6a259a899..669355a1a 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -486,12 +486,12 @@ abstract contract AbstractDeploySingle is Script { contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; /// @dev 9 - Add newly deployed form implementations to Factory, formImplementationId 1 - ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0], 0); + ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0], 1); /// passing 2 cuz timelock state registry id is 2 ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1], 2); - ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 0); + ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 1); /// @dev 10 - Deploy SuperformRouter vars.superformRouter = address(new SuperformRouter{ salt: salt }(vars.superRegistry)); diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 751fdbc1f..a97e77ef6 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -192,11 +192,16 @@ contract SuperformFactory is ISuperformFactory { formImplementation[formImplementationId_] = formImplementation_; formImplementationIds[formImplementation_] = formImplementationId_; - /// @dev formStateRegistryId can also be zero if the form requires no additional state registry - if (formStateRegistryId_ != 0) { - formStateRegistryId[formImplementationId_] = formStateRegistryId_; + /// @dev set CoreStateRegistry if the form implementation needs no special state registry + /// @dev if the form needs any special state registry, set this value to the id of the special state registry + /// and core state registry can be used by default. + /// @dev if this value is != 1, then the form supports two state registries (CoreStateRegistry + its special + /// state registry) + if (formStateRegistryId_ == 0) { + revert Error.INVALID_FORM_REGISTRY_ID(); } + formStateRegistryId[formImplementationId_] = formStateRegistryId_; formImplementations.push(formImplementation_); emit FormImplementationAdded(formImplementation_, formImplementationId_, formStateRegistryId_); diff --git a/test/unit/super-positions/super-positions.t.sol b/test/unit/super-positions/super-positions.t.sol index 1dc3508ce..79e123039 100644 --- a/test/unit/super-positions/super-positions.t.sol +++ b/test/unit/super-positions/super-positions.t.sol @@ -30,7 +30,7 @@ contract SuperPositionsTest is BaseSetup { vault = getContract(ETH, VAULT_NAMES[0][0]); vm.prank(deployer); SuperformFactory(getContract(ETH, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); } @@ -120,7 +120,8 @@ contract SuperPositionsTest is BaseSetup { ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) ); - uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); + /// non existent form implementation id so the get form state registry id returns 0 + uint256 superformId = DataLib.packSuperform(superform, 5, ETH); ReturnSingleData memory maliciousReturnData = ReturnSingleData(0, superformId, 100); AMBMessage memory maliciousMessage = AMBMessage(txInfo, abi.encode(maliciousReturnData)); diff --git a/test/unit/superform-factory/superform-factory.addImplementation.sol b/test/unit/superform-factory/superform-factory.addImplementation.sol index b4513c935..807164f1f 100644 --- a/test/unit/superform-factory/superform-factory.addImplementation.sol +++ b/test/unit/superform-factory/superform-factory.addImplementation.sol @@ -30,7 +30,21 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { vm.startPrank(deployer); /// @dev Event With Implementation vm.expectEmit(true, true, true, true); - emit FormImplementationAdded(formImplementation, formImplementationId, 0); + emit FormImplementationAdded(formImplementation, formImplementationId, 1); + SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( + formImplementation, formImplementationId, 1 + ); + } + + /// testing adding form implementation with state registry id 0 + function test_revert_addForm_InvalidFormStateRegistryId() public { + vm.selectFork(FORKS[chainId]); + + address formImplementation = address(new ERC4626Form(getContract(chainId, "SuperRegistry"))); + uint32 formImplementationId = 44; + + vm.startPrank(deployer); + vm.expectRevert(Error.INVALID_FORM_REGISTRY_ID.selector); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( formImplementation, formImplementationId, 0 ); @@ -47,18 +61,18 @@ contract SuperformFactoryAddImplementationTest is BaseSetup { vm.startPrank(deployer); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId, 0 + formImplementation1, formImplementationId, 1 ); address imp = SuperformFactory(getContract(chainId, "SuperformFactory")).getFormImplementation(formImplementationId); assertEq(imp, formImplementation1); vm.expectRevert(Error.FORM_IMPLEMENTATION_ALREADY_EXISTS.selector); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation2, formImplementationId, 0 + formImplementation2, formImplementationId, 1 ); vm.expectRevert(Error.FORM_IMPLEMENTATION_ID_ALREADY_EXISTS.selector); - SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(formImplementation1, 555, 0); + SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation(formImplementation1, 555, 1); } /// @dev Testing adding form with form address 0 diff --git a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol index 83a3620be..702867f2c 100644 --- a/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol +++ b/test/unit/superform-factory/superform-factory.changeFormPauseStatus.t.sol @@ -28,7 +28,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId, 0 + formImplementation1, formImplementationId, 1 ); SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus( @@ -55,7 +55,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId, 0 + formImplementation1, formImplementationId, 1 ); SuperformFactory(getContract(chainId, "SuperformFactory")).changeFormImplementationPauseStatus( @@ -83,7 +83,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { /// @dev Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId, 0 + formImplementation1, formImplementationId, 1 ); /// @dev Invalid Form Implementation For Pausing @@ -106,7 +106,7 @@ contract SuperformFactoryChangePauseTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId, 0 + formImplementation1, formImplementationId, 1 ); vm.expectRevert(Error.MSG_VALUE_NOT_ZERO.selector); diff --git a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol index 3ae5c0d72..133e723e1 100644 --- a/test/unit/superform-factory/superform-factory.createSuperforms.t.sol +++ b/test/unit/superform-factory/superform-factory.createSuperforms.t.sol @@ -91,7 +91,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); uint256 totalSuperformsBefore = SuperformFactory(getContract(chainId, "SuperformFactory")).getSuperformCount(); @@ -124,7 +124,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { /// Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation1, formImplementationId, 0 + formImplementation1, formImplementationId, 1 ); /// @dev Creating superform using form @@ -145,7 +145,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using form @@ -170,7 +170,7 @@ contract SuperformFactoryCreateSuperformTest is BaseSetup { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested vm.expectRevert(Error.FORM_INTERFACE_UNSUPPORTED.selector); SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); } diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index 7e88ec81a..026a15984 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -43,7 +43,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -74,7 +74,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -104,7 +104,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -135,7 +135,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -165,7 +165,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -195,7 +195,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -225,7 +225,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -255,7 +255,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -285,7 +285,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -315,7 +315,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -345,7 +345,7 @@ contract SuperformERC4626FormTest is ProtocolActions { // Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested SuperformFactory(getContract(chainId, "SuperformFactory")).addFormImplementation( - formImplementation, formImplementationId, 0 + formImplementation, formImplementationId, 1 ); /// @dev Creating superform using formImplementationId and vault @@ -661,7 +661,7 @@ contract SuperformERC4626FormTest is ProtocolActions { VaultMock vault = new VaultMock(asset, "Mock Vault", "Mock"); /// @dev Deploying Forms Using AddImplementation. Not Testing Reverts As Already Tested - superformFactory.addFormImplementation(formImplementation, formImplementationId, 0); + superformFactory.addFormImplementation(formImplementation, formImplementationId, 1); /// @dev should revert as superRegistry coming from SuperformFactory does not /// match the one set in the ERC4626Form diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 550cdcdb0..94fff1eff 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -631,7 +631,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; /// @dev 11 - Add newly deployed form implementations to Factory - ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0], 0); + ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0], 1); ISuperformFactory(vars.factory).addFormImplementation( vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1], 2 From fa09c452367da66c62f8c47c9b19f34c85cd3c56 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 15:16:44 +0530 Subject: [PATCH 156/210] chore: switch proof length to 160 --- src/payments/PaymentHelper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index d34b2a472..4bb8e4446 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -32,7 +32,7 @@ contract PaymentHelper is IPaymentHelper { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - uint256 private constant PROOF_LENGTH = 96; + uint256 private constant PROOF_LENGTH = 160; ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; From c2d2954e1042f1a79786188b2a8b78517116861e Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 18:55:52 +0530 Subject: [PATCH 157/210] chore: add commenting about resetting gas or native feed --- src/payments/PaymentHelper.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 88375c3b1..90171e9d7 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -578,6 +578,8 @@ contract PaymentHelper is IPaymentHelper { /// @dev Type 1: DST TOKEN PRICE FEED ORACLE if (configType_ == 1) { AggregatorV3Interface nativeFeedOracleContract = AggregatorV3Interface(abi.decode(config_, (address))); + + /// @dev allows setting price feed to address(0), equivalent for resetting native price if ( address(nativeFeedOracleContract) != address(0) && nativeFeedOracleContract.decimals() != SUPPORTED_FEED_PRECISION @@ -591,6 +593,8 @@ contract PaymentHelper is IPaymentHelper { /// @dev Type 2: DST GAS PRICE ORACLE if (configType_ == 2) { AggregatorV3Interface gasPriceOracleContract = AggregatorV3Interface(abi.decode(config_, (address))); + + /// @dev allows setting gas price to address(0), equivalent for resetting gas price if ( address(gasPriceOracleContract) != address(0) && gasPriceOracleContract.decimals() != SUPPORTED_FEED_PRECISION From 66ae51f67eb340799139bc436dbad9e3927dc2a4 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 19:12:24 +0530 Subject: [PATCH 158/210] chore: add revert for underflows in broadcast --- src/crosschain-data/BroadcastRegistry.sol | 4 ++++ test/unit/crosschain-data/BroadcastRegistry.t.sol | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/crosschain-data/BroadcastRegistry.sol b/src/crosschain-data/BroadcastRegistry.sol index 08feada89..ab2be4369 100644 --- a/src/crosschain-data/BroadcastRegistry.sol +++ b/src/crosschain-data/BroadcastRegistry.sol @@ -98,6 +98,10 @@ contract BroadcastRegistry is IBroadcastRegistry { override onlySender { + if (msg.value < gasFee_) { + revert Error.INVALID_BROADCAST_FEE(); + } + _broadcastPayload(srcSender_, ambId_, gasFee_, message_, extraData_); /// @dev refunds any overpaid msg.value diff --git a/test/unit/crosschain-data/BroadcastRegistry.t.sol b/test/unit/crosschain-data/BroadcastRegistry.t.sol index 3d47cdf5e..fa207cb53 100644 --- a/test/unit/crosschain-data/BroadcastRegistry.t.sol +++ b/test/unit/crosschain-data/BroadcastRegistry.t.sol @@ -48,4 +48,10 @@ contract BroadcastRegistryTest is BaseSetup { assertEq(address(broadcastRegistry).balance, 0); assertEq(invalidReceiver.balance, 100 ether); } + + function test_revertOnBroadcastUnderPayment() public { + vm.startPrank(invalidReceiver); + vm.expectRevert(Error.INVALID_BROADCAST_FEE.selector); + broadcastRegistry.broadcastPayload{ value: 1 ether }(invalidReceiver, 4, 2 ether, bytes("testmepls"), bytes("")); + } } From 52cf33bf06b395bb494445507f718b5fbb114f56 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Sun, 24 Dec 2023 19:34:18 +0530 Subject: [PATCH 159/210] fix: comments --- src/payments/PaymentHelper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 4bb8e4446..4066b0a39 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -654,7 +654,7 @@ contract PaymentHelper is IPaymentHelper { uint256 gasReqPerByte = gasPerByte[dstChainId_]; uint256 totalDstGasReqInWei = abi.encode(ambIdEncodedMessage).length * gasReqPerByte; - /// @dev proof length is always 96 + /// @dev proof length is always of fixed length uint256 totalDstGasReqInWeiForProof = PROOF_LENGTH * gasReqPerByte; extraDataPerAMB = new bytes[](len); From 0e96b233e39375d99f148bc685be40358f66b126 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 11:11:40 -0600 Subject: [PATCH 160/210] chore: refactor + combine withdrawal txData checks --- src/crosschain-liquidity/DstSwapper.sol | 2 +- src/forms/ERC4626FormImplementation.sol | 93 ++++++++++++++----------- src/forms/ERC4626TimelockForm.sol | 1 - 3 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index f04f04e96..b92a72afe 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -27,7 +27,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; - uint256 private constant ENTIRE_SLIPPAGE = 10_000; + uint256 internal constant ENTIRE_SLIPPAGE = 10_000; ////////////////////////////////////////////////////////////// // STATE VARIABLES // diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 11aca09ab..6fcd139c0 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -240,16 +240,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC20(vars.asset).safeIncreaseAllowance(vault, vars.assetDifference); /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior - address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); - uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); - uint256 sharesExpected = v.convertToShares(vars.assetDifference); - shares = v.deposit(vars.assetDifference, sharesReceiver); - uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); - if ((sharesBalanceAfter - sharesBalanceBefore != shares) || - (shares < ((sharesExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) - ) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } + shares = _depositAndValidate(singleVaultData_,v,vars.assetDifference); } function _processXChainDeposit( @@ -275,16 +266,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC20(asset).safeIncreaseAllowance(vaultLoc, singleVaultData_.amount); /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior - address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); - uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); - uint256 sharesExpected = v.convertToShares(singleVaultData_.amount); - shares = v.deposit(singleVaultData_.amount, sharesReceiver); - uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); - if ((sharesBalanceAfter - sharesBalanceBefore != shares) || - (shares < ((sharesExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) - ) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } + shares = _depositAndValidate(singleVaultData_,v,singleVaultData_.amount); emit Processed(srcChainId_, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); } @@ -304,17 +286,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); - uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); - assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); - if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) - ) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } - - if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + assets = _withdrawAndValidate(singleVaultData_,vars.receiver,v,a); if (vars.len1 != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); @@ -389,17 +361,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - uint256 assetsBalanceBefore = a.balanceOf(vars.receiver); - uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); - assets = v.redeem(singleVaultData_.amount, vars.receiver, address(this)); - uint256 assetsBalanceAfter = a.balanceOf(vars.receiver); - if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) - ) { - revert Error.VAULT_IMPLEMENTATION_FAILED(); - } - - if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + assets = _withdrawAndValidate(singleVaultData_,vars.receiver,v,a); if (len != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); @@ -408,6 +370,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault /// @dev if less it should be within the slippage limit specified by the user + /// @dev important to maintain so that the keeper cannot update with malicious data after successful withdraw if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) { revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); } @@ -444,6 +407,52 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { emit Processed(srcChainId_, vars.dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vault); } + function _depositAndValidate( + InitSingleVaultData memory singleVaultData_, + IERC4626 v, + uint256 assetDifference + ) + internal + returns (uint256 shares) + { + address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); + uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); + uint256 sharesExpected = v.convertToShares(assetDifference); + shares = v.deposit(assetDifference, sharesReceiver); + uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); + + if ((sharesBalanceAfter - sharesBalanceBefore != shares) || + (shares < ((sharesExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + ) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } + } + + function _withdrawAndValidate( + InitSingleVaultData memory singleVaultData_, + address receiver, + IERC4626 v, + IERC20 a + ) + internal + returns (uint256 assets) + { + uint256 assetsBalanceBefore = a.balanceOf(receiver); + uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); + assets = v.redeem(singleVaultData_.amount, receiver, address(this)); + uint256 assetsBalanceAfter = a.balanceOf(receiver); + + if ((assetsBalanceAfter - assetsBalanceBefore != assets) || + (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + ) { + revert Error.VAULT_IMPLEMENTATION_FAILED(); + } + + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); + + return assets; + } + function _isWithdrawTxDataAmountInvalid( uint256 bridgeDecodedAmount_, uint256 redeemedAmount_, diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 38d4b19d5..287ce82de 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -25,7 +25,6 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { ////////////////////////////////////////////////////////////// uint8 constant stateRegistryId = 2; // TimelockStateRegistry - uint256 private constant ENTIRE_SLIPPAGE = 10_000; ////////////////////////////////////////////////////////////// // STRUCTS // From 564db3a1063658ef239ea55ca76aab6a5de8b746 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 11:40:25 -0600 Subject: [PATCH 161/210] chore: clean up logic --- src/forms/ERC4626FormImplementation.sol | 31 ++++++++----------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 6fcd139c0..1832c24f0 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -46,15 +46,12 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { struct directWithdrawLocalVars { uint64 chainId; address asset; - address receiver; address bridgeValidator; - uint256 len1; uint256 amount; } struct xChainWithdrawLocalVars { uint64 dstChainId; - address receiver; address asset; address bridgeValidator; uint256 balanceBefore; @@ -273,11 +270,9 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { function _processDirectWithdraw(InitSingleVaultData memory singleVaultData_) internal returns (uint256 assets) { directWithdrawLocalVars memory vars; - vars.len1 = singleVaultData_.liqData.txData.length; /// @dev if there is no txData, on withdraws the receiver is receiverAddress, otherwise it /// is this contract (before swap) - vars.receiver = vars.len1 == 0 ? singleVaultData_.receiverAddress : address(this); IERC4626 v = IERC4626(vault); IERC20 a = IERC20(asset); @@ -286,14 +281,16 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - assets = _withdrawAndValidate(singleVaultData_,vars.receiver,v,a); + assets = _withdrawAndValidate(singleVaultData_,v,a); - if (vars.len1 != 0) { + if (singleVaultData_.liqData.txData.length != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); vars.amount = IBridgeValidator(vars.bridgeValidator).decodeAmountIn(singleVaultData_.liqData.txData, false); /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault + /// @dev if less it should be within the slippage limit specified by the user + /// @dev important to maintain so that the keeper cannot update with malicious data after successful withdraw if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) { revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); } @@ -349,19 +346,13 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { (,, vars.dstChainId) = singleVaultData_.superformId.getSuperform(); - /// @dev receiverAddress is checked for existence on source - /// @dev user will either provide an address equal to msg.sender (if EOA) - /// @dev or user will specify an address on the target chain for the collateral extraction (if Smart Contract - /// Wallet) - vars.receiver = len == 0 ? singleVaultData_.receiverAddress : address(this); - IERC4626 v = IERC4626(vault); IERC20 a = IERC20(asset); if (!singleVaultData_.retain4626) { vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - assets = _withdrawAndValidate(singleVaultData_,vars.receiver,v,a); + assets = _withdrawAndValidate(singleVaultData_,v,a); if (len != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); @@ -430,17 +421,17 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { function _withdrawAndValidate( InitSingleVaultData memory singleVaultData_, - address receiver, IERC4626 v, IERC20 a ) internal returns (uint256 assets) { - uint256 assetsBalanceBefore = a.balanceOf(receiver); + address assetReceiver = singleVaultData_.liqData.txData.length == 0 ? singleVaultData_.receiverAddress : address(this); + uint256 assetsBalanceBefore = a.balanceOf(assetReceiver); uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); - assets = v.redeem(singleVaultData_.amount, receiver, address(this)); - uint256 assetsBalanceAfter = a.balanceOf(receiver); + assets = v.redeem(singleVaultData_.amount, assetReceiver, address(this)); + uint256 assetsBalanceAfter = a.balanceOf(assetReceiver); if ((assetsBalanceAfter - assetsBalanceBefore != assets) || (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) @@ -449,8 +440,6 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { } if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); - - return assets; } function _isWithdrawTxDataAmountInvalid( @@ -460,7 +449,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { ) internal pure - returns (bool isInvalid_) + returns (bool isInvalid) { if ( bridgeDecodedAmount_ > redeemedAmount_ From 2f4d3c3da9c259e345e04535bbd0f9d4bcd176e1 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 11:45:27 -0600 Subject: [PATCH 162/210] chore: assets over asset --- src/forms/ERC4626FormImplementation.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 1832c24f0..0cb31372e 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -427,11 +427,11 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { internal returns (uint256 assets) { - address assetReceiver = singleVaultData_.liqData.txData.length == 0 ? singleVaultData_.receiverAddress : address(this); - uint256 assetsBalanceBefore = a.balanceOf(assetReceiver); + address assetsReceiver = singleVaultData_.liqData.txData.length == 0 ? singleVaultData_.receiverAddress : address(this); + uint256 assetsBalanceBefore = a.balanceOf(assetsReceiver); uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); - assets = v.redeem(singleVaultData_.amount, assetReceiver, address(this)); - uint256 assetsBalanceAfter = a.balanceOf(assetReceiver); + assets = v.redeem(singleVaultData_.amount, assetsReceiver, address(this)); + uint256 assetsBalanceAfter = a.balanceOf(assetsReceiver); if ((assetsBalanceAfter - assetsBalanceBefore != assets) || (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) From a84620dd6a84c41eab38bc7243ea45367210c153 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 12:37:03 -0600 Subject: [PATCH 163/210] chore: SUP-4931 --- src/BaseForm.sol | 2 +- src/BaseRouter.sol | 2 +- src/BaseRouterImplementation.sol | 2 +- src/EmergencyQueue.sol | 5 +++-- src/SuperformFactory.sol | 3 ++- src/crosschain-data/BaseStateRegistry.sol | 5 +++-- src/crosschain-data/BroadcastRegistry.sol | 6 +++--- .../adapters/hyperlane/HyperlaneImplementation.sol | 14 +++++++------- .../adapters/layerzero/LayerzeroImplementation.sol | 8 ++++---- .../automatic-relayer/WormholeARImplementation.sol | 6 +++--- .../WormholeSRImplementation.sol | 4 ++-- .../extensions/TimelockStateRegistry.sol | 2 +- src/crosschain-data/utils/PayloadHelper.sol | 5 +++-- src/crosschain-liquidity/BridgeValidator.sol | 2 +- src/crosschain-liquidity/DstSwapper.sol | 2 +- src/crosschain-liquidity/lifi/LiFiValidator.sol | 2 +- .../socket/SocketOneInchValidator.sol | 4 ++-- .../socket/SocketValidator.sol | 4 ++-- src/forms/ERC4626Form.sol | 2 +- src/forms/ERC4626FormImplementation.sol | 4 ++-- src/forms/ERC4626KYCDaoForm.sol | 7 ++++--- src/forms/ERC4626TimelockForm.sol | 2 +- src/interfaces/IBaseForm.sol | 2 +- src/interfaces/IBaseRouterImplementation.sol | 1 - src/interfaces/ISuperPositions.sol | 2 +- src/payments/PayMaster.sol | 4 ++-- src/payments/PaymentHelper.sol | 3 ++- src/settings/SuperRegistry.sol | 2 +- 28 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 1a71054e1..ddd21a206 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -4,13 +4,13 @@ pragma solidity ^0.8.23; import { Initializable } from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol"; import { ERC165 } from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol"; import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -import { InitSingleVaultData } from "./types/DataTypes.sol"; import { IBaseForm } from "./interfaces/IBaseForm.sol"; import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; import { Error } from "./libraries/Error.sol"; import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; import { IEmergencyQueue } from "./interfaces/IEmergencyQueue.sol"; import { DataLib } from "./libraries/DataLib.sol"; +import { InitSingleVaultData } from "./types/DataTypes.sol"; /// @title BaseForm /// @author Zeropoint Labs. diff --git a/src/BaseRouter.sol b/src/BaseRouter.sol index c66998e71..b9e0e7aa1 100644 --- a/src/BaseRouter.sol +++ b/src/BaseRouter.sol @@ -5,7 +5,7 @@ import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IBaseRouter } from "./interfaces/IBaseRouter.sol"; import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; -import "./libraries/Error.sol"; +import { Error } from "./libraries/Error.sol"; import "./types/DataTypes.sol"; /// @title BaseRouter diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 2e0c4cc70..d8f4f3bb4 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -18,7 +18,7 @@ import { ISuperPositions } from "./interfaces/ISuperPositions.sol"; import { DataLib } from "./libraries/DataLib.sol"; import { Error } from "./libraries/Error.sol"; import { IPermit2 } from "./vendor/dragonfly-xyz/IPermit2.sol"; -import "./crosschain-liquidity/LiquidityHandler.sol"; +import { LiquidityHandler } from "./crosschain-liquidity/LiquidityHandler.sol"; import "./types/DataTypes.sol"; /// @title BaseRouterImplementation diff --git a/src/EmergencyQueue.sol b/src/EmergencyQueue.sol index 20164814b..8b59ae039 100644 --- a/src/EmergencyQueue.sol +++ b/src/EmergencyQueue.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { DataLib } from "./libraries/DataLib.sol"; + import { IBaseForm } from "./interfaces/IBaseForm.sol"; import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; import { ISuperRBAC } from "./interfaces/ISuperRBAC.sol"; import { IEmergencyQueue } from "./interfaces/IEmergencyQueue.sol"; -import { Error } from "./libraries/Error.sol"; import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; +import { DataLib } from "./libraries/DataLib.sol"; +import { Error } from "./libraries/Error.sol"; import "./types/DataTypes.sol"; /// @title EmergencyQueue diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 72d30289d..75c9e1a22 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.23; import { ERC165Checker } from "openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol"; import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +import { Clones } from "openzeppelin-contracts/contracts/proxy/Clones.sol"; import { BaseForm } from "./BaseForm.sol"; import { BroadcastMessage } from "./types/DataTypes.sol"; import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; @@ -12,7 +13,7 @@ import { ISuperRBAC } from "./interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; import { Error } from "./libraries/Error.sol"; import { DataLib } from "./libraries/DataLib.sol"; -import { Clones } from "openzeppelin-contracts/contracts/proxy/Clones.sol"; + /// @title Superforms Factory /// @dev A secure, and easily queryable central point of access for all Superforms on any given chain, diff --git a/src/crosschain-data/BaseStateRegistry.sol b/src/crosschain-data/BaseStateRegistry.sol index a1a19930e..b1d70dccc 100644 --- a/src/crosschain-data/BaseStateRegistry.sol +++ b/src/crosschain-data/BaseStateRegistry.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { Error } from "../libraries/Error.sol"; + import { IQuorumManager } from "../interfaces/IQuorumManager.sol"; import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; import { IBaseStateRegistry } from "../interfaces/IBaseStateRegistry.sol"; import { IAmbImplementation } from "../interfaces/IAmbImplementation.sol"; -import { PayloadState, AMBMessage, AMBExtraData } from "../types/DataTypes.sol"; +import { Error } from "../libraries/Error.sol"; import { ProofLib } from "../libraries/ProofLib.sol"; +import { PayloadState, AMBMessage, AMBExtraData } from "../types/DataTypes.sol"; /// @title BaseStateRegistry /// @author Zeropoint Labs diff --git a/src/crosschain-data/BroadcastRegistry.sol b/src/crosschain-data/BroadcastRegistry.sol index 62a45439b..fce3238b1 100644 --- a/src/crosschain-data/BroadcastRegistry.sol +++ b/src/crosschain-data/BroadcastRegistry.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { Error } from "src/libraries/Error.sol"; +import { IBroadcastAmbImplementation } from "src/interfaces/IBroadcastAmbImplementation.sol"; import { IBroadcastRegistry } from "src/interfaces/IBroadcastRegistry.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { Error } from "src/libraries/Error.sol"; +import { ProofLib } from "src/libraries/ProofLib.sol"; import { BroadcastMessage, PayloadState } from "src/types/DataTypes.sol"; -import { IBroadcastAmbImplementation } from "src/interfaces/IBroadcastAmbImplementation.sol"; -import { ProofLib } from "../libraries/ProofLib.sol"; interface Target { function stateSyncBroadcast(bytes memory data_) external; diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index 8a732db15..f7c11e763 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol"; -import { IMailbox } from "src/vendor/hyperlane/IMailbox.sol"; -import { StandardHookMetadata } from "src/vendor/hyperlane/StandardHookMetadata.sol"; -import { IMessageRecipient } from "src/vendor/hyperlane/IMessageRecipient.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; -import { IInterchainGasPaymaster } from "src/vendor/hyperlane/IInterchainGasPaymaster.sol"; -import { AMBMessage } from "src/types/DataTypes.sol"; -import { Error } from "src/libraries/Error.sol"; import { DataLib } from "src/libraries/DataLib.sol"; +import { Error } from "src/libraries/Error.sol"; +import { AMBMessage } from "src/types/DataTypes.sol"; +import { IMailbox } from "src/vendor/hyperlane/IMailbox.sol"; +import { IMessageRecipient } from "src/vendor/hyperlane/IMessageRecipient.sol"; +import { IInterchainGasPaymaster } from "src/vendor/hyperlane/IInterchainGasPaymaster.sol"; +import { StandardHookMetadata } from "src/vendor/hyperlane/StandardHookMetadata.sol"; /// @title HyperlaneImplementation /// @author Zeropoint Labs diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index 6f5a67e4a..27a4f0a32 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; -import { AMBMessage } from "src/types/DataTypes.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; import { Error } from "src/libraries/Error.sol"; +import { AMBMessage } from "src/types/DataTypes.sol"; +import { ILayerZeroEndpoint } from "src/vendor/layerzero/ILayerZeroEndpoint.sol"; import { ILayerZeroReceiver } from "src/vendor/layerzero/ILayerZeroReceiver.sol"; import { ILayerZeroUserApplicationConfig } from "src/vendor/layerzero/ILayerZeroUserApplicationConfig.sol"; -import { ILayerZeroEndpoint } from "src/vendor/layerzero/ILayerZeroEndpoint.sol"; -import { DataLib } from "src/libraries/DataLib.sol"; /// @title LayerzeroImplementation /// @author Zeropoint Labs diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 1b164ebbc..7ed5a4e40 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; -import { AMBMessage } from "src/types/DataTypes.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; import { Error } from "src/libraries/Error.sol"; +import { AMBMessage } from "src/types/DataTypes.sol"; import { IWormholeRelayer, VaaKey } from "src/vendor/wormhole/IWormholeRelayer.sol"; import { IWormholeReceiver } from "src/vendor/wormhole/IWormholeReceiver.sol"; -import { DataLib } from "src/libraries/DataLib.sol"; import "src/vendor/wormhole/Utils.sol"; /// @title WormholeImplementation diff --git a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol index b0d544e9c..c774fa779 100644 --- a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IBroadcastRegistry } from "src/interfaces/IBroadcastRegistry.sol"; import { IBroadcastAmbImplementation } from "src/interfaces/IBroadcastAmbImplementation.sol"; +import { IBroadcastRegistry } from "src/interfaces/IBroadcastRegistry.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; import { Error } from "src/libraries/Error.sol"; import { IWormhole } from "src/vendor/wormhole/IWormhole.sol"; -import { DataLib } from "src/libraries/DataLib.sol"; import "src/vendor/wormhole/Utils.sol"; /// @title WormholeImplementation diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index df9c84692..7f8c9e41f 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.23; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +import { BaseStateRegistry } from "../BaseStateRegistry.sol"; import { IBaseForm } from "../../interfaces/IBaseForm.sol"; import { ISuperformFactory } from "../../interfaces/ISuperformFactory.sol"; import { ISuperRegistry } from "../../interfaces/ISuperRegistry.sol"; @@ -14,7 +15,6 @@ import { IBaseStateRegistry } from "../../interfaces/IBaseStateRegistry.sol"; import { ISuperRBAC } from "../../interfaces/ISuperRBAC.sol"; import { IPaymentHelper } from "../../interfaces/IPaymentHelper.sol"; import { Error } from "../../libraries/Error.sol"; -import { BaseStateRegistry } from "../BaseStateRegistry.sol"; import { ProofLib } from "../../libraries/ProofLib.sol"; import { DataLib } from "../../libraries/DataLib.sol"; import { PayloadUpdaterLib } from "../../libraries/PayloadUpdaterLib.sol"; diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 819673f92..916edf083 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -7,6 +7,8 @@ import { IBaseStateRegistry } from "../../interfaces/IBaseStateRegistry.sol"; import { ITimelockStateRegistry } from "../../interfaces/ITimelockStateRegistry.sol"; import { IPayloadHelper } from "../../interfaces/IPayloadHelper.sol"; import { IBridgeValidator } from "../../interfaces/IBridgeValidator.sol"; +import { DataLib } from "../../libraries/DataLib.sol"; +import { ProofLib } from "../../libraries/ProofLib.sol"; import { Error } from "../../libraries/Error.sol"; import { CallbackType, @@ -18,8 +20,7 @@ import { LiqRequest, AMBMessage } from "../../types/DataTypes.sol"; -import { DataLib } from "../../libraries/DataLib.sol"; -import { ProofLib } from "../../libraries/ProofLib.sol"; + /// @title PayloadHelper /// @author ZeroPoint Labs diff --git a/src/crosschain-liquidity/BridgeValidator.sol b/src/crosschain-liquidity/BridgeValidator.sol index 1d1c9862c..80bd942b9 100644 --- a/src/crosschain-liquidity/BridgeValidator.sol +++ b/src/crosschain-liquidity/BridgeValidator.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; +import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; /// @title BridgeValidator /// @author Zeropoint Labs diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index f04f04e96..30866f3b0 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -4,11 +4,11 @@ pragma solidity ^0.8.23; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; import { IDstSwapper } from "../interfaces/IDstSwapper.sol"; import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; import { IBaseStateRegistry } from "../interfaces/IBaseStateRegistry.sol"; import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; -import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; import { IERC4626Form } from "../forms/interfaces/IERC4626Form.sol"; import { Error } from "../libraries/Error.sol"; diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index 1dbec98ab..8f3d6deaa 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -10,7 +10,7 @@ import { StandardizedCallFacet } from "src/vendor/lifi/StandardizedCallFacet.sol /// @title LiFiValidator /// @author Zeropoint Labs -/// @dev To assert input txData is valid +/// @dev To assert LiFi input txData is valid contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index da39be389..eabf447af 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { Error } from "src/libraries/Error.sol"; import { BridgeValidator } from "src/crosschain-liquidity/BridgeValidator.sol"; +import { Error } from "src/libraries/Error.sol"; import { ISocketOneInchImpl } from "src/vendor/socket/ISocketOneInchImpl.sol"; /// @title SocketOneInchValidator /// @author Zeropoint Labs -/// @dev to assert input txData is valid +/// @dev to assert input Socket same-chain txData is valid contract SocketOneInchValidator is BridgeValidator { ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index 57ac8aa1b..8196927a3 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { Error } from "src/libraries/Error.sol"; import { BridgeValidator } from "src/crosschain-liquidity/BridgeValidator.sol"; +import { Error } from "src/libraries/Error.sol"; import { ISocketRegistry } from "src/vendor/socket/ISocketRegistry.sol"; /// @title SocketValidator /// @author Zeropoint Labs -/// @dev to assert input txData is valid +/// @dev to assert input Socket x-chain txData is valid contract SocketValidator is BridgeValidator { ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index 09bc1f598..9d4ea3069 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { InitSingleVaultData } from "../types/DataTypes.sol"; import { ERC4626FormImplementation } from "./ERC4626FormImplementation.sol"; import { BaseForm } from "../BaseForm.sol"; +import { InitSingleVaultData } from "../types/DataTypes.sol"; /// @title ERC4626Form /// @notice The Form implementation for IERC4626 vaults diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 848d31808..f5d2a134c 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -5,12 +5,12 @@ import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { IERC20Metadata } from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; -import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; -import { InitSingleVaultData } from "../types/DataTypes.sol"; import { BaseForm } from "../BaseForm.sol"; +import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; import { Error } from "../libraries/Error.sol"; import { DataLib } from "../libraries/DataLib.sol"; +import { InitSingleVaultData } from "../types/DataTypes.sol"; /// @title ERC4626FormImplementation /// @notice Has common internal functions that can be re-used by actual form implementations diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index d41d0737c..f99764b64 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -3,12 +3,13 @@ pragma solidity ^0.8.23; import { kycDAO4626 } from "super-vaults/kycdao-4626/kycdao4626.sol"; import { ERC721Holder } from "openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol"; -import { IKycdaoNTNFT } from "../vendor/kycDAO/IKycDAONTNFT.sol"; -import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; -import { InitSingleVaultData } from "../types/DataTypes.sol"; import { ERC4626FormImplementation } from "./ERC4626FormImplementation.sol"; import { BaseForm } from "../BaseForm.sol"; +import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; +import { IKycdaoNTNFT } from "../vendor/kycDAO/IKycDAONTNFT.sol"; import { Error } from "../libraries/Error.sol"; +import { InitSingleVaultData } from "../types/DataTypes.sol"; + /// @title ERC4626KYCDaoForm /// @notice The Form implementation for IERC4626 vaults with kycDAO NFT checks diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 24b44c01b..ae39a37c3 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.23; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC4626TimelockVault } from "super-vaults/interfaces/IERC4626TimelockVault.sol"; -import { InitSingleVaultData, TimelockPayload, LiqRequest } from "../types/DataTypes.sol"; import { ERC4626FormImplementation } from "./ERC4626FormImplementation.sol"; import { BaseForm } from "../BaseForm.sol"; import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; @@ -12,6 +11,7 @@ import { ITimelockStateRegistry } from "../interfaces/ITimelockStateRegistry.sol import { IEmergencyQueue } from "../interfaces/IEmergencyQueue.sol"; import { DataLib } from "../libraries/DataLib.sol"; import { Error } from "../libraries/Error.sol"; +import { InitSingleVaultData, TimelockPayload, LiqRequest } from "../types/DataTypes.sol"; /// @title ERC4626TimelockForm /// @notice Form implementation to handle timelock extension for ERC4626 vaults diff --git a/src/interfaces/IBaseForm.sol b/src/interfaces/IBaseForm.sol index 989295ed0..d51c84e05 100644 --- a/src/interfaces/IBaseForm.sol +++ b/src/interfaces/IBaseForm.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.23; import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -import { InitSingleVaultData } from "../types/DataTypes.sol"; import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; +import { InitSingleVaultData } from "../types/DataTypes.sol"; /// @title IBaseForm /// @author ZeroPoint Labs diff --git a/src/interfaces/IBaseRouterImplementation.sol b/src/interfaces/IBaseRouterImplementation.sol index c88f20861..b76166082 100644 --- a/src/interfaces/IBaseRouterImplementation.sol +++ b/src/interfaces/IBaseRouterImplementation.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.23; import { IBaseRouter } from "./IBaseRouter.sol"; - import "../types/DataTypes.sol"; /// @title IBaseRouterImplementation diff --git a/src/interfaces/ISuperPositions.sol b/src/interfaces/ISuperPositions.sol index 65c736dfc..c2dcdd517 100644 --- a/src/interfaces/ISuperPositions.sol +++ b/src/interfaces/ISuperPositions.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { AMBMessage } from "../types/DataTypes.sol"; import { IERC1155A } from "ERC1155A/interfaces/IERC1155A.sol"; +import { AMBMessage } from "../types/DataTypes.sol"; /// @title ISuperPositions /// @author Zeropoint Labs. diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index 67565bd19..e5e24f58d 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -3,13 +3,13 @@ pragma solidity ^0.8.23; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import { Error } from "../libraries/Error.sol"; +import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; import { IPayMaster } from "../interfaces/IPayMaster.sol"; import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; import { IAmbImplementation } from "../interfaces/IAmbImplementation.sol"; -import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; +import { Error } from "../libraries/Error.sol"; import { LiqRequest } from "../types/DataTypes.sol"; /// @title PayMaster diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 2b060232c..0c9e77501 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { AggregatorV3Interface } from "../vendor/chainlink/AggregatorV3Interface.sol"; + import { IPaymentHelper } from "../interfaces/IPaymentHelper.sol"; import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; @@ -13,6 +13,7 @@ import { DataLib } from "../libraries/DataLib.sol"; import { ProofLib } from "../libraries/ProofLib.sol"; import { ArrayCastLib } from "../libraries/ArrayCastLib.sol"; import "../types/DataTypes.sol"; +import { AggregatorV3Interface } from "../vendor/chainlink/AggregatorV3Interface.sol"; /// @dev interface to read public variable from state registry interface ReadOnlyBaseRegistry is IBaseStateRegistry { diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 2186e2355..996fd1bdc 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { QuorumManager } from "../crosschain-data/utils/QuorumManager.sol"; import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; -import { QuorumManager } from "../crosschain-data/utils/QuorumManager.sol"; import { Error } from "../libraries/Error.sol"; /// @title SuperRegistry From 2b3937e75757c0ad4ad0c9052227e1c5dd0b7ae5 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 13:04:33 -0600 Subject: [PATCH 164/210] chore: SUP-4930 --- src/BaseForm.sol | 17 ++++----- src/BaseRouter.sol | 8 ++--- src/BaseRouterImplementation.sol | 14 ++++---- src/EmergencyQueue.sol | 17 +++++---- src/SuperPositions.sol | 18 +++++----- src/SuperformFactory.sol | 18 +++++----- src/SuperformRouter.sol | 8 ++--- src/crosschain-data/BaseStateRegistry.sol | 15 ++++---- .../extensions/CoreStateRegistry.sol | 35 ++++++++++--------- .../extensions/TimelockStateRegistry.sol | 35 ++++++++++--------- src/crosschain-data/utils/PayloadHelper.sol | 22 ++++++------ src/crosschain-data/utils/QuorumManager.sol | 4 +-- src/crosschain-liquidity/BridgeValidator.sol | 4 +-- src/crosschain-liquidity/DstSwapper.sol | 20 +++++------ src/crosschain-liquidity/LiquidityHandler.sol | 2 +- src/forms/ERC4626Form.sol | 6 ++-- src/forms/ERC4626FormImplementation.sol | 12 +++---- src/forms/ERC4626KYCDaoForm.sol | 12 +++---- src/forms/ERC4626TimelockForm.sol | 16 ++++----- src/interfaces/IBaseForm.sol | 2 +- src/interfaces/IBaseRouter.sol | 2 +- src/interfaces/IBaseRouterImplementation.sol | 4 +-- src/interfaces/IBaseStateRegistry.sol | 2 +- src/interfaces/IEmergencyQueue.sol | 2 +- src/interfaces/IPayMaster.sol | 2 +- src/interfaces/IPaymentHelper.sol | 2 +- src/interfaces/ITimelockStateRegistry.sol | 2 +- src/libraries/ArrayCastLib.sol | 2 +- src/libraries/DataLib.sol | 2 +- src/libraries/PayloadUpdaterLib.sol | 6 ++-- src/libraries/ProofLib.sol | 2 +- src/payments/PayMaster.sol | 17 ++++----- src/payments/PaymentHelper.sol | 22 ++++++------ src/settings/SuperRBAC.sol | 10 +++--- src/settings/SuperRegistry.sol | 8 ++--- 35 files changed, 185 insertions(+), 185 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index ddd21a206..c818852df 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -1,21 +1,22 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; + +import { IBaseForm } from "src/interfaces/IBaseForm.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { IEmergencyQueue } from "src/interfaces/IEmergencyQueue.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { Error } from "src/libraries/Error.sol"; +import { InitSingleVaultData } from "src/types/DataTypes.sol"; import { Initializable } from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol"; import { ERC165 } from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol"; import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -import { IBaseForm } from "./interfaces/IBaseForm.sol"; -import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; -import { Error } from "./libraries/Error.sol"; -import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; -import { IEmergencyQueue } from "./interfaces/IEmergencyQueue.sol"; -import { DataLib } from "./libraries/DataLib.sol"; -import { InitSingleVaultData } from "./types/DataTypes.sol"; /// @title BaseForm /// @author Zeropoint Labs. /// @dev Abstract contract to be inherited by different form implementations -abstract contract BaseForm is Initializable, ERC165, IBaseForm { +abstract contract BaseForm is IBaseForm, Initializable, ERC165 { using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/BaseRouter.sol b/src/BaseRouter.sol index b9e0e7aa1..d9f1c75bf 100644 --- a/src/BaseRouter.sol +++ b/src/BaseRouter.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { Error } from "src/libraries/Error.sol"; +import "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import { IBaseRouter } from "./interfaces/IBaseRouter.sol"; -import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; -import { Error } from "./libraries/Error.sol"; -import "./types/DataTypes.sol"; /// @title BaseRouter /// @author Zeropoint Labs. diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index d8f4f3bb4..8220f7744 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -1,14 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { BaseRouter } from "./BaseRouter.sol"; -import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; -import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; -import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol"; -import { IBaseStateRegistry } from "./interfaces/IBaseStateRegistry.sol"; +import { BaseRouter } from "src/BaseRouter.sol"; import { IBaseRouterImplementation } from "./interfaces/IBaseRouterImplementation.sol"; +import { IBaseStateRegistry } from "./interfaces/IBaseStateRegistry.sol"; import { IPayMaster } from "./interfaces/IPayMaster.sol"; import { IPaymentHelper } from "./interfaces/IPaymentHelper.sol"; import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; @@ -20,6 +15,11 @@ import { Error } from "./libraries/Error.sol"; import { IPermit2 } from "./vendor/dragonfly-xyz/IPermit2.sol"; import { LiquidityHandler } from "./crosschain-liquidity/LiquidityHandler.sol"; import "./types/DataTypes.sol"; +import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; +import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; +import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; +import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol"; /// @title BaseRouterImplementation /// @author Zeropoint Labs diff --git a/src/EmergencyQueue.sol b/src/EmergencyQueue.sol index 8b59ae039..750f31b52 100644 --- a/src/EmergencyQueue.sol +++ b/src/EmergencyQueue.sol @@ -1,15 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; - -import { IBaseForm } from "./interfaces/IBaseForm.sol"; -import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; -import { ISuperRBAC } from "./interfaces/ISuperRBAC.sol"; -import { IEmergencyQueue } from "./interfaces/IEmergencyQueue.sol"; -import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; -import { DataLib } from "./libraries/DataLib.sol"; -import { Error } from "./libraries/Error.sol"; -import "./types/DataTypes.sol"; +import { IEmergencyQueue } from "src/interfaces/IEmergencyQueue.sol"; +import { IBaseForm } from "src/interfaces/IBaseForm.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { Error } from "src/libraries/Error.sol"; +import "src/types/DataTypes.sol"; /// @title EmergencyQueue /// @author Zeropoint Labs diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index c6bc39419..517ff9611 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -3,6 +3,15 @@ pragma solidity ^0.8.23; import { ERC1155A } from "ERC1155A/ERC1155A.sol"; import { aERC20 } from "ERC1155A/aERC20.sol"; +import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { IBaseForm } from "src/interfaces/IBaseForm.sol"; +import { IBroadcastRegistry } from "./interfaces/IBroadcastRegistry.sol"; +import { IPaymentHelper } from "./interfaces/IPaymentHelper.sol"; +import { Error } from "src/libraries/Error.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; import { TransactionType, ReturnMultiData, @@ -12,15 +21,6 @@ import { BroadcastMessage } from "src/types/DataTypes.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; -import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; -import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; -import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; -import { IBaseForm } from "src/interfaces/IBaseForm.sol"; -import { IBroadcastRegistry } from "./interfaces/IBroadcastRegistry.sol"; -import { IPaymentHelper } from "./interfaces/IPaymentHelper.sol"; -import { Error } from "src/libraries/Error.sol"; -import { DataLib } from "src/libraries/DataLib.sol"; /// @title SuperPositions /// @author Zeropoint Labs. diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index 75c9e1a22..d8d4b88dc 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { BaseForm } from "src/BaseForm.sol"; +import { BroadcastMessage } from "src/types/DataTypes.sol"; +import { IBaseForm } from "src/interfaces/IBaseForm.sol"; +import { IBroadcastRegistry } from "src/interfaces/IBroadcastRegistry.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { Error } from "src/libraries/Error.sol"; import { ERC165Checker } from "openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol"; import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; import { Clones } from "openzeppelin-contracts/contracts/proxy/Clones.sol"; -import { BaseForm } from "./BaseForm.sol"; -import { BroadcastMessage } from "./types/DataTypes.sol"; -import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; -import { IBaseForm } from "./interfaces/IBaseForm.sol"; -import { IBroadcastRegistry } from "./interfaces/IBroadcastRegistry.sol"; -import { ISuperRBAC } from "./interfaces/ISuperRBAC.sol"; -import { ISuperRegistry } from "./interfaces/ISuperRegistry.sol"; -import { Error } from "./libraries/Error.sol"; -import { DataLib } from "./libraries/DataLib.sol"; /// @title Superforms Factory diff --git a/src/SuperformRouter.sol b/src/SuperformRouter.sol index 4dfdd2d4c..8394c385d 100644 --- a/src/SuperformRouter.sol +++ b/src/SuperformRouter.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { BaseRouterImplementation } from "./BaseRouterImplementation.sol"; -import { BaseRouter } from "./BaseRouter.sol"; -import { IBaseRouter } from "./interfaces/IBaseRouter.sol"; -import "./types/DataTypes.sol"; +import { BaseRouterImplementation } from "src/BaseRouterImplementation.sol"; +import { BaseRouter } from "src/BaseRouter.sol"; +import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; +import "src/types/DataTypes.sol"; /// @title SuperformRouter /// @author Zeropoint Labs. diff --git a/src/crosschain-data/BaseStateRegistry.sol b/src/crosschain-data/BaseStateRegistry.sol index b1d70dccc..684203927 100644 --- a/src/crosschain-data/BaseStateRegistry.sol +++ b/src/crosschain-data/BaseStateRegistry.sol @@ -1,14 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; - -import { IQuorumManager } from "../interfaces/IQuorumManager.sol"; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; -import { IBaseStateRegistry } from "../interfaces/IBaseStateRegistry.sol"; -import { IAmbImplementation } from "../interfaces/IAmbImplementation.sol"; -import { Error } from "../libraries/Error.sol"; -import { ProofLib } from "../libraries/ProofLib.sol"; -import { PayloadState, AMBMessage, AMBExtraData } from "../types/DataTypes.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; +import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol"; +import { IQuorumManager } from "src/interfaces/IQuorumManager.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { Error } from "src/libraries/Error.sol"; +import { ProofLib } from "src/libraries/ProofLib.sol"; +import { PayloadState, AMBMessage, AMBExtraData } from "src/types/DataTypes.sol"; /// @title BaseStateRegistry /// @author Zeropoint Labs diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 1e4a31164..9aae4864d 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -1,23 +1,21 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import { BaseStateRegistry } from "../BaseStateRegistry.sol"; -import { ISuperRBAC } from "../../interfaces/ISuperRBAC.sol"; -import { ISuperPositions } from "../../interfaces/ISuperPositions.sol"; -import { ISuperRegistry } from "../../interfaces/ISuperRegistry.sol"; -import { IPaymentHelper } from "../../interfaces/IPaymentHelper.sol"; -import { IBaseForm } from "../../interfaces/IBaseForm.sol"; -import { IDstSwapper } from "../../interfaces/IDstSwapper.sol"; -import { ISuperformFactory } from "../../interfaces/ISuperformFactory.sol"; -import { ICoreStateRegistry } from "../../interfaces/ICoreStateRegistry.sol"; -import { IBridgeValidator } from "../../interfaces/IBridgeValidator.sol"; -import { DataLib } from "../../libraries/DataLib.sol"; -import { ProofLib } from "../../libraries/ProofLib.sol"; -import { ArrayCastLib } from "../../libraries/ArrayCastLib.sol"; -import { PayloadUpdaterLib } from "../../libraries/PayloadUpdaterLib.sol"; -import { Error } from "../../libraries/Error.sol"; +import { BaseStateRegistry } from "src/crosschain-data/BaseStateRegistry.sol"; +import { ICoreStateRegistry } from "src/interfaces/ICoreStateRegistry.sol"; +import { IBaseForm } from "src/interfaces/IBaseForm.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { IDstSwapper } from "src/interfaces/IDstSwapper.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { ProofLib } from "src/libraries/ProofLib.sol"; +import { ArrayCastLib } from "src/libraries/ArrayCastLib.sol"; +import { PayloadUpdaterLib } from "src/libraries/PayloadUpdaterLib.sol"; +import { Error } from "src/libraries/Error.sol"; import { PayloadState, AMBMessage, @@ -29,6 +27,9 @@ import { InitSingleVaultData, LiqRequest } from "../../types/DataTypes.sol"; +import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; + /// @title CoreStateRegistry /// @author Zeropoint Labs /// @dev enables communication between Superform Core Contracts deployed on all supported networks diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index 7f8c9e41f..fe28da3c3 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -1,24 +1,25 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; + +import { BaseStateRegistry } from "src/crosschain-data/BaseStateRegistry.sol"; +import { IBaseForm } from "src/interfaces/IBaseForm.sol"; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { IQuorumManager } from "src/interfaces/IQuorumManager.sol"; +import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; +import { IERC4626TimelockForm } from "src/forms/interfaces/IERC4626TimelockForm.sol"; +import { ITimelockStateRegistry } from "src/interfaces/ITimelockStateRegistry.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; +import { Error } from "src/libraries/Error.sol"; +import { ProofLib } from "src/libraries/ProofLib.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { PayloadUpdaterLib } from "src/libraries/PayloadUpdaterLib.sol"; +import "src/types/DataTypes.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; -import { BaseStateRegistry } from "../BaseStateRegistry.sol"; -import { IBaseForm } from "../../interfaces/IBaseForm.sol"; -import { ISuperformFactory } from "../../interfaces/ISuperformFactory.sol"; -import { ISuperRegistry } from "../../interfaces/ISuperRegistry.sol"; -import { IBridgeValidator } from "../../interfaces/IBridgeValidator.sol"; -import { IQuorumManager } from "../../interfaces/IQuorumManager.sol"; -import { ISuperPositions } from "../../interfaces/ISuperPositions.sol"; -import { IERC4626TimelockForm } from "../../forms/interfaces/IERC4626TimelockForm.sol"; -import { ITimelockStateRegistry } from "../../interfaces/ITimelockStateRegistry.sol"; -import { IBaseStateRegistry } from "../../interfaces/IBaseStateRegistry.sol"; -import { ISuperRBAC } from "../../interfaces/ISuperRBAC.sol"; -import { IPaymentHelper } from "../../interfaces/IPaymentHelper.sol"; -import { Error } from "../../libraries/Error.sol"; -import { ProofLib } from "../../libraries/ProofLib.sol"; -import { DataLib } from "../../libraries/DataLib.sol"; -import { PayloadUpdaterLib } from "../../libraries/PayloadUpdaterLib.sol"; -import "../../types/DataTypes.sol"; /// @title TimelockStateRegistry /// @author Zeropoint Labs diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 916edf083..7f2876917 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { ISuperRegistry } from "../../interfaces/ISuperRegistry.sol"; -import { ISuperPositions } from "../../interfaces/ISuperPositions.sol"; -import { IBaseStateRegistry } from "../../interfaces/IBaseStateRegistry.sol"; -import { ITimelockStateRegistry } from "../../interfaces/ITimelockStateRegistry.sol"; -import { IPayloadHelper } from "../../interfaces/IPayloadHelper.sol"; -import { IBridgeValidator } from "../../interfaces/IBridgeValidator.sol"; -import { DataLib } from "../../libraries/DataLib.sol"; -import { ProofLib } from "../../libraries/ProofLib.sol"; -import { Error } from "../../libraries/Error.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; +import { ITimelockStateRegistry } from "src/interfaces/ITimelockStateRegistry.sol"; +import { IPayloadHelper } from "src/interfaces/IPayloadHelper.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { ProofLib } from "src/libraries/ProofLib.sol"; +import { Error } from "src/libraries/Error.sol"; import { CallbackType, ReturnMultiData, @@ -19,13 +19,11 @@ import { TimelockPayload, LiqRequest, AMBMessage -} from "../../types/DataTypes.sol"; - +} from "src/types/DataTypes.sol"; /// @title PayloadHelper /// @author ZeroPoint Labs /// @dev helps decode payload data more easily. Used for off-chain purposes - contract PayloadHelper is IPayloadHelper { using DataLib for uint256; diff --git a/src/crosschain-data/utils/QuorumManager.sol b/src/crosschain-data/utils/QuorumManager.sol index f7fe1c397..44240c003 100644 --- a/src/crosschain-data/utils/QuorumManager.sol +++ b/src/crosschain-data/utils/QuorumManager.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IQuorumManager } from "../../interfaces/IQuorumManager.sol"; -import { Error } from "../../libraries/Error.sol"; +import { IQuorumManager } from "src/interfaces/IQuorumManager.sol"; +import { Error } from "src/libraries/Error.sol"; /// @title QuorumManager /// @author ZeroPoint Labs diff --git a/src/crosschain-liquidity/BridgeValidator.sol b/src/crosschain-liquidity/BridgeValidator.sol index 80bd942b9..c3da3da5c 100644 --- a/src/crosschain-liquidity/BridgeValidator.sol +++ b/src/crosschain-liquidity/BridgeValidator.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; /// @title BridgeValidator /// @author Zeropoint Labs diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 30866f3b0..75c61e0cf 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { LiquidityHandler } from "src/crosschain-liquidity/LiquidityHandler.sol"; +import { IDstSwapper } from "src/interfaces/IDstSwapper.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { IERC4626Form } from "src/forms/interfaces/IERC4626Form.sol"; +import { Error } from "src/libraries/Error.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; -import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; -import { IDstSwapper } from "../interfaces/IDstSwapper.sol"; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; -import { IBaseStateRegistry } from "../interfaces/IBaseStateRegistry.sol"; -import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; -import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; -import { IERC4626Form } from "../forms/interfaces/IERC4626Form.sol"; -import { Error } from "../libraries/Error.sol"; -import { DataLib } from "../libraries/DataLib.sol"; -import "../types/DataTypes.sol"; /// @title DstSwapper /// @author Zeropoint Labs. diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index 6f4f5fee8..1b70c702a 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { Error } from "src/libraries/Error.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import { Error } from "../libraries/Error.sol"; /** * @title LiquidityHandler diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index 9d4ea3069..11a1c05f6 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { ERC4626FormImplementation } from "./ERC4626FormImplementation.sol"; -import { BaseForm } from "../BaseForm.sol"; -import { InitSingleVaultData } from "../types/DataTypes.sol"; +import { ERC4626FormImplementation } from "src/forms/ERC4626FormImplementation.sol"; +import { BaseForm } from "src/BaseForm.sol"; +import { InitSingleVaultData } from "src/types/DataTypes.sol"; /// @title ERC4626Form /// @notice The Form implementation for IERC4626 vaults diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index f5d2a134c..88f0fcba7 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { BaseForm } from "src/BaseForm.sol"; +import { LiquidityHandler } from "src/crosschain-liquidity/LiquidityHandler.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { Error } from "src/libraries/Error.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { InitSingleVaultData } from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { IERC20Metadata } from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; -import { BaseForm } from "../BaseForm.sol"; -import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; -import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; -import { Error } from "../libraries/Error.sol"; -import { DataLib } from "../libraries/DataLib.sol"; -import { InitSingleVaultData } from "../types/DataTypes.sol"; /// @title ERC4626FormImplementation /// @notice Has common internal functions that can be re-used by actual form implementations diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index f99764b64..7d0efefb0 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { ERC4626FormImplementation } from "src/forms/ERC4626FormImplementation.sol"; +import { BaseForm } from "src/BaseForm.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { IKycdaoNTNFT } from "src/vendor/kycDAO/IKycDAONTNFT.sol"; +import { Error } from "src/libraries/Error.sol"; +import { InitSingleVaultData } from "src/types/DataTypes.sol"; import { kycDAO4626 } from "super-vaults/kycdao-4626/kycdao4626.sol"; import { ERC721Holder } from "openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol"; -import { ERC4626FormImplementation } from "./ERC4626FormImplementation.sol"; -import { BaseForm } from "../BaseForm.sol"; -import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; -import { IKycdaoNTNFT } from "../vendor/kycDAO/IKycDAONTNFT.sol"; -import { Error } from "../libraries/Error.sol"; -import { InitSingleVaultData } from "../types/DataTypes.sol"; /// @title ERC4626KYCDaoForm diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index ae39a37c3..1d565f2aa 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { ERC4626FormImplementation } from "src/forms/ERC4626FormImplementation.sol"; +import { BaseForm } from "src/BaseForm.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { ITimelockStateRegistry } from "src/interfaces/ITimelockStateRegistry.sol"; +import { IEmergencyQueue } from "src/interfaces/IEmergencyQueue.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { Error } from "src/libraries/Error.sol"; +import { InitSingleVaultData, TimelockPayload, LiqRequest } from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC4626TimelockVault } from "super-vaults/interfaces/IERC4626TimelockVault.sol"; -import { ERC4626FormImplementation } from "./ERC4626FormImplementation.sol"; -import { BaseForm } from "../BaseForm.sol"; -import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; -import { ITimelockStateRegistry } from "../interfaces/ITimelockStateRegistry.sol"; -import { IEmergencyQueue } from "../interfaces/IEmergencyQueue.sol"; -import { DataLib } from "../libraries/DataLib.sol"; -import { Error } from "../libraries/Error.sol"; -import { InitSingleVaultData, TimelockPayload, LiqRequest } from "../types/DataTypes.sol"; /// @title ERC4626TimelockForm /// @notice Form implementation to handle timelock extension for ERC4626 vaults diff --git a/src/interfaces/IBaseForm.sol b/src/interfaces/IBaseForm.sol index d51c84e05..d506642c1 100644 --- a/src/interfaces/IBaseForm.sol +++ b/src/interfaces/IBaseForm.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +import { InitSingleVaultData } from "src/types/DataTypes.sol"; import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; -import { InitSingleVaultData } from "../types/DataTypes.sol"; /// @title IBaseForm /// @author ZeroPoint Labs diff --git a/src/interfaces/IBaseRouter.sol b/src/interfaces/IBaseRouter.sol index 20f2042a4..427275d34 100644 --- a/src/interfaces/IBaseRouter.sol +++ b/src/interfaces/IBaseRouter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import "../types/DataTypes.sol"; +import "src/types/DataTypes.sol"; /// @title IBaseRouter /// @author Zeropoint Labs. diff --git a/src/interfaces/IBaseRouterImplementation.sol b/src/interfaces/IBaseRouterImplementation.sol index b76166082..d35003619 100644 --- a/src/interfaces/IBaseRouterImplementation.sol +++ b/src/interfaces/IBaseRouterImplementation.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { IBaseRouter } from "./IBaseRouter.sol"; -import "../types/DataTypes.sol"; +import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; +import "src/types/DataTypes.sol"; /// @title IBaseRouterImplementation /// @author Zeropoint Labs. diff --git a/src/interfaces/IBaseStateRegistry.sol b/src/interfaces/IBaseStateRegistry.sol index 49b79bae2..ea742f5b4 100644 --- a/src/interfaces/IBaseStateRegistry.sol +++ b/src/interfaces/IBaseStateRegistry.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import "../types/DataTypes.sol"; +import "src/types/DataTypes.sol"; /// @title IBaseStateRegistry /// @author ZeroPoint Labs diff --git a/src/interfaces/IEmergencyQueue.sol b/src/interfaces/IEmergencyQueue.sol index ab77801bc..adb3ba5cf 100644 --- a/src/interfaces/IEmergencyQueue.sol +++ b/src/interfaces/IEmergencyQueue.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { InitSingleVaultData } from "../types/DataTypes.sol"; +import { InitSingleVaultData } from "src/types/DataTypes.sol"; interface IEmergencyQueue { ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IPayMaster.sol b/src/interfaces/IPayMaster.sol index bf14f51f2..d0a39c02d 100644 --- a/src/interfaces/IPayMaster.sol +++ b/src/interfaces/IPayMaster.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { LiqRequest } from "../types/DataTypes.sol"; +import { LiqRequest } from "src/types/DataTypes.sol"; /// @title IPayMaster /// @author ZeroPoint Labs diff --git a/src/interfaces/IPaymentHelper.sol b/src/interfaces/IPaymentHelper.sol index aa15e518e..4bf7ab0c8 100644 --- a/src/interfaces/IPaymentHelper.sol +++ b/src/interfaces/IPaymentHelper.sol @@ -8,7 +8,7 @@ import { SingleXChainSingleVaultStateReq, SingleDirectSingleVaultStateReq, SingleDirectMultiVaultStateReq -} from "../types/DataTypes.sol"; +} from "src/types/DataTypes.sol"; /// @title IPaymentHelper /// @author ZeroPoint Labs diff --git a/src/interfaces/ITimelockStateRegistry.sol b/src/interfaces/ITimelockStateRegistry.sol index 77d16df71..cbd13c728 100644 --- a/src/interfaces/ITimelockStateRegistry.sol +++ b/src/interfaces/ITimelockStateRegistry.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { InitSingleVaultData, TimelockPayload } from "../types/DataTypes.sol"; +import { InitSingleVaultData, TimelockPayload } from "src/types/DataTypes.sol"; /// @title ITimelockStateRegistry /// @author ZeroPoint Labs diff --git a/src/libraries/ArrayCastLib.sol b/src/libraries/ArrayCastLib.sol index e22427d83..7e702c1de 100644 --- a/src/libraries/ArrayCastLib.sol +++ b/src/libraries/ArrayCastLib.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { InitSingleVaultData, InitMultiVaultData, LiqRequest } from "../types/DataTypes.sol"; +import { InitSingleVaultData, InitMultiVaultData, LiqRequest } from "src/types/DataTypes.sol"; /// @dev library to cast single values into array for streamlining helper functions /// @notice not gas optimized, suggested for usage only in view/pure functions diff --git a/src/libraries/DataLib.sol b/src/libraries/DataLib.sol index 63a82ab9c..d654a358b 100644 --- a/src/libraries/DataLib.sol +++ b/src/libraries/DataLib.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { Error } from "../libraries/Error.sol"; +import { Error } from "src/libraries/Error.sol"; library DataLib { function packTxInfo( diff --git a/src/libraries/PayloadUpdaterLib.sol b/src/libraries/PayloadUpdaterLib.sol index a46be73b5..2588553ea 100644 --- a/src/libraries/PayloadUpdaterLib.sol +++ b/src/libraries/PayloadUpdaterLib.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { DataLib } from "./DataLib.sol"; -import { Error } from "../libraries/Error.sol"; -import { PayloadState, CallbackType, LiqRequest } from "../types/DataTypes.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { Error } from "src/libraries/Error.sol"; +import { PayloadState, CallbackType, LiqRequest } from "src/types/DataTypes.sol"; /// @dev library to validate slippage updation library PayloadUpdaterLib { diff --git a/src/libraries/ProofLib.sol b/src/libraries/ProofLib.sol index 707e1cac2..da7ca3ebe 100644 --- a/src/libraries/ProofLib.sol +++ b/src/libraries/ProofLib.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { AMBMessage } from "../types/DataTypes.sol"; +import { AMBMessage } from "src/types/DataTypes.sol"; /// @dev generates proof for amb message and bytes encoded message library ProofLib { diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index e5e24f58d..081d93641 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -1,16 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; + +import { LiquidityHandler } from "src/crosschain-liquidity/LiquidityHandler.sol"; +import { IPayMaster } from "src/interfaces/IPayMaster.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol"; +import { Error } from "src/libraries/Error.sol"; +import { LiqRequest } from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import { LiquidityHandler } from "../crosschain-liquidity/LiquidityHandler.sol"; -import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; -import { IPayMaster } from "../interfaces/IPayMaster.sol"; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; -import { IBridgeValidator } from "../interfaces/IBridgeValidator.sol"; -import { IAmbImplementation } from "../interfaces/IAmbImplementation.sol"; -import { Error } from "../libraries/Error.sol"; -import { LiqRequest } from "../types/DataTypes.sol"; /// @title PayMaster /// @author ZeroPoint Labs diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 0c9e77501..7e5b481f7 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -2,17 +2,17 @@ pragma solidity ^0.8.23; -import { IPaymentHelper } from "../interfaces/IPaymentHelper.sol"; -import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; -import { ISuperformFactory } from "../interfaces/ISuperformFactory.sol"; -import { IBaseStateRegistry } from "../interfaces/IBaseStateRegistry.sol"; -import { IAmbImplementation } from "../interfaces/IAmbImplementation.sol"; -import { Error } from "../libraries/Error.sol"; -import { DataLib } from "../libraries/DataLib.sol"; -import { ProofLib } from "../libraries/ProofLib.sol"; -import { ArrayCastLib } from "../libraries/ArrayCastLib.sol"; -import "../types/DataTypes.sol"; +import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; +import { IAmbImplementation } from "src/interfaces/IAmbImplementation.sol"; +import { Error } from "src/libraries/Error.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { ProofLib } from "src/libraries/ProofLib.sol"; +import { ArrayCastLib } from "src/libraries/ArrayCastLib.sol"; +import "src/types/DataTypes.sol"; import { AggregatorV3Interface } from "../vendor/chainlink/AggregatorV3Interface.sol"; /// @dev interface to read public variable from state registry diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 22c89e021..01a41e75c 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -2,11 +2,11 @@ pragma solidity ^0.8.23; import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol"; -import { IBroadcastRegistry } from "../interfaces/IBroadcastRegistry.sol"; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; -import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; -import { Error } from "../libraries/Error.sol"; -import { BroadcastMessage } from "../types/DataTypes.sol"; +import { IBroadcastRegistry } from "src/interfaces/IBroadcastRegistry.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { Error } from "src/libraries/Error.sol"; +import { BroadcastMessage } from "src/types/DataTypes.sol"; /// @title SuperRBAC /// @author Zeropoint Labs. diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 996fd1bdc..2a90cfd3e 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { QuorumManager } from "../crosschain-data/utils/QuorumManager.sol"; -import { ISuperRBAC } from "../interfaces/ISuperRBAC.sol"; -import { ISuperRegistry } from "../interfaces/ISuperRegistry.sol"; -import { Error } from "../libraries/Error.sol"; +import { QuorumManager } from "src/crosschain-data/utils/QuorumManager.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; +import { Error } from "src/libraries/Error.sol"; /// @title SuperRegistry /// @author Zeropoint Labs. From 7fe602160f398a03019fa9e93a050ef159f7dae2 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 13:13:15 -0600 Subject: [PATCH 165/210] chore: SUP-4946 --- src/types/DataTypes.sol | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index 583a2522f..1e761203e 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -193,12 +193,6 @@ struct ReturnSingleData { uint256 superformId; uint256 amount; } -/// @dev struct that contains the data on the fees to pay - -struct SingleDstAMBParams { - uint256 gasToPay; - bytes encodedAMBExtraData; -} /// @dev struct that contains the data on the fees to pay to the AMBs struct AMBExtraData { @@ -211,9 +205,3 @@ struct BroadCastAMBExtraData { uint256[] gasPerDst; bytes[] extraDataPerDst; } - -/// @dev acknowledgement extra data (contains gas information from dst to src callbacks) -struct AckAMBData { - uint8[] ambIds; - bytes extraData; -} From b4facb2bc1cecf58011358d9529c9a36c1845250 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 13:33:52 -0600 Subject: [PATCH 166/210] chore: SUP-4951 --- src/BaseForm.sol | 1 - src/BaseRouterImplementation.sol | 26 +++++++++---------- src/SuperPositions.sol | 3 ++- src/SuperformFactory.sol | 7 +++-- src/SuperformRouter.sol | 2 +- .../extensions/CoreStateRegistry.sol | 2 +- .../extensions/TimelockStateRegistry.sol | 3 +-- src/payments/PayMaster.sol | 1 - src/payments/PaymentHelper.sol | 3 +-- src/settings/SuperRBAC.sol | 4 +-- 10 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index c818852df..f89c61f30 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; - import { IBaseForm } from "src/interfaces/IBaseForm.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 8220f7744..5062267f9 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -2,19 +2,19 @@ pragma solidity ^0.8.23; import { BaseRouter } from "src/BaseRouter.sol"; -import { IBaseRouterImplementation } from "./interfaces/IBaseRouterImplementation.sol"; -import { IBaseStateRegistry } from "./interfaces/IBaseStateRegistry.sol"; -import { IPayMaster } from "./interfaces/IPayMaster.sol"; -import { IPaymentHelper } from "./interfaces/IPaymentHelper.sol"; -import { ISuperformFactory } from "./interfaces/ISuperformFactory.sol"; -import { IBaseForm } from "./interfaces/IBaseForm.sol"; -import { IBridgeValidator } from "./interfaces/IBridgeValidator.sol"; -import { ISuperPositions } from "./interfaces/ISuperPositions.sol"; -import { DataLib } from "./libraries/DataLib.sol"; -import { Error } from "./libraries/Error.sol"; -import { IPermit2 } from "./vendor/dragonfly-xyz/IPermit2.sol"; -import { LiquidityHandler } from "./crosschain-liquidity/LiquidityHandler.sol"; -import "./types/DataTypes.sol"; +import { IBaseRouterImplementation } from "src/interfaces/IBaseRouterImplementation.sol"; +import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; +import { IPayMaster } from "src/interfaces/IPayMaster.sol"; +import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; +import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; +import { IBaseForm } from "src/interfaces/IBaseForm.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; +import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; +import { DataLib } from "src/libraries/DataLib.sol"; +import { Error } from "src/libraries/Error.sol"; +import { IPermit2 } from "src/vendor/dragonfly-xyz/IPermit2.sol"; +import { LiquidityHandler } from "src/crosschain-liquidity/LiquidityHandler.sol"; +import "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index f754a9bd3..656573589 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -23,7 +23,8 @@ import { import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /// @title SuperPositions -/// @author Zeropoint Labs. +/// @dev Cross-chain LP token minted on source chain +/// @author Zeropoint Labs contract SuperPositions is ISuperPositions, ERC1155A { using DataLib for uint256; diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index db7b4cfbb..b2a9d6bd5 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -14,10 +14,9 @@ import { ERC165Checker } from "openzeppelin-contracts/contracts/utils/introspect import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; import { Clones } from "openzeppelin-contracts/contracts/proxy/Clones.sol"; - -/// @title Superforms Factory -/// @dev A secure, and easily queryable central point of access for all Superforms on any given chain, -/// @author Zeropoint Labs. +/// @title SuperformFactory +/// @dev Central point of read & write access for all Superforms on this chain +/// @author Zeropoint Labs contract SuperformFactory is ISuperformFactory { using DataLib for uint256; using Clones for address; diff --git a/src/SuperformRouter.sol b/src/SuperformRouter.sol index 8394c385d..23216e54a 100644 --- a/src/SuperformRouter.sol +++ b/src/SuperformRouter.sol @@ -7,8 +7,8 @@ import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import "src/types/DataTypes.sol"; /// @title SuperformRouter +/// @dev Routes funds and action information to a remote execution chain /// @author Zeropoint Labs. -/// @dev SuperformRouter users funds and action information to a remote execution chain. contract SuperformRouter is BaseRouterImplementation { ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 9aae4864d..bb550b987 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -26,7 +26,7 @@ import { ReturnSingleData, InitSingleVaultData, LiqRequest -} from "../../types/DataTypes.sol"; +} from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index fe28da3c3..1f93da7c2 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; - import { BaseStateRegistry } from "src/crosschain-data/BaseStateRegistry.sol"; import { IBaseForm } from "src/interfaces/IBaseForm.sol"; import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; @@ -9,11 +8,11 @@ import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; import { IQuorumManager } from "src/interfaces/IQuorumManager.sol"; import { ISuperPositions } from "src/interfaces/ISuperPositions.sol"; -import { IERC4626TimelockForm } from "src/forms/interfaces/IERC4626TimelockForm.sol"; import { ITimelockStateRegistry } from "src/interfaces/ITimelockStateRegistry.sol"; import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; +import { IERC4626TimelockForm } from "src/forms/interfaces/IERC4626TimelockForm.sol"; import { Error } from "src/libraries/Error.sol"; import { ProofLib } from "src/libraries/ProofLib.sol"; import { DataLib } from "src/libraries/DataLib.sol"; diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index 50d14079d..a8fb0d33a 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; - import { LiquidityHandler } from "src/crosschain-liquidity/LiquidityHandler.sol"; import { IPayMaster } from "src/interfaces/IPayMaster.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 4dc043d24..16d3d2038 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; - import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; @@ -13,7 +12,7 @@ import { DataLib } from "src/libraries/DataLib.sol"; import { ProofLib } from "src/libraries/ProofLib.sol"; import { ArrayCastLib } from "src/libraries/ArrayCastLib.sol"; import "src/types/DataTypes.sol"; -import { AggregatorV3Interface } from "../vendor/chainlink/AggregatorV3Interface.sol"; +import { AggregatorV3Interface } from "src/vendor/chainlink/AggregatorV3Interface.sol"; /// @dev interface to read public variable from state registry interface ReadOnlyBaseRegistry is IBaseStateRegistry { diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 01a41e75c..d80959c4e 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { IBroadcastRegistry } from "src/interfaces/IBroadcastRegistry.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; -import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { Error } from "src/libraries/Error.sol"; import { BroadcastMessage } from "src/types/DataTypes.sol"; +import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol"; /// @title SuperRBAC /// @author Zeropoint Labs. From 9d7cdb5d677296ebb7bad26a0fc241385b61988c Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 13:35:27 -0600 Subject: [PATCH 167/210] chore: SUP-4944 --- src/crosschain-data/utils/PayloadHelper.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 5e85df61a..2d218cd14 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -17,7 +17,6 @@ import { InitMultiVaultData, InitSingleVaultData, TimelockPayload, - LiqRequest, AMBMessage } from "src/types/DataTypes.sol"; From 4444dbbbcb782dd234b586315f168655ee0f71d2 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 13:40:33 -0600 Subject: [PATCH 168/210] chore: SUP-4952 --- src/BaseRouterImplementation.sol | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 5062267f9..c5ade124b 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -909,11 +909,10 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); - bool valid; /// @dev slippage, amount, paused status validation for (uint256 i; i < len; ++i) { - valid = _validateSuperformData( + if(!_validateSuperformData( superformsData_.superformIds[i], superformsData_.maxSlippages[i], superformsData_.amounts[i], @@ -923,10 +922,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou deposit_, factory, true - ); - - if (!valid) { - return valid; + )) { + return false; } /// @dev ensure interimTokens aren't repeated on destination chains From f90f3dbafbb5409ef469a1eaad4b2b934f5b9f42 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 14:33:22 -0600 Subject: [PATCH 169/210] chore: SUP-4944 --- src/BaseForm.sol | 3 ++- src/BaseRouter.sol | 3 ++- src/BaseRouterImplementation.sol | 3 ++- src/EmergencyQueue.sol | 3 ++- src/SuperPositions.sol | 1 + src/SuperformFactory.sol | 1 + src/SuperformRouter.sol | 3 ++- src/crosschain-data/BaseStateRegistry.sol | 1 + src/crosschain-data/BroadcastRegistry.sol | 3 ++- .../hyperlane/HyperlaneImplementation.sol | 3 ++- .../layerzero/LayerzeroImplementation.sol | 3 ++- .../WormholeARImplementation.sol | 4 ++-- .../WormholeSRImplementation.sol | 4 ++-- .../extensions/CoreStateRegistry.sol | 4 ++-- .../extensions/TimelockStateRegistry.sol | 4 ++-- src/crosschain-data/utils/PayloadHelper.sol | 3 ++- src/crosschain-data/utils/QuorumManager.sol | 1 + src/crosschain-liquidity/BridgeValidator.sol | 8 ++++--- .../lifi/LiFiValidator.sol | 1 + .../socket/SocketOneInchValidator.sol | 3 ++- .../socket/SocketValidator.sol | 3 ++- src/forms/ERC4626Form.sol | 6 ++++-- src/forms/ERC4626FormImplementation.sol | 4 +++- src/forms/ERC4626KYCDaoForm.sol | 8 ++++--- src/forms/ERC4626TimelockForm.sol | 4 +++- src/interfaces/IAmbImplementation.sol | 3 ++- src/interfaces/IBaseForm.sol | 3 ++- src/interfaces/IBaseRouter.sol | 3 ++- src/interfaces/IBaseRouterImplementation.sol | 3 ++- src/interfaces/IBaseStateRegistry.sol | 3 ++- src/interfaces/IBridgeValidator.sol | 4 +++- .../IBroadcastAmbImplementation.sol | 3 ++- src/interfaces/IBroadcastRegistry.sol | 3 ++- src/interfaces/ICoreStateRegistry.sol | 3 ++- src/interfaces/IDstSwapper.sol | 4 ++-- src/interfaces/IEmergencyQueue.sol | 1 + src/interfaces/IPayMaster.sol | 3 ++- src/interfaces/IPayloadHelper.sol | 3 ++- src/interfaces/IPaymentHelper.sol | 3 ++- src/interfaces/IQuorumManager.sol | 4 ++++ src/interfaces/ISuperPositions.sol | 7 ++++--- src/interfaces/ISuperRBAC.sol | 3 ++- src/interfaces/ISuperRegistry.sol | 5 +++-- src/interfaces/ISuperformFactory.sol | 3 ++- src/interfaces/ITimelockStateRegistry.sol | 3 ++- src/payments/PayMaster.sol | 2 ++ src/payments/PaymentHelper.sol | 4 +++- src/settings/SuperRBAC.sol | 5 +++-- src/settings/SuperRegistry.sol | 21 +++++++++++++++++-- 49 files changed, 127 insertions(+), 56 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index f89c61f30..e6bd9894c 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -13,9 +13,10 @@ import { ERC165 } from "openzeppelin-contracts/contracts/utils/introspection/ERC import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; /// @title BaseForm -/// @author Zeropoint Labs. /// @dev Abstract contract to be inherited by different form implementations +/// @author Zeropoint Labs abstract contract BaseForm is IBaseForm, Initializable, ERC165 { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/BaseRouter.sol b/src/BaseRouter.sol index 794c9f14b..dd5a06a01 100644 --- a/src/BaseRouter.sol +++ b/src/BaseRouter.sol @@ -9,10 +9,11 @@ import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title BaseRouter -/// @author Zeropoint Labs. /// @dev Routes users funds and action information to a remote execution chain. /// @dev abstract implementation that allows inheriting contract to implement the logic +/// @author Zeropoint Labs abstract contract BaseRouter is IBaseRouter { + using SafeERC20 for IERC20; ////////////////////////////////////////////////////////////// diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index c5ade124b..f7b3d247f 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -22,9 +22,10 @@ import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IE import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol"; /// @title BaseRouterImplementation -/// @author Zeropoint Labs /// @dev Extends BaseRouter with standard internal execution functions +/// @author Zeropoint Labs abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRouter, LiquidityHandler { + using SafeERC20 for IERC20; using DataLib for uint256; diff --git a/src/EmergencyQueue.sol b/src/EmergencyQueue.sol index 8ff3b75b8..3aca68e4a 100644 --- a/src/EmergencyQueue.sol +++ b/src/EmergencyQueue.sol @@ -11,9 +11,10 @@ import { Error } from "src/libraries/Error.sol"; import "src/types/DataTypes.sol"; /// @title EmergencyQueue -/// @author Zeropoint Labs /// @dev stores withdrawal requests when forms are paused +/// @author Zeropoint Labs contract EmergencyQueue is IEmergencyQueue { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index 656573589..a23a5afcc 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -26,6 +26,7 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol /// @dev Cross-chain LP token minted on source chain /// @author Zeropoint Labs contract SuperPositions is ISuperPositions, ERC1155A { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index b2a9d6bd5..a030ce8df 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -18,6 +18,7 @@ import { Clones } from "openzeppelin-contracts/contracts/proxy/Clones.sol"; /// @dev Central point of read & write access for all Superforms on this chain /// @author Zeropoint Labs contract SuperformFactory is ISuperformFactory { + using DataLib for uint256; using Clones for address; diff --git a/src/SuperformRouter.sol b/src/SuperformRouter.sol index 23216e54a..ec0f312ee 100644 --- a/src/SuperformRouter.sol +++ b/src/SuperformRouter.sol @@ -8,8 +8,9 @@ import "src/types/DataTypes.sol"; /// @title SuperformRouter /// @dev Routes funds and action information to a remote execution chain -/// @author Zeropoint Labs. +/// @author Zeropoint Labs contract SuperformRouter is BaseRouterImplementation { + ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/BaseStateRegistry.sol b/src/crosschain-data/BaseStateRegistry.sol index 684203927..85669ad05 100644 --- a/src/crosschain-data/BaseStateRegistry.sol +++ b/src/crosschain-data/BaseStateRegistry.sol @@ -16,6 +16,7 @@ import { PayloadState, AMBMessage, AMBExtraData } from "src/types/DataTypes.sol" /// @dev payloads (messages). Inheriting children contracts have the flexibility to define their own processing /// mechanisms. abstract contract BaseStateRegistry is IBaseStateRegistry { + using ProofLib for AMBMessage; using ProofLib for bytes; diff --git a/src/crosschain-data/BroadcastRegistry.sol b/src/crosschain-data/BroadcastRegistry.sol index bf7b2abc4..30a27854b 100644 --- a/src/crosschain-data/BroadcastRegistry.sol +++ b/src/crosschain-data/BroadcastRegistry.sol @@ -17,10 +17,11 @@ interface Target { /// @author ZeroPoint Labs /// @notice helps core contract communicate with multiple dst chains through supported AMBs contract BroadcastRegistry is IBroadcastRegistry { + using ProofLib for bytes; ////////////////////////////////////////////////////////////// - // CONSTANTS // + // CONSTANTS // ////////////////////////////////////////////////////////////// ISuperRegistry public immutable superRegistry; diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index f7c11e763..8181241ae 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -14,9 +14,10 @@ import { IInterchainGasPaymaster } from "src/vendor/hyperlane/IInterchainGasPaym import { StandardHookMetadata } from "src/vendor/hyperlane/StandardHookMetadata.sol"; /// @title HyperlaneImplementation -/// @author Zeropoint Labs /// @dev allows state registries to use hyperlane for crosschain communication +/// @author Zeropoint Labs contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index 27a4f0a32..d87ea4972 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -13,9 +13,10 @@ import { ILayerZeroReceiver } from "src/vendor/layerzero/ILayerZeroReceiver.sol" import { ILayerZeroUserApplicationConfig } from "src/vendor/layerzero/ILayerZeroUserApplicationConfig.sol"; /// @title LayerzeroImplementation -/// @author Zeropoint Labs /// @dev allows state registries to use Layerzero for crosschain communication +/// @author Zeropoint Labs contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicationConfig, ILayerZeroReceiver { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 7ed5a4e40..5b450a383 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -13,10 +13,10 @@ import { IWormholeReceiver } from "src/vendor/wormhole/IWormholeReceiver.sol"; import "src/vendor/wormhole/Utils.sol"; /// @title WormholeImplementation -/// @author Zeropoint Labs -/// @notice allows state registries to use wormhole for crosschain communication /// @dev uses automatic relayers of wormhole for 1:1 messaging +/// @author Zeropoint Labs contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol index c774fa779..1888f92b4 100644 --- a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol @@ -11,10 +11,10 @@ import { IWormhole } from "src/vendor/wormhole/IWormhole.sol"; import "src/vendor/wormhole/Utils.sol"; /// @title WormholeImplementation +/// @dev uses multicast of wormhole for broadcasting to multiple chains /// @author Zeropoint Labs -/// @notice allows broadcast state registry contracts to send messages to multiple chains -/// @dev uses multicast of wormhole for broadcasting contract WormholeSRImplementation is IBroadcastAmbImplementation { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index bb550b987..c2ffb1514 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -31,10 +31,10 @@ import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol" import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title CoreStateRegistry -/// @author Zeropoint Labs /// @dev enables communication between Superform Core Contracts deployed on all supported networks - +/// @author Zeropoint Labs contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { + using SafeERC20 for IERC20; using DataLib for uint256; using ProofLib for AMBMessage; diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index 1f93da7c2..af76b6b0b 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -21,10 +21,10 @@ import "src/types/DataTypes.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; /// @title TimelockStateRegistry +/// @dev handles communication in timelocked forms /// @author Zeropoint Labs -/// @notice handles communication in timelocked forms - contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, ReentrancyGuard { + using DataLib for uint256; using ProofLib for AMBMessage; diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 2d218cd14..688d0c53f 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -21,9 +21,10 @@ import { } from "src/types/DataTypes.sol"; /// @title PayloadHelper +/// @dev helps decode payload data for off-chain purposes /// @author ZeroPoint Labs -/// @dev helps decode payload data more easily. Used for off-chain purposes contract PayloadHelper is IPayloadHelper { + using DataLib for uint256; ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/utils/QuorumManager.sol b/src/crosschain-data/utils/QuorumManager.sol index 44240c003..b2b6d1ab2 100644 --- a/src/crosschain-data/utils/QuorumManager.sol +++ b/src/crosschain-data/utils/QuorumManager.sol @@ -9,6 +9,7 @@ import { Error } from "src/libraries/Error.sol"; /// @dev separates quorum management concerns into an abstract contract. Can be re-used (currently used by /// superRegistry) to set different quorums per amb in different areas of the protocol abstract contract QuorumManager is IQuorumManager { + ////////////////////////////////////////////////////////////// // STATE VARIABLES // ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-liquidity/BridgeValidator.sol b/src/crosschain-liquidity/BridgeValidator.sol index 1dfab79eb..ea87a6756 100644 --- a/src/crosschain-liquidity/BridgeValidator.sol +++ b/src/crosschain-liquidity/BridgeValidator.sol @@ -6,14 +6,16 @@ import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; import { Error } from "src/libraries/Error.sol"; /// @title BridgeValidator -/// @author Zeropoint Labs /// @dev To be inherited by specific bridge handlers to verify the calldata being sent +/// @author Zeropoint Labs abstract contract BridgeValidator is IBridgeValidator { + ////////////////////////////////////////////////////////////// - // CONSTANTS // + // CONSTANTS // ////////////////////////////////////////////////////////////// + ISuperRegistry public immutable superRegistry; - address immutable NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index adc610573..c3195ddb7 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -12,6 +12,7 @@ import { StandardizedCallFacet } from "src/vendor/lifi/StandardizedCallFacet.sol /// @author Zeropoint Labs /// @dev To assert LiFi input txData is valid contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { + ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index 2da6b44a9..8a189d4fd 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -6,9 +6,10 @@ import { Error } from "src/libraries/Error.sol"; import { ISocketOneInchImpl } from "src/vendor/socket/ISocketOneInchImpl.sol"; /// @title SocketOneInchValidator -/// @author Zeropoint Labs /// @dev to assert input Socket same-chain txData is valid +/// @author Zeropoint Labs contract SocketOneInchValidator is BridgeValidator { + ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index c9b33860c..d50f5d0fa 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -6,9 +6,10 @@ import { Error } from "src/libraries/Error.sol"; import { ISocketRegistry } from "src/vendor/socket/ISocketRegistry.sol"; /// @title SocketValidator -/// @author Zeropoint Labs /// @dev to assert input Socket x-chain txData is valid +/// @author Zeropoint Labs contract SocketValidator is BridgeValidator { + ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index 11a1c05f6..bd80e103c 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -6,13 +6,15 @@ import { BaseForm } from "src/BaseForm.sol"; import { InitSingleVaultData } from "src/types/DataTypes.sol"; /// @title ERC4626Form -/// @notice The Form implementation for IERC4626 vaults +/// @dev The Form implementation for IERC4626 vaults +/// @author Zeropoint Labs contract ERC4626Form is ERC4626FormImplementation { + ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - uint8 constant stateRegistryId = 1; // CoreStateRegistry + uint8 immutable stateRegistryId = 1; // CoreStateRegistry ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index e8a2825db..c77de1765 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -13,8 +13,10 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; /// @title ERC4626FormImplementation -/// @notice Has common internal functions that can be re-used by actual form implementations +/// @dev Has common internal functions that can be re-used by actual form implementations +/// @author Zeropoint Labs abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { + using SafeERC20 for IERC20; using SafeERC20 for IERC4626; using DataLib for uint256; diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index 7d0efefb0..0805d203b 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -12,14 +12,16 @@ import { ERC721Holder } from "openzeppelin-contracts/contracts/token/ERC721/util /// @title ERC4626KYCDaoForm -/// @notice The Form implementation for IERC4626 vaults with kycDAO NFT checks -/// @notice This form must hold a kycDAO NFT to operate +/// @dev The Form implementation for IERC4626 vaults with kycDAO NFT checks +/// @dev This form must hold a kycDAO NFT to operate +/// @author Zeropoint Labs contract ERC4626KYCDaoForm is ERC4626FormImplementation, ERC721Holder { + ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - uint8 constant stateRegistryId = 1; // CoreStateRegistry + uint8 immutable stateRegistryId = 1; // CoreStateRegistry ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 1d565f2aa..c5d9a7df5 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -15,7 +15,9 @@ import { IERC4626TimelockVault } from "super-vaults/interfaces/IERC4626TimelockV /// @title ERC4626TimelockForm /// @notice Form implementation to handle timelock extension for ERC4626 vaults +/// @author Zeropoint Labs contract ERC4626TimelockForm is ERC4626FormImplementation { + using SafeERC20 for IERC20; using SafeERC20 for IERC4626TimelockVault; using DataLib for uint256; @@ -24,7 +26,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { // CONSTANTS // ////////////////////////////////////////////////////////////// - uint8 constant stateRegistryId = 2; // TimelockStateRegistry + uint8 immutable stateRegistryId = 2; // TimelockStateRegistry ////////////////////////////////////////////////////////////// // STRUCTS // diff --git a/src/interfaces/IAmbImplementation.sol b/src/interfaces/IAmbImplementation.sol index bd56af57a..9928298cc 100644 --- a/src/interfaces/IAmbImplementation.sol +++ b/src/interfaces/IAmbImplementation.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.23; /// @title IAmbImplementation -/// @author ZeroPoint Labs /// @dev interface for arbitrary message bridge implementation +/// @author ZeroPoint Labs interface IAmbImplementation { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBaseForm.sol b/src/interfaces/IBaseForm.sol index d506642c1..4a298a947 100644 --- a/src/interfaces/IBaseForm.sol +++ b/src/interfaces/IBaseForm.sol @@ -6,9 +6,10 @@ import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IE import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; /// @title IBaseForm +/// @dev Interface for BaseForm /// @author ZeroPoint Labs -/// @notice Interface for Base Form interface IBaseForm is IERC165 { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBaseRouter.sol b/src/interfaces/IBaseRouter.sol index 427275d34..4e6683836 100644 --- a/src/interfaces/IBaseRouter.sol +++ b/src/interfaces/IBaseRouter.sol @@ -4,9 +4,10 @@ pragma solidity ^0.8.23; import "src/types/DataTypes.sol"; /// @title IBaseRouter -/// @author Zeropoint Labs. /// @dev interface for abstract Router +/// @author Zeropoint Labs interface IBaseRouter { + ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBaseRouterImplementation.sol b/src/interfaces/IBaseRouterImplementation.sol index d35003619..619c12f16 100644 --- a/src/interfaces/IBaseRouterImplementation.sol +++ b/src/interfaces/IBaseRouterImplementation.sol @@ -5,9 +5,10 @@ import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import "src/types/DataTypes.sol"; /// @title IBaseRouterImplementation -/// @author Zeropoint Labs. /// @dev interface for BaseRouterImplementation +/// @author Zeropoint Labs interface IBaseRouterImplementation is IBaseRouter { + ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBaseStateRegistry.sol b/src/interfaces/IBaseStateRegistry.sol index ea742f5b4..929475d7d 100644 --- a/src/interfaces/IBaseStateRegistry.sol +++ b/src/interfaces/IBaseStateRegistry.sol @@ -4,9 +4,10 @@ pragma solidity ^0.8.23; import "src/types/DataTypes.sol"; /// @title IBaseStateRegistry +/// @dev Crosschain interaction point: send, store & process crosschain messages /// @author ZeroPoint Labs -/// @dev Is the crosschain interaction point. Send, store & process crosschain messages interface IBaseStateRegistry { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBridgeValidator.sol b/src/interfaces/IBridgeValidator.sol index 6a9c97100..229f39bbe 100644 --- a/src/interfaces/IBridgeValidator.sol +++ b/src/interfaces/IBridgeValidator.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -/// @title Bridge Handler Interface +/// @title Bridge Validator Interface +/// @dev Validate and handle bridging of tokens /// @author Zeropoint Labs interface IBridgeValidator { + ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBroadcastAmbImplementation.sol b/src/interfaces/IBroadcastAmbImplementation.sol index d9a3b1507..55e20b6df 100644 --- a/src/interfaces/IBroadcastAmbImplementation.sol +++ b/src/interfaces/IBroadcastAmbImplementation.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.23; /// @title IBroadcastAmbImplementation -/// @author ZeroPoint Labs /// @dev interface for arbitrary message bridge implementation the supports broadcasting +/// @author ZeroPoint Labs interface IBroadcastAmbImplementation { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBroadcastRegistry.sol b/src/interfaces/IBroadcastRegistry.sol index 1eb6ab438..31d586a93 100644 --- a/src/interfaces/IBroadcastRegistry.sol +++ b/src/interfaces/IBroadcastRegistry.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.23; /// @title IBroadcastRegistry +/// @dev is an helper for base state registry with broadcasting abilities /// @author ZeroPoint Labs -/// @dev is an helper for base state registry with broadcasting abilities. interface IBroadcastRegistry { + ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ICoreStateRegistry.sol b/src/interfaces/ICoreStateRegistry.sol index 119706f34..4a79d6274 100644 --- a/src/interfaces/ICoreStateRegistry.sol +++ b/src/interfaces/ICoreStateRegistry.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.23; /// @title ICoreStateRegistry +/// @dev Interface for Core State Registry /// @author ZeroPoint Labs -/// @notice Interface for Core State Registry interface ICoreStateRegistry { + ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IDstSwapper.sol b/src/interfaces/IDstSwapper.sol index dbb960c88..58ee5d714 100644 --- a/src/interfaces/IDstSwapper.sol +++ b/src/interfaces/IDstSwapper.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.23; /// @title IDstSwapper +/// @dev handles all destination chain swaps, accessed by superform keepers /// @author Zeropoint Labs -/// @dev handles all destination chain swaps. -/// @notice all write functions can only be accessed by superform keepers. interface IDstSwapper { + ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IEmergencyQueue.sol b/src/interfaces/IEmergencyQueue.sol index adb3ba5cf..bd6c307ec 100644 --- a/src/interfaces/IEmergencyQueue.sol +++ b/src/interfaces/IEmergencyQueue.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.23; import { InitSingleVaultData } from "src/types/DataTypes.sol"; interface IEmergencyQueue { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IPayMaster.sol b/src/interfaces/IPayMaster.sol index d0a39c02d..6b067bf50 100644 --- a/src/interfaces/IPayMaster.sol +++ b/src/interfaces/IPayMaster.sol @@ -4,9 +4,10 @@ pragma solidity ^0.8.23; import { LiqRequest } from "src/types/DataTypes.sol"; /// @title IPayMaster -/// @author ZeroPoint Labs /// @dev contract for destination transaction costs payment +/// @author ZeroPoint Labs interface IPayMaster { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index a8d198db2..2fda98bb3 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.23; /// @title IPayloadHelper -/// @author ZeroPoint Labs /// @dev helps decoding the bytes payload and returns meaningful information +/// @author ZeroPoint Labs interface IPayloadHelper { + ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IPaymentHelper.sol b/src/interfaces/IPaymentHelper.sol index 4bf7ab0c8..5217d9d78 100644 --- a/src/interfaces/IPaymentHelper.sol +++ b/src/interfaces/IPaymentHelper.sol @@ -11,9 +11,10 @@ import { } from "src/types/DataTypes.sol"; /// @title IPaymentHelper -/// @author ZeroPoint Labs /// @dev helps decoding the bytes payload and returns meaningful information +/// @author ZeroPoint Labs interface IPaymentHelper { + ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IQuorumManager.sol b/src/interfaces/IQuorumManager.sol index 53a6460c1..1f632fd25 100644 --- a/src/interfaces/IQuorumManager.sol +++ b/src/interfaces/IQuorumManager.sol @@ -1,7 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; +/// @title IQuorumManager +/// @dev interface to manage the quorum needed to send messages from chain to chain +/// @author ZeroPoint Labs interface IQuorumManager { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ISuperPositions.sol b/src/interfaces/ISuperPositions.sol index c2dcdd517..a88d07184 100644 --- a/src/interfaces/ISuperPositions.sol +++ b/src/interfaces/ISuperPositions.sol @@ -5,11 +5,12 @@ import { IERC1155A } from "ERC1155A/interfaces/IERC1155A.sol"; import { AMBMessage } from "../types/DataTypes.sol"; /// @title ISuperPositions -/// @author Zeropoint Labs. -/// @dev interface for Super Positions +/// @dev interface for SuperPositions +/// @author Zeropoint Labs interface ISuperPositions is IERC1155A { + ////////////////////////////////////////////////////////////// - // STRUCTS // + // STRUCTS // ////////////////////////////////////////////////////////////// struct TxHistory { diff --git a/src/interfaces/ISuperRBAC.sol b/src/interfaces/ISuperRBAC.sol index 5aca2d92b..8ad7debd5 100644 --- a/src/interfaces/ISuperRBAC.sol +++ b/src/interfaces/ISuperRBAC.sol @@ -4,9 +4,10 @@ pragma solidity ^0.8.23; import { IAccessControl } from "openzeppelin-contracts/contracts/access/IAccessControl.sol"; /// @title ISuperRBAC -/// @author Zeropoint Labs. /// @dev interface for Super RBAC +/// @author Zeropoint Labs interface ISuperRBAC is IAccessControl { + ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ISuperRegistry.sol b/src/interfaces/ISuperRegistry.sol index bc1171c43..6c4f265f5 100644 --- a/src/interfaces/ISuperRegistry.sol +++ b/src/interfaces/ISuperRegistry.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.23; /// @title ISuperRegistry -/// @author Zeropoint Labs. -/// @dev interface for Super Registry +/// @dev interface for SuperRegistry +/// @author Zeropoint Labs interface ISuperRegistry { + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ISuperformFactory.sol b/src/interfaces/ISuperformFactory.sol index ad4a2237f..b3fb7022a 100644 --- a/src/interfaces/ISuperformFactory.sol +++ b/src/interfaces/ISuperformFactory.sol @@ -2,9 +2,10 @@ pragma solidity ^0.8.23; /// @title ISuperformFactory +/// @dev Interface for Superform Factory /// @author ZeroPoint Labs -/// @notice Interface for Superform Factory interface ISuperformFactory { + ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/ITimelockStateRegistry.sol b/src/interfaces/ITimelockStateRegistry.sol index cbd13c728..215b0f999 100644 --- a/src/interfaces/ITimelockStateRegistry.sol +++ b/src/interfaces/ITimelockStateRegistry.sol @@ -4,9 +4,10 @@ pragma solidity ^0.8.23; import { InitSingleVaultData, TimelockPayload } from "src/types/DataTypes.sol"; /// @title ITimelockStateRegistry +/// @dev Interface for Timelock Form State Registry /// @author ZeroPoint Labs -/// @notice Interface for Timelock Form State Registry interface ITimelockStateRegistry { + ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index a8fb0d33a..f690fc0e8 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -13,8 +13,10 @@ import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title PayMaster +/// @dev manages cross-chain payments and rebalancing of funds /// @author ZeroPoint Labs contract PayMaster is IPayMaster, LiquidityHandler { + using SafeERC20 for IERC20; ////////////////////////////////////////////////////////////// diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 16d3d2038..c301b7461 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -20,9 +20,10 @@ interface ReadOnlyBaseRegistry is IBaseStateRegistry { } /// @title PaymentHelper -/// @author ZeroPoint Labs /// @dev helps estimating the cost for the entire transaction lifecycle +/// @author ZeroPoint Labs contract PaymentHelper is IPaymentHelper { + using DataLib for uint256; using ArrayCastLib for LiqRequest; using ArrayCastLib for bool; @@ -32,6 +33,7 @@ contract PaymentHelper is IPaymentHelper { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// + uint256 private constant PROOF_LENGTH = 160; uint8 private constant SUPPORTED_FEED_PRECISION = 8; uint32 private constant TIMELOCK_FORM_ID = 2; diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index d80959c4e..1781f6e3f 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -9,9 +9,10 @@ import { BroadcastMessage } from "src/types/DataTypes.sol"; import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol"; /// @title SuperRBAC -/// @author Zeropoint Labs. -/// @dev Contract to manage roles in the entire superform protocol +/// @dev contract to manage roles in the entire superform protocol +/// @author Zeropoint Labs contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { + ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index e3c031ecb..9be2a685f 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -7,9 +7,10 @@ import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { Error } from "src/libraries/Error.sol"; /// @title SuperRegistry -/// @author Zeropoint Labs. -/// @dev Keeps information on all addresses used in the Superforms ecosystem. +/// @dev Keeps information on all addresses used in the Superform ecosystem +/// @author Zeropoint Labs contract SuperRegistry is ISuperRegistry, QuorumManager { + ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// @@ -21,44 +22,60 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { /// @dev core protocol - identifiers /// @notice should not be allowed to be changed bytes32 public constant override SUPERFORM_ROUTER = keccak256("SUPERFORM_ROUTER"); + /// @dev can be used to set a new factory that has form ids paused /// @notice should not be allowed to be changed bytes32 public constant override SUPERFORM_FACTORY = keccak256("SUPERFORM_FACTORY"); + /// @dev not accessed in protocol /// @dev could be allowed to be changed bytes32 public constant override SUPER_TRANSMUTER = keccak256("SUPER_TRANSMUTER"); + /// @dev can be used to set a new paymaster to forward payments to /// @dev could be allowed to be changed bytes32 public constant override PAYMASTER = keccak256("PAYMASTER"); + /// @dev accessed in some areas of the protocol to calculate AMB fees. Already has a function to alter the /// configuration /// @dev could be allowed to be changed bytes32 public constant override PAYMENT_HELPER = keccak256("PAYMENT_HELPER"); + /// @dev accessed in many areas of the protocol. has direct access to superforms /// @notice should not be allowed to be changed bytes32 public constant override CORE_STATE_REGISTRY = keccak256("CORE_STATE_REGISTRY"); + /// @dev accessed in many areas of the protocol. has direct access to timelock form /// @notice should not be allowed to be changed bytes32 public constant override TIMELOCK_STATE_REGISTRY = keccak256("TIMELOCK_STATE_REGISTRY"); + /// @dev used to sync messages for pausing superforms or deploying transmuters /// @notice should not be allowed to be changed bytes32 public constant override BROADCAST_REGISTRY = keccak256("BROADCAST_REGISTRY"); + /// @dev not accessed in protocol /// @notice should not be allowed to be changed bytes32 public constant override SUPER_POSITIONS = keccak256("SUPER_POSITIONS"); + /// @dev accessed in many areas of the protocol /// @notice should not be allowed to be changed bytes32 public constant override SUPER_RBAC = keccak256("SUPER_RBAC"); + /// @dev not accessed in protocol /// @dev could be allowed to be changed bytes32 public constant override PAYLOAD_HELPER = keccak256("PAYLOAD_HELPER"); + /// @dev accessed in CSR and validators. can be used to alter behaviour of update deposit payloads /// @notice should not be allowed to be changed bytes32 public constant override DST_SWAPPER = keccak256("DST_SWAPPER"); + /// @dev accessed in base form to send payloads to emergency queue /// @notice should not be allowed to be changed bytes32 public constant override EMERGENCY_QUEUE = keccak256("EMERGENCY_QUEUE"); + + /// @dev receiver of bridge refunds and airdropped tokens + /// @notice should not be allowed to be changed bytes32 public constant override SUPERFORM_RECEIVER = keccak256("SUPERFORM_RECEIVER"); + /// @dev default keepers - identifiers /// @dev could be allowed to be changed bytes32 public constant override PAYMENT_ADMIN = keccak256("PAYMENT_ADMIN"); From 1a9863abb66122cbd6068322839153dc543e9bc3 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Sun, 24 Dec 2023 14:57:09 -0600 Subject: [PATCH 170/210] chore: contract decorators --- src/BaseForm.sol | 2 +- src/EmergencyQueue.sol | 2 +- src/crosschain-data/BaseStateRegistry.sol | 6 +++--- src/crosschain-data/BroadcastRegistry.sol | 2 +- .../adapters/hyperlane/HyperlaneImplementation.sol | 2 +- .../adapters/layerzero/LayerzeroImplementation.sol | 2 +- .../automatic-relayer/WormholeARImplementation.sol | 2 +- .../specialized-relayer/WormholeSRImplementation.sol | 2 +- src/crosschain-data/extensions/CoreStateRegistry.sol | 2 +- .../extensions/TimelockStateRegistry.sol | 2 +- src/crosschain-data/utils/PayloadHelper.sol | 2 +- src/crosschain-data/utils/QuorumManager.sol | 3 +-- src/crosschain-liquidity/BridgeValidator.sol | 2 +- src/crosschain-liquidity/DstSwapper.sol | 4 ++-- src/crosschain-liquidity/LiquidityHandler.sol | 11 +++++------ src/crosschain-liquidity/lifi/LiFiValidator.sol | 2 +- .../socket/SocketOneInchValidator.sol | 2 +- src/crosschain-liquidity/socket/SocketValidator.sol | 2 +- src/forms/ERC4626TimelockForm.sol | 2 +- src/forms/interfaces/IERC4626Form.sol | 2 ++ src/forms/interfaces/IERC4626TimelockForm.sol | 3 +-- src/payments/PayMaster.sol | 2 +- src/payments/PaymentHelper.sol | 2 +- src/settings/SuperRBAC.sol | 2 +- 24 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index e6bd9894c..3c98c27c0 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -13,7 +13,7 @@ import { ERC165 } from "openzeppelin-contracts/contracts/utils/introspection/ERC import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; /// @title BaseForm -/// @dev Abstract contract to be inherited by different form implementations +/// @dev Abstract contract to be inherited by different Form implementations /// @author Zeropoint Labs abstract contract BaseForm is IBaseForm, Initializable, ERC165 { diff --git a/src/EmergencyQueue.sol b/src/EmergencyQueue.sol index 3aca68e4a..87ea05a28 100644 --- a/src/EmergencyQueue.sol +++ b/src/EmergencyQueue.sol @@ -11,7 +11,7 @@ import { Error } from "src/libraries/Error.sol"; import "src/types/DataTypes.sol"; /// @title EmergencyQueue -/// @dev stores withdrawal requests when forms are paused +/// @dev Stores withdrawal requests when forms are paused /// @author Zeropoint Labs contract EmergencyQueue is IEmergencyQueue { diff --git a/src/crosschain-data/BaseStateRegistry.sol b/src/crosschain-data/BaseStateRegistry.sol index 85669ad05..7d68d7172 100644 --- a/src/crosschain-data/BaseStateRegistry.sol +++ b/src/crosschain-data/BaseStateRegistry.sol @@ -10,11 +10,11 @@ import { ProofLib } from "src/libraries/ProofLib.sol"; import { PayloadState, AMBMessage, AMBExtraData } from "src/types/DataTypes.sol"; /// @title BaseStateRegistry -/// @author Zeropoint Labs -/// @dev contract module that allows inheriting contracts to implement crosschain messaging & processing mechanisms. -/// @dev This is a lightweight version that allows only dispatching and receiving crosschain +/// @dev Contract module that allows inheriting contracts to implement crosschain messaging & processing mechanisms. +/// @dev this is a lightweight version that allows only dispatching and receiving crosschain /// @dev payloads (messages). Inheriting children contracts have the flexibility to define their own processing /// mechanisms. +/// @author Zeropoint Labs abstract contract BaseStateRegistry is IBaseStateRegistry { using ProofLib for AMBMessage; diff --git a/src/crosschain-data/BroadcastRegistry.sol b/src/crosschain-data/BroadcastRegistry.sol index 30a27854b..5d8ecccf6 100644 --- a/src/crosschain-data/BroadcastRegistry.sol +++ b/src/crosschain-data/BroadcastRegistry.sol @@ -14,8 +14,8 @@ interface Target { } /// @title BroadcastRegistry +/// @dev Helps core contracts communicate with multiple dst chains through supported AMBs /// @author ZeroPoint Labs -/// @notice helps core contract communicate with multiple dst chains through supported AMBs contract BroadcastRegistry is IBroadcastRegistry { using ProofLib for bytes; diff --git a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol index 8181241ae..ce51f0743 100644 --- a/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol +++ b/src/crosschain-data/adapters/hyperlane/HyperlaneImplementation.sol @@ -14,7 +14,7 @@ import { IInterchainGasPaymaster } from "src/vendor/hyperlane/IInterchainGasPaym import { StandardHookMetadata } from "src/vendor/hyperlane/StandardHookMetadata.sol"; /// @title HyperlaneImplementation -/// @dev allows state registries to use hyperlane for crosschain communication +/// @dev Allows state registries to use Hyperlane v3 for crosschain communication /// @author Zeropoint Labs contract HyperlaneImplementation is IAmbImplementation, IMessageRecipient { diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index d87ea4972..c3c51b212 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -13,7 +13,7 @@ import { ILayerZeroReceiver } from "src/vendor/layerzero/ILayerZeroReceiver.sol" import { ILayerZeroUserApplicationConfig } from "src/vendor/layerzero/ILayerZeroUserApplicationConfig.sol"; /// @title LayerzeroImplementation -/// @dev allows state registries to use Layerzero for crosschain communication +/// @dev Allows state registries to use Layerzero for crosschain communication /// @author Zeropoint Labs contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicationConfig, ILayerZeroReceiver { diff --git a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol index 5b450a383..2c4d46354 100644 --- a/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/automatic-relayer/WormholeARImplementation.sol @@ -13,7 +13,7 @@ import { IWormholeReceiver } from "src/vendor/wormhole/IWormholeReceiver.sol"; import "src/vendor/wormhole/Utils.sol"; /// @title WormholeImplementation -/// @dev uses automatic relayers of wormhole for 1:1 messaging +/// @dev Allows state registries to use Wormhole AR's for crosschain communication /// @author Zeropoint Labs contract WormholeARImplementation is IAmbImplementation, IWormholeReceiver { diff --git a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol index 1888f92b4..b469c0656 100644 --- a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol @@ -11,7 +11,7 @@ import { IWormhole } from "src/vendor/wormhole/IWormhole.sol"; import "src/vendor/wormhole/Utils.sol"; /// @title WormholeImplementation -/// @dev uses multicast of wormhole for broadcasting to multiple chains +/// @dev Allows state registries to use Wormhole SR's for broadcasting /// @author Zeropoint Labs contract WormholeSRImplementation is IBroadcastAmbImplementation { diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index c2ffb1514..81a252b15 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -31,7 +31,7 @@ import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol" import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title CoreStateRegistry -/// @dev enables communication between Superform Core Contracts deployed on all supported networks +/// @dev Enables communication between Superform core contracts deployed on all supported networks /// @author Zeropoint Labs contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index af76b6b0b..88b331ed8 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -21,7 +21,7 @@ import "src/types/DataTypes.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; /// @title TimelockStateRegistry -/// @dev handles communication in timelocked forms +/// @dev Handles communication in timelocked forms /// @author Zeropoint Labs contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, ReentrancyGuard { diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 688d0c53f..efbc9e853 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -21,7 +21,7 @@ import { } from "src/types/DataTypes.sol"; /// @title PayloadHelper -/// @dev helps decode payload data for off-chain purposes +/// @dev Helps decode payload data for off-chain purposes /// @author ZeroPoint Labs contract PayloadHelper is IPayloadHelper { diff --git a/src/crosschain-data/utils/QuorumManager.sol b/src/crosschain-data/utils/QuorumManager.sol index b2b6d1ab2..185a411ef 100644 --- a/src/crosschain-data/utils/QuorumManager.sol +++ b/src/crosschain-data/utils/QuorumManager.sol @@ -5,9 +5,8 @@ import { IQuorumManager } from "src/interfaces/IQuorumManager.sol"; import { Error } from "src/libraries/Error.sol"; /// @title QuorumManager +/// @dev Quorum management to send messages from chain to chain /// @author ZeroPoint Labs -/// @dev separates quorum management concerns into an abstract contract. Can be re-used (currently used by -/// superRegistry) to set different quorums per amb in different areas of the protocol abstract contract QuorumManager is IQuorumManager { ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-liquidity/BridgeValidator.sol b/src/crosschain-liquidity/BridgeValidator.sol index ea87a6756..42314e148 100644 --- a/src/crosschain-liquidity/BridgeValidator.sol +++ b/src/crosschain-liquidity/BridgeValidator.sol @@ -6,7 +6,7 @@ import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; import { Error } from "src/libraries/Error.sol"; /// @title BridgeValidator -/// @dev To be inherited by specific bridge handlers to verify the calldata being sent +/// @dev Inherited by specific bridge handlers to verify the calldata being sent /// @author Zeropoint Labs abstract contract BridgeValidator is IBridgeValidator { diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 144360080..ae677d7b4 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -16,8 +16,8 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; /// @title DstSwapper -/// @author Zeropoint Labs. -/// @dev handles all destination chain swaps. +/// @dev Handles all destination chain swaps +/// @author Zeropoint Labs contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { using SafeERC20 for IERC20; diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index 1b70c702a..1475c3a07 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -5,13 +5,12 @@ import { Error } from "src/libraries/Error.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -/** - * @title LiquidityHandler - * @author Zeropoint Labs. - * @dev Executes an action with tokens to either bridge from Chain A -> Chain B or swap on same chain. - * @dev To be inherited by contracts that move liquidity - */ +/// @title LiquidityHandler +/// @dev Executes an action with tokens to either bridge from Chain A -> Chain B or swap on same chain +/// @dev To be inherited by contracts that move liquidity +/// @author ZeroPoint Labs abstract contract LiquidityHandler { + using SafeERC20 for IERC20; ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index c3195ddb7..f9c7585b7 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -9,8 +9,8 @@ import { ILiFi } from "src/vendor/lifi/ILiFi.sol"; import { StandardizedCallFacet } from "src/vendor/lifi/StandardizedCallFacet.sol"; /// @title LiFiValidator +/// @dev Asserts LiFi input txData is valid /// @author Zeropoint Labs -/// @dev To assert LiFi input txData is valid contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol index 8a189d4fd..e4b55a2d6 100644 --- a/src/crosschain-liquidity/socket/SocketOneInchValidator.sol +++ b/src/crosschain-liquidity/socket/SocketOneInchValidator.sol @@ -6,7 +6,7 @@ import { Error } from "src/libraries/Error.sol"; import { ISocketOneInchImpl } from "src/vendor/socket/ISocketOneInchImpl.sol"; /// @title SocketOneInchValidator -/// @dev to assert input Socket same-chain txData is valid +/// @dev Asserts Socket same-chain txData is valid /// @author Zeropoint Labs contract SocketOneInchValidator is BridgeValidator { diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index d50f5d0fa..4355cbe52 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -6,7 +6,7 @@ import { Error } from "src/libraries/Error.sol"; import { ISocketRegistry } from "src/vendor/socket/ISocketRegistry.sol"; /// @title SocketValidator -/// @dev to assert input Socket x-chain txData is valid +/// @dev Asserts Socket x-chain input txData is valid /// @author Zeropoint Labs contract SocketValidator is BridgeValidator { diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index c5d9a7df5..e2b716431 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -14,7 +14,7 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa import { IERC4626TimelockVault } from "super-vaults/interfaces/IERC4626TimelockVault.sol"; /// @title ERC4626TimelockForm -/// @notice Form implementation to handle timelock extension for ERC4626 vaults +/// @dev Form implementation to handle timelock extension for ERC4626 vaults /// @author Zeropoint Labs contract ERC4626TimelockForm is ERC4626FormImplementation { diff --git a/src/forms/interfaces/IERC4626Form.sol b/src/forms/interfaces/IERC4626Form.sol index 01c100e62..dd0ff1668 100644 --- a/src/forms/interfaces/IERC4626Form.sol +++ b/src/forms/interfaces/IERC4626Form.sol @@ -4,8 +4,10 @@ pragma solidity ^0.8.23; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; /// @title IERC4626Form +/// @dev The Interface for the ERC4626Form /// @author Zeropoint Labs interface IERC4626Form is IERC20 { + ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/forms/interfaces/IERC4626TimelockForm.sol b/src/forms/interfaces/IERC4626TimelockForm.sol index 0920f87b1..951d1ee55 100644 --- a/src/forms/interfaces/IERC4626TimelockForm.sol +++ b/src/forms/interfaces/IERC4626TimelockForm.sol @@ -5,9 +5,8 @@ import { IERC4626Form } from "./IERC4626Form.sol"; import { InitSingleVaultData, TimelockPayload } from "../../types/DataTypes.sol"; /// @title IERC4626TimelockForm +/// @dev Interface used by ERC4626TimelockForm. Required by TimelockStateRegistry to call processUnlock() /// @author Zeropoint Labs -/// @notice Interface used by ERC4626TimelockForm. Required by TimelockStateRegistry to call processUnlock() -/// function interface IERC4626TimelockForm is IERC4626Form { ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/payments/PayMaster.sol b/src/payments/PayMaster.sol index f690fc0e8..a11714447 100644 --- a/src/payments/PayMaster.sol +++ b/src/payments/PayMaster.sol @@ -13,7 +13,7 @@ import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title PayMaster -/// @dev manages cross-chain payments and rebalancing of funds +/// @dev Manages cross-chain payments and rebalancing of funds /// @author ZeroPoint Labs contract PayMaster is IPayMaster, LiquidityHandler { diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index c301b7461..8474700e3 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -20,7 +20,7 @@ interface ReadOnlyBaseRegistry is IBaseStateRegistry { } /// @title PaymentHelper -/// @dev helps estimating the cost for the entire transaction lifecycle +/// @dev Helps estimate the cost for the entire transaction lifecycle /// @author ZeroPoint Labs contract PaymentHelper is IPaymentHelper { diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 1781f6e3f..86ae60e80 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -9,7 +9,7 @@ import { BroadcastMessage } from "src/types/DataTypes.sol"; import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol"; /// @title SuperRBAC -/// @dev contract to manage roles in the entire superform protocol +/// @dev Contract to manage roles in the entire superform protocol /// @author Zeropoint Labs contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { From 58a00929c0335aaa79c55301bca9026fd2d4b426 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 25 Dec 2023 14:22:42 +0530 Subject: [PATCH 171/210] chore: add commenting about _validateStateSyncer and onlyMinter --- src/SuperPositions.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index 134acdcdc..755182fea 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -68,6 +68,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { _; } + /// @dev is used in same chain case (as superform is available on the chain to validate caller) modifier onlyMinter(uint256 superformId) { address router = superRegistry.getAddress(keccak256("SUPERFORM_ROUTER")); @@ -326,6 +327,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { } /// @dev helps validate the state registry id for minting superform id + /// @dev is used in cross chain case (as superform is not available on the chain to validate caller) function _validateStateSyncer(uint256 superformId_) internal view { uint8 registryId = superRegistry.getStateRegistryId(msg.sender); _isValidStateSyncer(registryId, superformId_); From 1c95b7e99945fc6d95f267f86a02c35e4d70ef57 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 25 Dec 2023 16:35:49 +0530 Subject: [PATCH 172/210] chore: add token inputs to _updateDeposit --- .../extensions/CoreStateRegistry.sol | 48 +++++--- src/interfaces/ICoreStateRegistry.sol | 8 +- src/libraries/Error.sol | 3 + .../extensions/CoreStateRegistry.t.sol | 115 ++++++++++++++---- .../crosschain-liquidity/DstSwapper.t.sol | 31 +++-- test/unit/emergency/EmergencyQueue.t.sol | 7 +- .../superform-router/SuperformRouter.AA.t.sol | 14 ++- .../superform-router/SuperformRouter.t.sol | 12 +- test/utils/InvariantProtocolActions.sol | 24 ++-- test/utils/ProtocolActions.sol | 44 +++++-- 10 files changed, 231 insertions(+), 75 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index d22a8b4a2..c6a3cb21b 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -91,7 +91,15 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { ////////////////////////////////////////////////////////////// /// @inheritdoc ICoreStateRegistry - function updateDepositPayload(uint256 payloadId_, uint256[] calldata finalAmounts_) external virtual override { + function updateDepositPayload( + uint256 payloadId_, + address[] calldata finalTokens_, + uint256[] calldata finalAmounts_ + ) + external + virtual + override + { /// @dev validates the caller _onlyAllowedCaller(keccak256("CORE_STATE_REGISTRY_UPDATER_ROLE")); @@ -107,9 +115,11 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { PayloadState finalState; if (isMulti != 0) { - (prevPayloadBody, finalState) = _updateMultiDeposit(payloadId_, prevPayloadBody, finalAmounts_); + (prevPayloadBody, finalState) = + _updateMultiDeposit(payloadId_, prevPayloadBody, finalAmounts_, finalTokens_); } else { - (prevPayloadBody, finalState) = _updateSingleDeposit(payloadId_, prevPayloadBody, finalAmounts_[0]); + (prevPayloadBody, finalState) = + _updateSingleDeposit(payloadId_, prevPayloadBody, finalAmounts_[0], finalTokens_[0]); } /// @dev updates the payload proof @@ -405,16 +415,15 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { function _updateMultiDeposit( uint256 payloadId_, bytes memory prevPayloadBody_, - uint256[] calldata finalAmounts_ + uint256[] calldata finalAmounts_, + address[] calldata finalToken_ ) internal returns (bytes memory newPayloadBody_, PayloadState finalState_) { InitMultiVaultData memory multiVaultData = abi.decode(prevPayloadBody_, (InitMultiVaultData)); - IDstSwapper dstSwapper = IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))); uint256 arrLen = finalAmounts_.length; - /// @dev compare number of vaults to update with provided finalAmounts length if (multiVaultData.amounts.length != arrLen) { revert Error.DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH(); @@ -426,9 +435,13 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { revert Error.ZERO_AMOUNT(); } + if (_getVaultAsset(_getSuperform(multiVaultData.superformIds[i])) != finalToken_[i]) { + revert Error.INVALID_UPDATE_FINAL_TOKEN(); + } + /// @dev observe not consuming the second return value (multiVaultData.amounts[i],, validLen) = _updateAmount( - dstSwapper, + IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))), multiVaultData.hasDstSwaps[i], payloadId_, i, @@ -481,7 +494,8 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { function _updateSingleDeposit( uint256 payloadId_, bytes memory prevPayloadBody_, - uint256 finalAmount_ + uint256 finalAmount_, + address finalToken_ ) internal returns (bytes memory newPayloadBody_, PayloadState finalState_) @@ -493,6 +507,10 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { revert Error.ZERO_AMOUNT(); } + if (_getVaultAsset(_getSuperform(singleVaultData.superformId)) != finalToken_) { + revert Error.INVALID_UPDATE_FINAL_TOKEN(); + } + /// @dev observe not consuming the third return value (singleVaultData.amount, finalState_,) = _updateAmount( dstSwapper, @@ -647,8 +665,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { for (uint256 i; i < len; ++i) { if (txData_[i].length != 0 && multiVaultData_.liqData[i].txData.length == 0) { - (address superformAddress,,) = multiVaultData_.superformIds[i].getSuperform(); - superform = IBaseForm(superformAddress); + superform = IBaseForm(_getSuperform(multiVaultData_.superformIds[i])); /// @dev for withdrawals the payload update can happen on core state registry (for normal forms) /// and also can happen in timelock state registry (for timelock form) @@ -668,7 +685,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { srcChainId_, multiVaultData_.liqData[i].liqDstChainId, false, - superformAddress, + address(superform), multiVaultData_.receiverAddress, superform.getVaultAsset(), address(0) @@ -715,9 +732,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { } /// @dev Store destination payloadId_ & index in extraFormData (tbd: 1-step flow doesnt need this) - (address superform_,,) = multiVaultData.superformIds[i].getSuperform(); - - try IBaseForm(superform_).xChainWithdrawFromVault( + try IBaseForm(_getSuperform(multiVaultData.superformIds[i])).xChainWithdrawFromVault( InitSingleVaultData({ payloadId: multiVaultData.payloadId, superformId: multiVaultData.superformIds[i], @@ -864,9 +879,10 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { revert Error.SUPERFORM_ID_NONEXISTENT(); } - (address superform_,,) = singleVaultData.superformId.getSuperform(); /// @dev Withdraw from superform - try IBaseForm(superform_).xChainWithdrawFromVault(singleVaultData, srcSender_, srcChainId_) { + try IBaseForm(_getSuperform(singleVaultData.superformId)).xChainWithdrawFromVault( + singleVaultData, srcSender_, srcChainId_ + ) { // Handle the case when the external call succeeds } catch { // Handle the case when the external call reverts for whatever reason diff --git a/src/interfaces/ICoreStateRegistry.sol b/src/interfaces/ICoreStateRegistry.sol index 4d2767fcf..aae299505 100644 --- a/src/interfaces/ICoreStateRegistry.sol +++ b/src/interfaces/ICoreStateRegistry.sol @@ -65,9 +65,15 @@ interface ICoreStateRegistry { /// @dev allows accounts with {CORE_STATE_REGISTRY_UPDATER_ROLE} to modify a received cross-chain deposit payload. /// @param payloadId_ is the identifier of the cross-chain payload to be updated. + /// @param finalTokens_ is the token received by the core state registry. /// @param finalAmounts_ is the amount to be updated. /// NOTE: amounts cannot be updated beyond user specified safe slippage limit. - function updateDepositPayload(uint256 payloadId_, uint256[] calldata finalAmounts_) external; + function updateDepositPayload( + uint256 payloadId_, + address[] calldata finalTokens_, + uint256[] calldata finalAmounts_ + ) + external; /// @dev allows accounts with {CORE_STATE_REGISTRY_UPDATER_ROLE} to modify a received cross-chain withdraw payload. /// @param payloadId_ is the identifier of the cross-chain payload to be updated. diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 934703d79..509852a24 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -224,6 +224,9 @@ library Error { /// @dev thrown if payload is being updated with tx data length different than liq data length error DIFFERENT_PAYLOAD_UPDATE_TX_DATA_LENGTH(); + /// @dev thrown if keeper update final token is different than the vault underlying + error INVALID_UPDATE_FINAL_TOKEN(); + /// @dev thrown if broadcast finality for wormhole is invalid error INVALID_BROADCAST_FINALITY(); diff --git a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol index 9b0a98bf1..0ae5ed402 100644 --- a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol @@ -27,9 +27,14 @@ contract CoreStateRegistryTest is ProtocolActions { vm.prank(deployer); uint256[] memory amounts = new uint256[](1); + address[] memory bridgedTokens = new address[](1); /// @dev 1e18 after decimal corrections and bridge slippage would give the following value amounts[0] = 999_900_000_000_000_000; - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, amounts); + bridgedTokens[0] = getContract(AVAX, "DAI"); + + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, amounts + ); vm.prank(getContract(AVAX, "CoreStateRegistry")); MockERC20(getContract(AVAX, "DAI")).transfer(deployer, 999_900_000_000_000_000); @@ -60,15 +65,31 @@ contract CoreStateRegistryTest is ProtocolActions { finalAmounts[0] = 0; finalAmounts[1] = 419; + address[] memory bridgedTokens = new address[](2); + bridgedTokens[0] = getContract(AVAX, "DAI"); + bridgedTokens[1] = getContract(AVAX, "DAI"); + vm.prank(deployer); vm.expectRevert(Error.ZERO_AMOUNT.selector); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); finalAmounts[0] = 419; finalAmounts[1] = 419; vm.prank(deployer); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, finalAmounts); + bridgedTokens[0] = getContract(AVAX, "WETH"); + vm.expectRevert(Error.INVALID_UPDATE_FINAL_TOKEN.selector); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); + + vm.prank(deployer); + bridgedTokens[0] = getContract(AVAX, "DAI"); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); vm.prank(getContract(AVAX, "CoreStateRegistry")); MockERC20(getContract(AVAX, "DAI")).transfer(deployer, 840); @@ -151,8 +172,7 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](4), new bool[](4), receiverAddress, - receiverAddress, - + receiverAddress, bytes("") ); /// @dev approves before call @@ -182,8 +202,16 @@ contract CoreStateRegistryTest is ProtocolActions { finalAmounts[2] = 419; finalAmounts[3] = 100; + address[] memory bridgedTokens = new address[](4); + bridgedTokens[0] = getContract(AVAX, "DAI"); + bridgedTokens[1] = getContract(AVAX, "DAI"); + bridgedTokens[2] = getContract(AVAX, "DAI"); + bridgedTokens[3] = getContract(AVAX, "DAI"); + vm.prank(deployer); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); uint256 nativeValue = PaymentHelper(getContract(AVAX, "PaymentHelper")).estimateAckCost(1); vm.prank(deployer); @@ -235,9 +263,20 @@ contract CoreStateRegistryTest is ProtocolActions { vm.prank(deployer); uint256[] memory amounts = new uint256[](1); - amounts[0] = 999_900_000_000_000_000; - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, amounts); + + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(AVAX, "WETH"); + vm.expectRevert(Error.INVALID_UPDATE_FINAL_TOKEN.selector); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, amounts + ); + + vm.prank(deployer); + bridgedTokens[0] = getContract(AVAX, "DAI"); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, amounts + ); uint256 nativeValue = PaymentHelper(getContract(AVAX, "PaymentHelper")).estimateAckCost(1); @@ -264,11 +303,16 @@ contract CoreStateRegistryTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 2222; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(AVAX, "DAI"); + vm.prank(deployer); vm.expectEmit(); // We emit the event we expect to see. emit ICoreStateRegistry.FailedXChainDeposits(1); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, amounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, amounts + ); } /// @dev test processPayload without updating multi vault deposit payload @@ -296,14 +340,21 @@ contract CoreStateRegistryTest is ProtocolActions { _successfulSingleDeposit(ambIds_); vm.selectFork(FORKS[AVAX]); + uint256[] memory amounts = new uint256[](1); amounts[0] = 0; + + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(AVAX, "DAI"); + vm.prank(deployer); SuperRegistry(getContract(AVAX, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); vm.prank(deployer); vm.expectRevert(Error.ZERO_AMOUNT.selector); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, amounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, amounts + ); vm.prank(deployer); SuperRegistry(getContract(AVAX, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 2); @@ -313,7 +364,9 @@ contract CoreStateRegistryTest is ProtocolActions { vm.prank(deployer); vm.expectRevert(Error.INSUFFICIENT_QUORUM.selector); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, amounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, amounts + ); } /// @dev test all revert cases with single vault withdraw payload update @@ -405,18 +458,23 @@ contract CoreStateRegistryTest is ProtocolActions { _successfulMultiDeposit(ambIds_); uint256[] memory finalAmounts = new uint256[](1); + address[] memory bridgedTokens = new address[](1); vm.selectFork(FORKS[AVAX]); vm.prank(deployer); vm.expectRevert(Error.INSUFFICIENT_QUORUM.selector); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); vm.prank(deployer); SuperRegistry(getContract(AVAX, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); vm.prank(deployer); vm.expectRevert(Error.DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH.selector); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); } /// @dev test revert cases for duplicate proof bridge id @@ -521,6 +579,11 @@ contract CoreStateRegistryTest is ProtocolActions { uint256[] memory finalAmounts = new uint256[](2); finalAmounts[0] = 420; finalAmounts[1] = 420; + + address[] memory bridgedTokens = new address[](2); + bridgedTokens[0] = getContract(AVAX, "DAI"); + bridgedTokens[1] = getContract(AVAX, "DAI"); + vm.selectFork(FORKS[AVAX]); vm.prank(deployer); SuperRegistry(getContract(AVAX, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); @@ -533,7 +596,9 @@ contract CoreStateRegistryTest is ProtocolActions { abi.encode(false) ); vm.prank(deployer); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); vm.prank(deployer); vm.expectRevert(Error.PAYLOAD_ALREADY_PROCESSED.selector); @@ -552,6 +617,9 @@ contract CoreStateRegistryTest is ProtocolActions { uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = 999_900_000_000_000_000; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(AVAX, "DAI"); + vm.selectFork(FORKS[AVAX]); vm.prank(deployer); SuperRegistry(getContract(AVAX, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); @@ -565,7 +633,9 @@ contract CoreStateRegistryTest is ProtocolActions { ); vm.prank(deployer); - CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(payable(getContract(AVAX, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, finalAmounts + ); vm.prank(deployer); vm.expectRevert(Error.PAYLOAD_ALREADY_PROCESSED.selector); @@ -626,8 +696,7 @@ contract CoreStateRegistryTest is ProtocolActions { false, false, receiverAddress, - receiverAddress, - + receiverAddress, bytes("") ); /// @dev approves before call @@ -690,8 +759,7 @@ contract CoreStateRegistryTest is ProtocolActions { false, false, receiverAddress, - receiverAddress, - + receiverAddress, bytes("") ); @@ -775,8 +843,7 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](2), new bool[](2), receiverAddress, - receiverAddress, - + receiverAddress, bytes("") ); /// @dev approves before call @@ -836,8 +903,7 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](2), new bool[](2), receiverAddress, - receiverAddress, - + receiverAddress, bytes("") ); @@ -920,8 +986,7 @@ contract CoreStateRegistryTest is ProtocolActions { new bool[](2), new bool[](2), receiverAddress, - receiverAddress, - + receiverAddress, bytes("") ); /// @dev approves before call diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index a28fa95f3..f0dc6a7da 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -205,13 +205,15 @@ contract DstSwapperTest is ProtocolActions { SuperRegistry(getContract(OP, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); uint256[] memory finalAmounts = new uint256[](1); + address[] memory bridgedTokens = new address[](1); finalAmounts[0] = 2e18; + bridgedTokens[0] = getContract(OP, "WETH"); vm.expectRevert(Error.INVALID_DST_SWAP_AMOUNT.selector); - CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, bridgedTokens, finalAmounts); finalAmounts[0] = 1e18; - CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, bridgedTokens, finalAmounts); vm.expectRevert(Error.INVALID_PAYLOAD_STATUS.selector); DstSwapper(dstSwapper).updateFailedTx(1, weth, 1e18); @@ -315,7 +317,11 @@ contract DstSwapperTest is ProtocolActions { uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = 1e18; - CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, finalAmounts); + + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(OP, "WETH"); + + CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, bridgedTokens, finalAmounts); vm.stopPrank(); @@ -397,7 +403,11 @@ contract DstSwapperTest is ProtocolActions { /// @dev set quorum to 0 for simplicity in testing setup SuperRegistry(getContract(OP, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); - CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, amounts); + address[] memory bridgedTokens = new address[](2); + bridgedTokens[0] = getContract(OP, "WETH"); + bridgedTokens[1] = getContract(OP, "WETH"); + + CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, bridgedTokens, amounts); vm.stopPrank(); AMBs = [2, 3]; @@ -462,7 +472,11 @@ contract DstSwapperTest is ProtocolActions { /// @dev set quorum to 0 for simplicity in testing setup SuperRegistry(getContract(OP, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); - CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, amounts); + address[] memory bridgedTokens = new address[](2); + bridgedTokens[0] = getContract(OP, "WETH"); + bridgedTokens[1] = getContract(OP, "WETH"); + + CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, bridgedTokens, amounts); vm.stopPrank(); @@ -693,10 +707,13 @@ contract DstSwapperTest is ProtocolActions { SuperRegistry(getContract(OP, "SuperRegistry")).setRequiredMessagingQuorum(ETH, 0); uint256[] memory finalAmounts = new uint256[](1); - finalAmounts[0] = 2e18; + + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(OP, "WETH"); + vm.expectRevert(Error.INVALID_DST_SWAPPER_FAILED_SWAP.selector); - CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, finalAmounts); + CoreStateRegistry(coreStateRegistry).updateDepositPayload(1, bridgedTokens, finalAmounts); } function _simulateSingleVaultExistingPayload( diff --git a/test/unit/emergency/EmergencyQueue.t.sol b/test/unit/emergency/EmergencyQueue.t.sol index 32aa54da6..a057ba909 100644 --- a/test/unit/emergency/EmergencyQueue.t.sol +++ b/test/unit/emergency/EmergencyQueue.t.sol @@ -845,7 +845,12 @@ contract EmergencyQueueTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 2e18; - CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload(payloadId, amounts); + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(ARBI, "DAI"); + + CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload( + payloadId, bridgedTokens, amounts + ); uint256 nativeAmount = PaymentHelper(getContract(ARBI, "PaymentHelper")).estimateAckCost(1); diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index 9bcebcc9b..85ceb78a3 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -371,13 +371,19 @@ contract SuperformRouterAATest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; - CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload(1, amounts); + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(ARBI, "DAI"); - uint256 nativeAmount = PaymentHelper(getContract(ARBI, "PaymentHelper")).estimateAckCost(1); + CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload( + 1, bridgedTokens, amounts + ); vm.recordLogs(); - vm.prank(deployer); - CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).processPayload{ value: nativeAmount }(1); + vm.startPrank(deployer); + CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).processPayload{ + value: PaymentHelper(getContract(ARBI, "PaymentHelper")).estimateAckCost(1) + }(1); + vm.stopPrank(); if (!receive4626_) { logs = vm.getRecordedLogs(); diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index a349f7bd9..530834d81 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -2586,6 +2586,7 @@ contract SuperformRouterTest is ProtocolActions { struct SimulateUpdateTestLocalVars { SingleVaultSFData data; uint8[] ambIds; + address[] bridgedTokens; uint256[] amounts; uint256 nativeAmount; uint256 swapAmount; @@ -2698,6 +2699,9 @@ contract SuperformRouterTest is ProtocolActions { v.amounts = new uint256[](1); v.amounts[0] = keeperUpdateExactAmount ? 3e18 : 2e18; // false -± 2e18 + v.bridgedTokens = new address[](1); + v.bridgedTokens[0] = getContract(ARBI, "DAI"); + v.swapAmount = swapperSwapExactBridgeAmount ? 3e18 : 2e18; // true -± 3e18 if (hasDstSwap) { @@ -2718,9 +2722,13 @@ contract SuperformRouterTest is ProtocolActions { if (hasDstSwap && keeperUpdateExactAmount && swapperSwapExactBridgeAmount) { vm.expectRevert(Error.INVALID_DST_SWAPPER_FAILED_SWAP.selector); - CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload(1, v.amounts); + CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload( + 1, v.bridgedTokens, v.amounts + ); } else { - CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload(1, v.amounts); + CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload( + 1, v.bridgedTokens, v.amounts + ); v.nativeAmount = PaymentHelper(getContract(ARBI, "PaymentHelper")).estimateAckCost(1); vm.recordLogs(); diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index 55ccf4733..bcbb85fb0 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -1353,6 +1353,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.selectFork(FORKS[args.targetChainId]); uint256 len = args.amounts.length; uint256[] memory finalAmounts = new uint256[](len); + address[] memory bridgedTokens = new address[](len); int256 dstSwapSlippage; @@ -1374,7 +1375,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { if (args.testType == TestType.Pass || args.testType == TestType.RevertProcessPayload) { vm.prank(deployer); CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); /// @dev if scenario is meant to revert here (e.g invalid slippage) @@ -1384,7 +1385,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { /// @dev removed string here: come to this later CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; @@ -1395,7 +1396,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.expectRevert(errorMsg); CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; @@ -1414,6 +1415,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.selectFork(FORKS[args.targetChainId]); uint256 finalAmount; + address bridgedToken; finalAmount = args.amount; @@ -1432,8 +1434,11 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = finalAmount; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = bridgedToken; + CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); /// @dev if scenario is meant to revert here (e.g invalid slippage) } else if (args.testType == TestType.RevertUpdateStateSlippage) { @@ -1442,12 +1447,14 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.expectRevert(args.revertError); /// @dev removed string here: come to this later - uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = finalAmount; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = bridgedToken; + CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; @@ -1461,8 +1468,11 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = finalAmount; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = bridgedToken; + CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index e5e659146..c684816ef 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -2167,9 +2167,15 @@ abstract contract ProtocolActions is CommonProtocolActions { vm.selectFork(FORKS[args.targetChainId]); uint256 len = args.amounts.length; uint256[] memory finalAmounts = new uint256[](len); + address[] memory bridgedTokens = new address[](len); int256 dstSwapSlippage; + for (uint256 i; i < len; ++i) { + bridgedTokens[i] = + getContract(args.targetChainId, UNDERLYING_TOKENS[TARGET_UNDERLYINGS[args.targetChainId][0][i]]); + } + for (uint256 i = 0; i < len; ++i) { finalAmounts[i] = args.amounts[i]; if (args.slippage > 0) { @@ -2189,7 +2195,7 @@ abstract contract ProtocolActions is CommonProtocolActions { if (args.testType == TestType.Pass || args.testType == TestType.RevertProcessPayload) { vm.prank(deployer); CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); /// @dev if scenario is meant to revert here (e.g invalid slippage) @@ -2199,7 +2205,7 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev removed string here: come to this later CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; @@ -2210,7 +2216,7 @@ abstract contract ProtocolActions is CommonProtocolActions { vm.expectRevert(errorMsg); CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; @@ -2232,9 +2238,10 @@ abstract contract ProtocolActions is CommonProtocolActions { vm.selectFork(FORKS[args.targetChainId]); uint256 finalAmount; + address bridgedToken = + getContract(args.targetChainId, UNDERLYING_TOKENS[TARGET_UNDERLYINGS[args.targetChainId][0][0]]); finalAmount = args.amount; - int256 dstSwapSlippage; if (args.isdstSwap) { @@ -2253,8 +2260,11 @@ abstract contract ProtocolActions is CommonProtocolActions { uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = finalAmount; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = bridgedToken; + CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); /// @dev if scenario is meant to revert here (e.g invalid slippage) } else if (args.testType == TestType.RevertUpdateStateSlippage) { @@ -2263,12 +2273,14 @@ abstract contract ProtocolActions is CommonProtocolActions { vm.expectRevert(args.revertError); /// @dev removed string here: come to this later - uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = finalAmount; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = bridgedToken; + CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; @@ -2282,8 +2294,11 @@ abstract contract ProtocolActions is CommonProtocolActions { uint256[] memory finalAmounts = new uint256[](1); finalAmounts[0] = finalAmount; + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = bridgedToken; + CoreStateRegistry(payable(getContract(args.targetChainId, "CoreStateRegistry"))).updateDepositPayload( - args.payloadId, finalAmounts + args.payloadId, bridgedTokens, finalAmounts ); return false; @@ -3577,8 +3592,6 @@ abstract contract ProtocolActions is CommonProtocolActions { ambIds[0] = 1; ambIds[1] = 2; - SingleXChainSingleVaultStateReq memory req = SingleXChainSingleVaultStateReq(ambIds, ARBI, data); - /// @dev approves before call vm.prank(mrperfect); MockERC20(getContract(ETH, "DAI")).approve(superformRouter, 2e18); @@ -3586,7 +3599,9 @@ abstract contract ProtocolActions is CommonProtocolActions { vm.prank(mrperfect); vm.deal(mrperfect, 2 ether); - SuperformRouter(payable(superformRouter)).singleXChainSingleVaultDeposit{ value: 2 ether }(req); + SuperformRouter(payable(superformRouter)).singleXChainSingleVaultDeposit{ value: 2 ether }( + SingleXChainSingleVaultStateReq(ambIds, ARBI, data) + ); Vm.Log[] memory logs = vm.getRecordedLogs(); @@ -3610,7 +3625,12 @@ abstract contract ProtocolActions is CommonProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 2e18; - CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload(payloadId, amounts); + address[] memory bridgedTokens = new address[](1); + bridgedTokens[0] = getContract(ARBI, "DAI"); + + CoreStateRegistry(payable(getContract(ARBI, "CoreStateRegistry"))).updateDepositPayload( + payloadId, bridgedTokens, amounts + ); uint256 nativeAmount = PaymentHelper(getContract(ARBI, "PaymentHelper")).estimateAckCost(1); From 6d0538655845ed4d857ded21aa60e09eabc2cffc Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 25 Dec 2023 12:03:37 +0000 Subject: [PATCH 173/210] feat: adds blacklisted of pack and min endpoints and removes try catch --- src/crosschain-liquidity/BridgeValidator.sol | 4 +- src/crosschain-liquidity/DstSwapper.sol | 4 +- .../lifi/LiFiValidator.sol | 263 ++++++++++-------- src/interfaces/IBridgeValidator.sol | 4 +- src/libraries/Error.sol | 3 + src/vendor/lifi/CBridgeFacetPacked.sol | 54 ++++ src/vendor/lifi/GenericSwapFacet.sol | 33 +++ src/vendor/lifi/HopFacetPacked.sol | 36 +++ src/vendor/lifi/LiFiTxDataExtractor.sol | 33 +++ test/mocks/LiFiMockBlacklisted.sol | 83 ++++++ test/unit/payments/PaymentHelper.t.sol | 4 +- test/unit/super-registry/SuperRegistry.t.sol | 2 +- .../superform-form.ERC4626Form.t.sol | 42 ++- .../superform-router/SuperformRouter.t.sol | 3 +- test/utils/BaseSetup.sol | 14 +- test/utils/TestTypes.sol | 1 + 16 files changed, 455 insertions(+), 128 deletions(-) create mode 100644 src/vendor/lifi/CBridgeFacetPacked.sol create mode 100644 src/vendor/lifi/GenericSwapFacet.sol create mode 100644 src/vendor/lifi/HopFacetPacked.sol create mode 100644 test/mocks/LiFiMockBlacklisted.sol diff --git a/src/crosschain-liquidity/BridgeValidator.sol b/src/crosschain-liquidity/BridgeValidator.sol index 1481a6797..23763f9a7 100644 --- a/src/crosschain-liquidity/BridgeValidator.sol +++ b/src/crosschain-liquidity/BridgeValidator.sol @@ -55,7 +55,7 @@ abstract contract BridgeValidator is IBridgeValidator { bool genericSwapDisallowed_ ) external - view + pure virtual override returns (uint256 amount_); @@ -71,7 +71,7 @@ abstract contract BridgeValidator is IBridgeValidator { /// @inheritdoc IBridgeValidator function decodeSwapOutputToken(bytes calldata txData_) external - view + pure virtual override returns (address outputToken_); diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index 2b19ba29a..bb30be20d 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -83,7 +83,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { if (superRegistry_ == address(0)) { revert Error.ZERO_ADDRESS(); } - + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } @@ -375,7 +375,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { v.balanceDiff = v.balanceAfter - v.balanceBefore; /// @dev if actual underlying is less than expAmount adjusted with maxSlippage, invariant breaks - if (v.balanceDiff * ENTIRE_SLIPPAGE < v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) { + if (v.balanceDiff * ENTIRE_SLIPPAGE < v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); } diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index aa31c7063..666062199 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -7,10 +7,12 @@ import { LiFiTxDataExtractor } from "src/vendor/lifi/LiFiTxDataExtractor.sol"; import { LibSwap } from "src/vendor/lifi/LibSwap.sol"; import { ILiFi } from "src/vendor/lifi/ILiFi.sol"; import { StandardizedCallFacet } from "src/vendor/lifi/StandardizedCallFacet.sol"; +import { GenericSwapFacet } from "src/vendor/lifi/GenericSwapFacet.sol"; /// @title LiFiValidator /// @author Zeropoint Labs /// @dev To assert input txData is valid + contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { ////////////////////////////////////////////////////////////// // CONSTRUCTOR // @@ -30,92 +32,39 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { /// @inheritdoc BridgeValidator function validateTxData(ValidateTxDataArgs calldata args_) external view override returns (bool hasDstSwap) { - /// @dev xchain actions can have bridgeData or bridgeData + swapData - /// @dev direct actions with deposit, cannot have bridge data - goes into catch block - /// @dev withdraw actions may have bridge data after withdrawing - goes into try block - /// @dev withdraw actions without bridge data (just swap) - goes into catch block + bytes4 selector = _extractSelector(args_.txData); - try this.extractMainParameters(args_.txData) returns ( - string memory, /*bridge*/ - address sendingAssetId, - address receiver, - uint256, /*amount*/ - uint256, /*minAmount*/ - uint256 destinationChainId, - bool, /*hasSourceSwaps*/ - bool hasDestinationCall - ) { - /// @dev 0. Destination call validation - if (hasDestinationCall) revert Error.INVALID_TXDATA_NO_DESTINATIONCALL_ALLOWED(); + address sendingAssetId; + address receiver; + bool hasDestinationCall; + uint256 destinationChainId; - /// @dev 1. chainId validation - /// @dev for deposits, liqDstChainId/toChainId will be the normal destination (where the target superform - /// is) - /// @dev for withdraws, liqDstChainId will be the desired chain to where the underlying must be - /// sent (post any bridge/swap). To ChainId is where the target superform is - /// @dev to after vault redemption + /// @dev 1 - check if it is a swapTokensGeneric call (match via selector) + if (selector == GenericSwapFacet.swapTokensGeneric.selector) { + /// @dev GenericSwapFacet + /// @dev direct actions with deposit, cannot have bridge data - goes in here + /// @dev withdraw actions without bridge data (just swap) - goes in here - if (uint256(args_.liqDstChainId) != destinationChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); + (sendingAssetId,, receiver,,) = extractGenericSwapParameters(args_.txData); + _validateGenericParameters(args_, receiver, sendingAssetId); + /// @dev if valid return here + return false; + } - /// @dev 2. receiver address validation - if (args_.deposit) { - if (args_.srcChainId == args_.dstChainId) { - revert Error.INVALID_ACTION(); - } else { - hasDstSwap = - receiver == superRegistry.getAddressByChainId(keccak256("DST_SWAPPER"), args_.dstChainId); - /// @dev if cross chain deposits, then receiver address must be CoreStateRegistry (or) Dst Swapper - if ( - !( - receiver - == superRegistry.getAddressByChainId(keccak256("CORE_STATE_REGISTRY"), args_.dstChainId) - || hasDstSwap - ) - ) { - revert Error.INVALID_TXDATA_RECEIVER(); - } - - /// @dev forbid xChain deposits with destination swaps without interim token set (for user - /// protection) - if (hasDstSwap && args_.liqDataInterimToken == address(0)) { - revert Error.INVALID_INTERIM_TOKEN(); - } - } - } else { - /// @dev if withdraws, then receiver address must be the receiverAddress - if (receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); - } + /// @dev 2 - check if it is any other blacklisted selector - /// @dev remap of address 0 to NATIVE because of how LiFi produces txData - if (sendingAssetId == address(0)) { - sendingAssetId = NATIVE; - } - /// @dev 3. token validations - if (args_.liqDataToken != sendingAssetId) revert Error.INVALID_TXDATA_TOKEN(); - } catch { - (address sendingAssetId,, address receiver,,) = extractGenericSwapParameters(args_.txData); - - if (args_.deposit) { - /// @dev 1. chainId validation - if (args_.srcChainId != args_.dstChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); - if (args_.dstChainId != args_.liqDstChainId) revert Error.INVALID_DEPOSIT_LIQ_DST_CHAIN_ID(); - - /// @dev 2. receiver address validation - /// @dev If same chain deposits then receiver address must be the superform - if (receiver != args_.superform) revert Error.INVALID_TXDATA_RECEIVER(); - } else { - /// @dev 2. receiver address validation - /// @dev if withdraws, then receiver address must be the receiverAddress - if (receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); - } + if (!_validateSelector(selector)) revert Error.BLACKLISTED_SELECTOR(); - /// @dev remap of address 0 to NATIVE because of how LiFi produces txData - if (sendingAssetId == address(0)) { - sendingAssetId = NATIVE; - } - /// @dev 3. token validations - if (args_.liqDataToken != sendingAssetId) revert Error.INVALID_TXDATA_TOKEN(); - } + /// @dev 3 - proceed with normal extraction + (, sendingAssetId, receiver,,, destinationChainId,, hasDestinationCall) = extractMainParameters(args_.txData); + + /// @dev xchain actions can have bridgeData or bridgeData + swapData - goes in here + /// @dev withdraw actions may have bridge data after withdrawing - goes in here + + hasDstSwap = + _validateMainParameters(args_, hasDestinationCall, hasDstSwap, receiver, sendingAssetId, destinationChainId); + + return hasDstSwap; } /// @inheritdoc BridgeValidator @@ -124,54 +73,50 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { bool genericSwapDisallowed_ ) external - view + pure override returns (uint256 amount_) { - try this.extractMainParameters(txData_) returns ( - string memory, /*bridge*/ - address, /*sendingAssetId*/ - address, /*receiver*/ - uint256 amount, - uint256, /*minAmount*/ - uint256, /*destinationChainId*/ - bool, /*hasSourceSwaps*/ - bool /*hasDestinationCall*/ - ) { - /// @dev if there isn't a source swap, amount_ is minAmountOut from bridge data - - amount_ = amount; - } catch { - if (genericSwapDisallowed_) revert Error.INVALID_ACTION(); - /// @dev in the case of a generic swap, amount_ is the from amount + bytes4 selector = _extractSelector(txData_); + /// @dev 1 - check if it is a swapTokensGeneric call (match via selector) + if (selector == GenericSwapFacet.swapTokensGeneric.selector && !genericSwapDisallowed_) { (, amount_,,,) = extractGenericSwapParameters(txData_); + return amount_; + } else if (selector == GenericSwapFacet.swapTokensGeneric.selector && genericSwapDisallowed_) { + revert Error.INVALID_ACTION(); } + + /// @dev 2 - check if it is any other blacklisted selector + if (!_validateSelector(selector)) revert Error.BLACKLISTED_SELECTOR(); + + /// @dev 3 - proceed with normal extraction + (, /*bridgeId*/,, amount_, /*amount*/, /*minAmount*/,, /*hasSourceSwaps*/ ) = extractMainParameters(txData_); + /// @dev if there isn't a source swap, amount_ is minAmountOut from bridge data + + return amount_; } /// @inheritdoc BridgeValidator function decodeDstSwap(bytes calldata txData_) external pure override returns (address token_, uint256 amount_) { - (token_, amount_,,,) = extractGenericSwapParameters(txData_); + bytes4 selector = _extractSelector(txData_); + if (selector == GenericSwapFacet.swapTokensGeneric.selector) { + (token_, amount_,,,) = extractGenericSwapParameters(txData_); + return (token_, amount_); + } else { + revert Error.INVALID_ACTION(); + } } /// @inheritdoc BridgeValidator - function decodeSwapOutputToken(bytes calldata txData_) external view override returns (address token_) { - try this.extractMainParameters(txData_) returns ( - string memory, /*bridge*/ - address, /*sendingAssetId*/ - address, /*receiver*/ - uint256, /*amount*/ - uint256, /*minAmount*/ - uint256, /*destinationChainId*/ - bool, /*hasSourceSwaps*/ - bool /*hasDestinationCall*/ - ) { - /// @dev if there isn't a source swap, amountIn is minAmountOut from bridge data? + function decodeSwapOutputToken(bytes calldata txData_) external pure override returns (address token_) { + bytes4 selector = _extractSelector(txData_); + if (selector == GenericSwapFacet.swapTokensGeneric.selector) { + (,,, token_,) = extractGenericSwapParameters(txData_); + return token_; + } else { revert Error.CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN(); - } catch { - (,,, address receivingAssetId,) = extractGenericSwapParameters(txData_); - token_ = receivingAssetId; } } @@ -257,4 +202,96 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { receivingAssetId = swapData[swapData.length - 1].receivingAssetId; return (sendingAssetId, amount, receiver, receivingAssetId, receivingAmount); } + + function _validateMainParameters( + ValidateTxDataArgs calldata args_, + bool hasDestinationCall, + bool hasDstSwap, + address receiver, + address sendingAssetId, + uint256 destinationChainId + ) + internal + view + returns (bool) + { + /// @dev 0. Destination call validation + if (hasDestinationCall) revert Error.INVALID_TXDATA_NO_DESTINATIONCALL_ALLOWED(); + + /// @dev 1. chainId validation + /// @dev for deposits, liqDstChainId/toChainId will be the normal destination (where the target superform + /// is) + /// @dev for withdraws, liqDstChainId will be the desired chain to where the underlying must be + /// sent (post any bridge/swap). To ChainId is where the target superform is + /// @dev to after vault redemption + + if (uint256(args_.liqDstChainId) != destinationChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); + + /// @dev 2. receiver address validation + if (args_.deposit) { + if (args_.srcChainId == args_.dstChainId) { + revert Error.INVALID_ACTION(); + } else { + hasDstSwap = receiver == superRegistry.getAddressByChainId(keccak256("DST_SWAPPER"), args_.dstChainId); + /// @dev if cross chain deposits, then receiver address must be CoreStateRegistry (or) Dst Swapper + if ( + !( + receiver + == superRegistry.getAddressByChainId(keccak256("CORE_STATE_REGISTRY"), args_.dstChainId) + || hasDstSwap + ) + ) { + revert Error.INVALID_TXDATA_RECEIVER(); + } + + /// @dev forbid xChain deposits with destination swaps without interim token set (for user + /// protection) + if (hasDstSwap && args_.liqDataInterimToken == address(0)) { + revert Error.INVALID_INTERIM_TOKEN(); + } + } + } else { + /// @dev if withdraws, then receiver address must be the receiverAddress + if (receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); + } + + /// @dev remap of address 0 to NATIVE because of how LiFi produces txData + if (sendingAssetId == address(0)) { + sendingAssetId = NATIVE; + } + /// @dev 3. token validations + if (args_.liqDataToken != sendingAssetId) revert Error.INVALID_TXDATA_TOKEN(); + + return hasDstSwap; + } + + function _validateGenericParameters( + ValidateTxDataArgs calldata args_, + address receiver, + address sendingAssetId + ) + internal + pure + { + if (args_.deposit) { + /// @dev 1. chainId validation + if (args_.srcChainId != args_.dstChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); + if (args_.dstChainId != args_.liqDstChainId) revert Error.INVALID_DEPOSIT_LIQ_DST_CHAIN_ID(); + + /// @dev 2. receiver address validation + /// @dev If same chain deposits then receiver address must be the superform + if (receiver != args_.superform) revert Error.INVALID_TXDATA_RECEIVER(); + } else { + /// @dev 2. receiver address validation + /// @dev if withdraws, then receiver address must be the receiverAddress + if (receiver != args_.receiverAddress) revert Error.INVALID_TXDATA_RECEIVER(); + } + + /// @dev remap of address 0 to NATIVE because of how LiFi produces txData + if (sendingAssetId == address(0)) { + sendingAssetId = NATIVE; + } + /// @dev 3. token validations + if (args_.liqDataToken != sendingAssetId) revert Error.INVALID_TXDATA_TOKEN(); + } } diff --git a/src/interfaces/IBridgeValidator.sol b/src/interfaces/IBridgeValidator.sol index 6a9c97100..b3f4fe67a 100644 --- a/src/interfaces/IBridgeValidator.sol +++ b/src/interfaces/IBridgeValidator.sol @@ -44,7 +44,7 @@ interface IBridgeValidator { bool genericSwapDisallowed_ ) external - view + pure returns (uint256 amount_); /// @dev decodes neccesary information for processing swaps on the destination chain @@ -56,5 +56,5 @@ interface IBridgeValidator { /// @dev decodes the final output token address (for only direct chain actions!) /// @param txData_ is the txData to be decoded /// @return token_ the address of the token - function decodeSwapOutputToken(bytes calldata txData_) external view returns (address token_); + function decodeSwapOutputToken(bytes calldata txData_) external pure returns (address token_); } diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 934703d79..53712fa32 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -264,6 +264,9 @@ library Error { /// @dev error thrown when msg value should be zero in certain payable functions error MSG_VALUE_NOT_ZERO(); + /// @dev error thrown when txData selector of lifi bridged is a blacklisted selector + error BLACKLISTED_SELECTOR(); + ////////////////////////////////////////////////////////////// // EXECUTION ERRORS // ////////////////////////////////////////////////////////////// diff --git a/src/vendor/lifi/CBridgeFacetPacked.sol b/src/vendor/lifi/CBridgeFacetPacked.sol new file mode 100644 index 000000000..0a143b648 --- /dev/null +++ b/src/vendor/lifi/CBridgeFacetPacked.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +/// @title CBridge Facet Packed +/// @author LI.FI (https://li.fi) +/// @notice Provides functionality for bridging through CBridge +/// @notice taken from LiFi contracts https://github.com/lifinance/contracts and stripped down to needs +/// @custom:version 1.0.3 +contract CBridgeFacetPacked { + /// @notice Bridges Native tokens via cBridge (packed) + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaCBridgeNativePacked() external payable { } + + /// @notice Bridges native tokens via cBridge + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param nonce A number input to guarantee uniqueness of transferId. + /// @param maxSlippage Destination swap minimal accepted amount + function startBridgeTokensViaCBridgeNativeMin( + bytes32 transactionId, + address receiver, + uint64 destinationChainId, + uint64 nonce, + uint32 maxSlippage + ) + external + payable + { } + + /// @notice Bridges ERC20 tokens via cBridge + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaCBridgeERC20Packed() external { } + + /// @notice Bridges ERC20 tokens via cBridge + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param sendingAssetId Address of the source asset to bridge + /// @param amount Amount of the source asset to bridge + /// @param nonce A number input to guarantee uniqueness of transferId + /// @param maxSlippage Destination swap minimal accepted amount + function startBridgeTokensViaCBridgeERC20Min( + bytes32 transactionId, + address receiver, + uint64 destinationChainId, + address sendingAssetId, + uint256 amount, + uint64 nonce, + uint32 maxSlippage + ) + external + { } +} diff --git a/src/vendor/lifi/GenericSwapFacet.sol b/src/vendor/lifi/GenericSwapFacet.sol new file mode 100644 index 000000000..726ed42ac --- /dev/null +++ b/src/vendor/lifi/GenericSwapFacet.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { LibSwap } from "./LibSwap.sol"; + +/// @title Generic Swap Facet +/// @author LI.FI (https://li.fi) +/// @notice Provides functionality for swapping through ANY APPROVED DEX +/// @dev Uses calldata to execute APPROVED arbitrary methods on DEXs +/// @notice taken from LiFi contracts https://github.com/lifinance/contracts and stripped down to needs +/// @custom:version 1.0.0 +contract GenericSwapFacet { + /// External Methods /// + + /// @notice Performs multiple swaps in one transaction + /// @param _transactionId the transaction id associated with the operation + /// @param _integrator the name of the integrator + /// @param _referrer the address of the referrer + /// @param _receiver the address to receive the swapped tokens into (also excess tokens) + /// @param _minAmount the minimum amount of the final asset to receive + /// @param _swapData an object containing swap related data to perform swaps before bridging + function swapTokensGeneric( + bytes32 _transactionId, + string calldata _integrator, + string calldata _referrer, + address payable _receiver, + uint256 _minAmount, + LibSwap.SwapData[] calldata _swapData + ) + external + payable + { } +} diff --git a/src/vendor/lifi/HopFacetPacked.sol b/src/vendor/lifi/HopFacetPacked.sol new file mode 100644 index 000000000..2f1aa564a --- /dev/null +++ b/src/vendor/lifi/HopFacetPacked.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +/// @title Hop Facet (Optimized for Rollups) +/// @author LI.FI (https://li.fi) +/// @notice Provides functionality for bridging through Hop +/// @notice taken from LiFi contracts https://github.com/lifinance/contracts and stripped down to needs +/// @custom:version 1.0.6 +contract HopFacetPacked { + /// @notice Bridges Native tokens via Hop Protocol from L2 + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaHopL2NativePacked() external payable { } + + /// @notice Bridges Native tokens via Hop Protocol from L2 + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param bonderFee Fees payed to hop bonder + /// @param amountOutMin Source swap minimal accepted amount + /// @param destinationAmountOutMin Destination swap minimal accepted amount + /// @param destinationDeadline Destination swap maximal time + /// @param hopBridge Address of the Hop L2_AmmWrapper + function startBridgeTokensViaHopL2NativeMin( + bytes8 transactionId, + address receiver, + uint256 destinationChainId, + uint256 bonderFee, + uint256 amountOutMin, + uint256 destinationAmountOutMin, + uint256 destinationDeadline, + address hopBridge + ) + external + payable + { } +} diff --git a/src/vendor/lifi/LiFiTxDataExtractor.sol b/src/vendor/lifi/LiFiTxDataExtractor.sol index ec00cdd43..b4b0bcc14 100644 --- a/src/vendor/lifi/LiFiTxDataExtractor.sol +++ b/src/vendor/lifi/LiFiTxDataExtractor.sol @@ -5,6 +5,8 @@ import { ILiFi } from "src/vendor/lifi/ILiFi.sol"; import { LibSwap } from "src/vendor/lifi/LibSwap.sol"; import { StandardizedCallFacet } from "./StandardizedCallFacet.sol"; import { AmarokFacet } from "./AmarokFacet.sol"; +import { CBridgeFacetPacked } from "./CBridgeFacetPacked.sol"; +import { HopFacetPacked } from "./HopFacetPacked.sol"; import { CelerIMFacetBase, CelerIM } from "./CelerIMFacetBase.sol"; import { StargateFacet } from "./StargateFacet.sol"; @@ -19,6 +21,37 @@ contract LiFiTxDataExtractor { error SliceOverflow(); error SliceOutOfBounds(); + /// @dev this function blacklists certain packed and min selectors. + /// @notice this is a patch to prevent a user to bypass our txData validation checks + /// @notice the offered solution here is not scallable and should be replaced by a better solution with a lifi + /// maintained list + function _validateSelector(bytes4 selector) internal pure returns (bool valid) { + if (selector == CBridgeFacetPacked.startBridgeTokensViaCBridgeNativePacked.selector) { + return false; + } + if (selector == CBridgeFacetPacked.startBridgeTokensViaCBridgeNativeMin.selector) { + return false; + } + if (selector == CBridgeFacetPacked.startBridgeTokensViaCBridgeERC20Packed.selector) { + return false; + } + if (selector == CBridgeFacetPacked.startBridgeTokensViaCBridgeERC20Min.selector) { + return false; + } + if (selector == HopFacetPacked.startBridgeTokensViaHopL2NativePacked.selector) { + return false; + } + if (selector == HopFacetPacked.startBridgeTokensViaHopL2NativeMin.selector) { + return false; + } + return true; + } + + function _extractSelector(bytes calldata data) internal pure returns (bytes4 selector) { + selector = bytes4(data[:4]); + if (selector == StandardizedCallFacet.standardizedCall.selector) selector = bytes4(data[4:8]); + } + /// @notice Extracts the bridge data from the calldata. Extracts receiver correctly pending certain facet features /// @param data The calldata to extract the bridge data from /// @return bridgeData The bridge data extracted from the calldata diff --git a/test/mocks/LiFiMockBlacklisted.sol b/test/mocks/LiFiMockBlacklisted.sol new file mode 100644 index 000000000..e5b5161bb --- /dev/null +++ b/test/mocks/LiFiMockBlacklisted.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.23; + +import "forge-std/Test.sol"; + +/// @title LiFi Router Mock Blacklisted selectors +contract LiFiMockBlacklisted is Test { + address constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + + receive() external payable { } + + /// @notice Bridges Native tokens via cBridge (packed) + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaCBridgeNativePacked() external payable { } + + /// @notice Bridges native tokens via cBridge + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param nonce A number input to guarantee uniqueness of transferId. + /// @param maxSlippage Destination swap minimal accepted amount + function startBridgeTokensViaCBridgeNativeMin( + bytes32 transactionId, + address receiver, + uint64 destinationChainId, + uint64 nonce, + uint32 maxSlippage + ) + external + payable + { } + + /// @notice Bridges ERC20 tokens via cBridge + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaCBridgeERC20Packed() external { } + + /// @notice Bridges ERC20 tokens via cBridge + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param sendingAssetId Address of the source asset to bridge + /// @param amount Amount of the source asset to bridge + /// @param nonce A number input to guarantee uniqueness of transferId + /// @param maxSlippage Destination swap minimal accepted amount + function startBridgeTokensViaCBridgeERC20Min( + bytes32 transactionId, + address receiver, + uint64 destinationChainId, + address sendingAssetId, + uint256 amount, + uint64 nonce, + uint32 maxSlippage + ) + external + { } + + /// @notice Bridges Native tokens via Hop Protocol from L2 + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaHopL2NativePacked() external payable { } + + /// @notice Bridges Native tokens via Hop Protocol from L2 + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param bonderFee Fees payed to hop bonder + /// @param amountOutMin Source swap minimal accepted amount + /// @param destinationAmountOutMin Destination swap minimal accepted amount + /// @param destinationDeadline Destination swap maximal time + /// @param hopBridge Address of the Hop L2_AmmWrapper + function startBridgeTokensViaHopL2NativeMin( + bytes8 transactionId, + address receiver, + uint256 destinationChainId, + uint256 bonderFee, + uint256 amountOutMin, + uint256 destinationAmountOutMin, + uint256 destinationDeadline, + address hopBridge + ) + external + payable + { } +} diff --git a/test/unit/payments/PaymentHelper.t.sol b/test/unit/payments/PaymentHelper.t.sol index 1052c4c7f..e332215b3 100644 --- a/test/unit/payments/PaymentHelper.t.sol +++ b/test/unit/payments/PaymentHelper.t.sol @@ -12,7 +12,7 @@ contract MockGasPriceOracle { return (0, 28 gwei, block.timestamp, block.timestamp, 28 gwei); } - function decimals() external view returns (uint8) { + function decimals() external pure returns (uint8) { return 8; } } @@ -26,7 +26,7 @@ contract MalFunctioningPriceOracle { return (0, 0, block.timestamp, block.timestamp, 0); } - function decimals() external view returns (uint8) { + function decimals() external pure returns (uint8) { return 8; } } diff --git a/test/unit/super-registry/SuperRegistry.t.sol b/test/unit/super-registry/SuperRegistry.t.sol index e08075084..abd625027 100644 --- a/test/unit/super-registry/SuperRegistry.t.sol +++ b/test/unit/super-registry/SuperRegistry.t.sol @@ -143,7 +143,7 @@ contract SuperRegistryTest is BaseSetup { address[] memory bridgeAddress = new address[](3); address[] memory bridgeValidator = new address[](3); - bridgeId[0] = 5; + bridgeId[0] = 8; bridgeAddress[0] = address(0x1); bridgeValidator[0] = address(0x2); bridgeId[1] = 6; diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index ce588071e..63a5c64bc 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -891,7 +891,7 @@ contract SuperformERC4626FormTest is ProtocolActions { superformId, daiAmount, 100, - LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), getContract(ETH, "DAI"), address(0), 1, ETH, 0), + LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), getContract(ETH, "DAI"), address(0), 4, ETH, 0), "", false, false, @@ -916,6 +916,46 @@ contract SuperformERC4626FormTest is ProtocolActions { LiFiMockRugpull(payable(getContract(ETH, "LiFiMockRugpull"))).pullTokens(getContract(ETH, "DAI"), superform); } + function test_blacklistedSelectors_reverts() public { + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + uint256 daiAmount = 10 * 1e18; // 10 DAI + address superform = getContract( + ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ); + uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); + bytes32 txId = keccak256("blacklisted"); + bytes memory blacklistedTxData = abi.encodeWithSelector( + LiFiMockBlacklisted.startBridgeTokensViaCBridgeNativeMin.selector, txId, address(0x1), 5, 5, 100 + ); + + SingleVaultSFData memory data = SingleVaultSFData( + superformId, + daiAmount, + 100, + LiqRequest(blacklistedTxData, getContract(ETH, "DAI"), address(0), 5, ETH, 0), + "", + false, + false, + receiverAddress, + receiverAddress, + "" + ); + + SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); + + address router = getContract(ETH, "SuperformRouter"); + + /// Make Superform's initial balance to 10 DAI + MockERC20(getContract(ETH, "DAI")).transfer(superform, daiAmount); + + /// Single deposit 10 DAI to the Superform + MockERC20(getContract(ETH, "DAI")).approve(router, daiAmount); + vm.expectRevert(Error.BLACKLISTED_SELECTOR.selector); + SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); + } + /*/////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index a349f7bd9..0be2916c5 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -2645,7 +2645,7 @@ contract SuperformRouterTest is ProtocolActions { false ), getContract(ETH, "DAI"), - address(0), + getContract(ARBI, "DAI"), 1, ARBI, 0 @@ -2662,7 +2662,6 @@ contract SuperformRouterTest is ProtocolActions { v.ambIds[0] = 1; v.ambIds[1] = 2; - v.data.liqRequest.interimToken = getContract(ARBI, "DAI"); SingleXChainSingleVaultStateReq memory req = SingleXChainSingleVaultStateReq(v.ambIds, ARBI, v.data); /// @dev approves before call diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index db59d5995..705cf696c 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -19,6 +19,7 @@ import { LiFiMock } from "../mocks/LiFiMock.sol"; import { SocketMock } from "../mocks/SocketMock.sol"; import { SocketOneInchMock } from "../mocks/SocketOneInchMock.sol"; import { LiFiMockRugpull } from "../mocks/LiFiMockRugpull.sol"; +import { LiFiMockBlacklisted } from "../mocks/LiFiMockBlacklisted.sol"; import { MockERC20 } from "../mocks/MockERC20.sol"; import { VaultMock } from "../mocks/VaultMock.sol"; @@ -531,6 +532,11 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { contracts[vars.chainId][bytes32(bytes("LiFiMockRugpull"))] = vars.liFiMockRugpull; vm.allowCheatcodes(vars.liFiMockRugpull); + /// @dev 7.1.5 deploy LiFiMockBlacklisted. This mock tests the behaviour of blacklisted selectors + vars.liFiMockBlacklisted = address(new LiFiMockBlacklisted{ salt: salt }()); + contracts[vars.chainId][bytes32(bytes("LiFiMockBlacklisted"))] = vars.liFiMockBlacklisted; + vm.allowCheatcodes(vars.liFiMockBlacklisted); + /// @dev 7.2.1- deploy lifi validator vars.lifiValidator = address(new LiFiValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("LiFiValidator"))] = vars.lifiValidator; @@ -551,11 +557,13 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { bridgeAddresses.push(vars.socketRouter); bridgeAddresses.push(vars.socketOneInch); bridgeAddresses.push(vars.liFiMockRugpull); + bridgeAddresses.push(vars.liFiMockBlacklisted); bridgeValidators.push(vars.lifiValidator); bridgeValidators.push(vars.socketValidator); bridgeValidators.push(vars.socketOneInchValidator); bridgeValidators.push(vars.lifiValidator); + bridgeValidators.push(vars.lifiValidator); /// @dev 8.1 - Deploy UNDERLYING_TOKENS and VAULTS for (uint256 j = 0; j < UNDERLYING_TOKENS.length; ++j) { @@ -902,9 +910,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), deployer, vars.dstChainId ); - vars.superRegistryC.setAddress( - vars.superRegistryC.SUPERFORM_RECEIVER(), deployer, vars.dstChainId - ); + vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_RECEIVER(), deployer, vars.dstChainId); } else { /// ack gas cost: 40000 /// timelock step form cost: 50000 @@ -1115,10 +1121,12 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { /// 2 is socket /// 3 is socket one inch impl /// 4 is lifi rugpull + /// 5 is lifi blacklist bridgeIds.push(1); bridgeIds.push(2); bridgeIds.push(3); bridgeIds.push(4); + bridgeIds.push(5); /// @dev setup users userKeys.push(1); diff --git a/test/utils/TestTypes.sol b/test/utils/TestTypes.sol index fdc20564d..e4650ea34 100644 --- a/test/utils/TestTypes.sol +++ b/test/utils/TestTypes.sol @@ -140,6 +140,7 @@ struct SetupVars { address socketRouter; address socketOneInch; address liFiMockRugpull; + address liFiMockBlacklisted; address erc4626Form; address erc4626TimelockForm; address kycDao4626Form; From ace2315772fcc3a1902419f91fa76162314a1384 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Mon, 25 Dec 2023 18:03:53 +0530 Subject: [PATCH 174/210] fix: csr size --- src/crosschain-data/extensions/CoreStateRegistry.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index c6a3cb21b..bd0721004 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -501,7 +501,6 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { returns (bytes memory newPayloadBody_, PayloadState finalState_) { InitSingleVaultData memory singleVaultData = abi.decode(prevPayloadBody_, (InitSingleVaultData)); - IDstSwapper dstSwapper = IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))); if (finalAmount_ == 0) { revert Error.ZERO_AMOUNT(); @@ -513,7 +512,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev observe not consuming the third return value (singleVaultData.amount, finalState_,) = _updateAmount( - dstSwapper, + IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))), singleVaultData.hasDstSwap, payloadId_, 0, @@ -723,7 +722,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { bool errors; uint256 len = multiVaultData.superformIds.length; - address superformFactory = superRegistry.getAddress(keccak256("SUPERFORM_FACTORY")); + address superformFactory = _getAddress(keccak256("SUPERFORM_FACTORY")); for (uint256 i; i < len; ++i) { // @dev validates if superformId exists on factory From 16c523ab4b8f6de1a72096f60ff98beed71eb722 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 25 Dec 2023 14:42:42 -0600 Subject: [PATCH 175/210] chore: add all missing natspec --- src/BaseForm.sol | 10 ++++--- src/crosschain-data/BaseStateRegistry.sol | 4 +-- .../layerzero/LayerzeroImplementation.sol | 27 +++++++++++++++---- .../WormholeSRImplementation.sol | 2 ++ .../extensions/TimelockStateRegistry.sol | 11 +++++--- src/payments/PaymentHelper.sol | 16 +++++------ src/settings/SuperRegistry.sol | 3 +++ 7 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/BaseForm.sol b/src/BaseForm.sol index 3c98c27c0..750915233 100644 --- a/src/BaseForm.sol +++ b/src/BaseForm.sol @@ -101,10 +101,6 @@ abstract contract BaseForm is IBaseForm, Initializable, ERC165 { // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// - function supportsInterface(bytes4 interfaceId_) public view virtual override(ERC165, IERC165) returns (bool) { - return interfaceId_ == type(IBaseForm).interfaceId || super.supportsInterface(interfaceId_); - } - /// @inheritdoc IBaseForm function superformYieldTokenName() external view virtual override returns (string memory); @@ -257,6 +253,12 @@ abstract contract BaseForm is IBaseForm, Initializable, ERC165 { _forwardDustToPaymaster(token_); } + /// @dev Checks if the Form implementation has the appropriate interface support + /// @param interfaceId_ is the interfaceId to check + function supportsInterface(bytes4 interfaceId_) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId_ == type(IBaseForm).interfaceId || super.supportsInterface(interfaceId_); + } + ////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/BaseStateRegistry.sol b/src/crosschain-data/BaseStateRegistry.sol index 7d68d7172..6cae8cdb9 100644 --- a/src/crosschain-data/BaseStateRegistry.sol +++ b/src/crosschain-data/BaseStateRegistry.sol @@ -52,12 +52,12 @@ abstract contract BaseStateRegistry is IBaseStateRegistry { // MODIFIERS // ////////////////////////////////////////////////////////////// - /// @dev sender varies based on functionality - /// @notice inheriting contracts should override this function (else not safe) + /// @dev inheriting contracts should override this function based on functionality modifier onlySender() virtual { _; } + /// @dev ensures that only added AMB implementations are accepted modifier onlyValidAmbImplementation() { if (!superRegistry.isValidAmbImpl(msg.sender)) { revert Error.NOT_AMB_IMPLEMENTATION(); diff --git a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol index c3c51b212..bf4ff4037 100644 --- a/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol +++ b/src/crosschain-data/adapters/layerzero/LayerzeroImplementation.sol @@ -101,7 +101,10 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio } } - /// @dev returns the configuration of this contract + /// @dev gets the configuration of the current LayerZero implementation supported + /// @param version_ is the messaging library version + /// @param chainId_ is the layerzero chainId for the pending config change + /// @param configType_ is the type of configuration function getConfig( uint16 version_, uint16 chainId_, @@ -115,7 +118,7 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio return lzEndpoint.getConfig(version_, chainId_, address(this), configType_); } - /// @dev allows protocol admin to configure UA on layerzero + /// @inheritdoc ILayerZeroUserApplicationConfig function setConfig( uint16 version_, uint16 chainId_, @@ -129,22 +132,24 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio lzEndpoint.setConfig(version_, chainId_, configType_, config_); } - /// @dev allows protocol admin to configure send version on layerzero + /// @inheritdoc ILayerZeroUserApplicationConfig function setSendVersion(uint16 version_) external override onlyProtocolAdmin { lzEndpoint.setSendVersion(version_); } - /// @dev allows protocol admin to configure receive version on layerzero + /// @inheritdoc ILayerZeroUserApplicationConfig function setReceiveVersion(uint16 version_) external override onlyProtocolAdmin { lzEndpoint.setReceiveVersion(version_); } - /// @dev allows protocol admin to unblock queue of messages if needed + /// @inheritdoc ILayerZeroUserApplicationConfig function forceResumeReceive(uint16 srcChainId_, bytes calldata srcAddress_) external override onlyEmergencyAdmin { lzEndpoint.forceResumeReceive(srcChainId_, srcAddress_); } /// @dev allows protocol admin to set contract which can receive messages + /// @param srcChainId_ is the layerzero source chain id + /// @param srcAddress_ is the address to set as the trusted remote on the source chain function setTrustedRemote(uint16 srcChainId_, bytes calldata srcAddress_) external onlyProtocolAdmin { trustedRemoteLookup[srcChainId_] = srcAddress_; emit SetTrustedRemote(srcChainId_, srcAddress_); @@ -154,6 +159,9 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// + /// @dev checks if another contract on another chain is a trusted remote + /// @param srcChainId_ is the layerzero source chain id + /// @param srcAddress_ is the address to check function isTrustedRemote(uint16 srcChainId_, bytes calldata srcAddress_) external view returns (bool) { if (srcChainId_ == 0) { revert Error.INVALID_CHAIN_ID(); @@ -263,6 +271,10 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio _blockingLzReceive(srcChainId_, srcAddress_, nonce_, payload_); } + /// @dev receive failed messages on this Endpoint destination + /// @param srcChainId_ is the layerzero source chain id + /// @param srcAddress_ is the address on the source chain + /// @param payload_ is the payload to store function nonblockingLzReceive(uint16 srcChainId_, bytes memory srcAddress_, bytes memory payload_) public { // only internal transaction if (msg.sender != address(this)) { @@ -272,6 +284,11 @@ contract LayerzeroImplementation is IAmbImplementation, ILayerZeroUserApplicatio _nonblockingLzReceive(srcChainId_, srcAddress_, payload_); } + /// @dev retry failed messages on this Endpoint destination + /// @param srcChainId_ is the layerzero source chain id + /// @param srcAddress_ is the address on the source chain + /// @param nonce_ is the sequential location of the stuck payload + /// @param payload_ is the payload to retry function retryMessage( uint16 srcChainId_, bytes memory srcAddress_, diff --git a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol index b469c0656..c83927429 100644 --- a/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol +++ b/src/crosschain-data/adapters/wormhole/specialized-relayer/WormholeSRImplementation.sol @@ -178,6 +178,8 @@ contract WormholeSRImplementation is IBroadcastAmbImplementation { } } + /// @dev function to receive broadcasted messages via Wormhole SR's + /// @param encodedMessage_ is the message to receive function receiveMessage(bytes memory encodedMessage_) public onlyWormholeVAARelayer { /// @dev 1. validate caller /// @dev 2. validate not broadcasted to emitter chain diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index 88b331ed8..279a723c9 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -56,12 +56,13 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree _; } - /// @dev allows only form to write to the receive payload - modifier onlyTimelockSuperform(uint256 superformId) { - if (!ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(superformId)) { + /// @dev ensures only the timelock form can write to a timelock superform + /// @param superformId_ is the superformId of the superform to check + modifier onlyTimelockSuperform(uint256 superformId_) { + if (!ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(superformId_)) { revert Error.SUPERFORM_ID_NONEXISTENT(); } - (address superform,,) = superformId.getSuperform(); + (address superform,,) = superformId_.getSuperform(); if (msg.sender != superform) revert Error.NOT_SUPERFORM(); if (IBaseForm(superform).getStateRegistryId() != superRegistry.getStateRegistryId(address(this))) { @@ -71,6 +72,8 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree _; } + /// @dev ensures only valid payloads are processed + /// @param payloadId_ is the payloadId to check modifier isValidPayloadId(uint256 payloadId_) { if (payloadId_ > payloadsCount) { revert Error.INVALID_PAYLOAD_ID(); diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 8474700e3..4fad7b897 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -78,6 +78,14 @@ contract PaymentHelper is IPaymentHelper { bytes message; } + struct LocalEstimateVars { + uint256 len; + uint256 superformIdsLen; + uint256 totalDstGas; + uint256 ambFees; + bool paused; + } + ////////////////////////////////////////////////////////////// // MODIFIERS // ////////////////////////////////////////////////////////////// @@ -140,14 +148,6 @@ contract PaymentHelper is IPaymentHelper { return extraDataForTransmuter; } - struct LocalEstimateVars { - uint256 len; - uint256 superformIdsLen; - uint256 totalDstGas; - uint256 ambFees; - bool paused; - } - /// @inheritdoc IPaymentHelper function estimateMultiDstMultiVault( MultiDstMultiVaultStateReq calldata req_, diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index 9be2a685f..b9c5b7c6f 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -154,11 +154,13 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// + /// @inheritdoc ISuperRegistry function getAddress(bytes32 id_) external view override returns (address addr) { addr = registry[id_][CHAIN_ID]; if (addr == address(0)) revert Error.ZERO_ADDRESS(); } + /// @inheritdoc ISuperRegistry function getAddressByChainId(bytes32 id_, uint64 chainId_) external view override returns (address addr) { addr = registry[id_][chainId_]; if (addr == address(0)) revert Error.ZERO_ADDRESS(); @@ -232,6 +234,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { return false; } + /// @inheritdoc ISuperRegistry function PERMIT2() external view override returns (address) { if (permit2Address == address(0)) revert Error.ZERO_ADDRESS(); return permit2Address; From ad556d423f448c97d36ae1d2765a9730862c7460 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 25 Dec 2023 15:01:20 -0600 Subject: [PATCH 176/210] chore: SUP-4987 --- src/crosschain-data/extensions/CoreStateRegistry.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 81a252b15..19ff9e10c 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -236,7 +236,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { revert Error.RESCUE_ALREADY_PROPOSED(); } - /// @dev note: should set this value to dstSwapper.failedSwap().amount for interim rescue + /// @dev should set this value to dstSwapper.failedSwap().amount for interim rescue failedDeposits[payloadId_].amounts = proposedAmounts_; failedDeposits[payloadId_].lastProposedTimestamp = block.timestamp; @@ -584,6 +584,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev if superform is invalid, try catch will fail and asset pushed is address (0) /// @notice this means that if a user tries to game the protocol with an invalid superformId, the funds /// bridged over that failed will be stuck here + /// @notice assets can still be spoofed with any vault.asset(), hence this is done via permissioned role failedDeposits[payloadId_].settlementToken.push(asset); failedDeposits[payloadId_].settleFromDstSwapper.push(false); From 9e6cdf463ceb0d8d84167b61259b2245e41624ed Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 25 Dec 2023 16:48:38 -0600 Subject: [PATCH 177/210] chore: make payloadhelper consistent with datatypes --- src/crosschain-data/utils/PayloadHelper.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index efbc9e853..3c14a73f9 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -141,10 +141,10 @@ contract PayloadHelper is IPayloadHelper { view override returns ( - uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, address[] memory interimTokens, + uint8[] memory bridgeIds, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts @@ -359,10 +359,10 @@ contract PayloadHelper is IPayloadHelper { internal view returns ( - uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, address[] memory interimTokens, + uint8[] memory bridgeIds, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts @@ -404,10 +404,10 @@ contract PayloadHelper is IPayloadHelper { internal view returns ( - uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, address[] memory interimTokens, + uint8[] memory bridgeIds, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts From 11a2523ad807ce2c6aae182f3409eb0e5a06964a Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 25 Dec 2023 16:58:27 -0600 Subject: [PATCH 178/210] chore: dst swapper interface --- src/interfaces/IDstSwapper.sol | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/interfaces/IDstSwapper.sol b/src/interfaces/IDstSwapper.sol index 58ee5d714..b695f9c21 100644 --- a/src/interfaces/IDstSwapper.sol +++ b/src/interfaces/IDstSwapper.sol @@ -65,6 +65,19 @@ interface IDstSwapper { /// @param txData_ represents the transaction data generated by liquidity bridge API. function processTx(uint256 payloadId_, uint8 bridgeId_, bytes calldata txData_) external; + /// @notice will process dst swaps in batch through a liquidity bridge + /// @param payloadId_ represents the array of payload ids used + /// @param indices_ represents the index of the superformid in the payload + /// @param bridgeIds_ represents the array of ids of liquidity bridges used + /// @param txData_ represents the array of transaction data generated by liquidity bridge API + function batchProcessTx( + uint256 payloadId_, + uint256[] calldata indices_, + uint8[] calldata bridgeIds_, + bytes[] calldata txData_ + ) + external; + /// @notice updates the amounts of intermediary tokens stuck because of failing dst swap /// @param payloadId_ represents the id of the payload /// @param interimToken_ is the intermediary token that cannot be swapped to the vault underlying @@ -84,19 +97,6 @@ interface IDstSwapper { ) external; - /// @notice will process dst swaps in batch through a liquidity bridge - /// @param payloadId_ represents the array of payload ids used - /// @param indices_ represents the index of the superformid in the payload - /// @param bridgeIds_ represents the array of ids of liquidity bridges used - /// @param txData_ represents the array of transaction data generated by liquidity bridge API - function batchProcessTx( - uint256 payloadId_, - uint256[] calldata indices_, - uint8[] calldata bridgeIds_, - bytes[] calldata txData_ - ) - external; - /// @notice is a privileged function that allows Core State Registry to process refunds /// @param user_ is the final refund receiver of the interimToken_ /// @param interimToken_ is the refund token From ba0ba0119044afe02ed180c698867a07b2d99aac Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 25 Dec 2023 17:07:01 -0600 Subject: [PATCH 179/210] chore: fix payloadhelper tests --- src/crosschain-liquidity/DstSwapper.sol | 6 +++--- src/interfaces/IDstSwapper.sol | 4 ++-- src/interfaces/IPayloadHelper.sol | 4 ++-- .../crosschain-data/utils/PayloadHelper.multiVault.t.sol | 2 +- .../crosschain-data/utils/PayloadHelper.singleVault.t.sol | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index ae677d7b4..bd065315f 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -167,14 +167,14 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { uint256 payloadId_, uint256[] calldata indices_, uint8[] calldata bridgeIds_, - bytes[] calldata txData_ + bytes[] calldata txDatas_ ) external override nonReentrant onlySwapper { - uint256 len = txData_.length; + uint256 len = txDatas_.length; if (len == 0) revert Error.ZERO_INPUT_VALUE(); if (len != indices_.length && len != bridgeIds_.length) revert Error.ARRAY_LENGTH_MISMATCH(); @@ -198,7 +198,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { } _processTx( - payloadId_, index, bridgeIds_[i], txData_[i], data.liqData[index].interimToken, coreStateRegistry + payloadId_, index, bridgeIds_[i], txDatas_[i], data.liqData[index].interimToken, coreStateRegistry ); } } diff --git a/src/interfaces/IDstSwapper.sol b/src/interfaces/IDstSwapper.sol index b695f9c21..e0abc6d3b 100644 --- a/src/interfaces/IDstSwapper.sol +++ b/src/interfaces/IDstSwapper.sol @@ -69,12 +69,12 @@ interface IDstSwapper { /// @param payloadId_ represents the array of payload ids used /// @param indices_ represents the index of the superformid in the payload /// @param bridgeIds_ represents the array of ids of liquidity bridges used - /// @param txData_ represents the array of transaction data generated by liquidity bridge API + /// @param txDatas_ represents the array of transaction data generated by liquidity bridge API function batchProcessTx( uint256 payloadId_, uint256[] calldata indices_, uint8[] calldata bridgeIds_, - bytes[] calldata txData_ + bytes[] calldata txDatas_ ) external; diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index 2fda98bb3..d86502b27 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -42,10 +42,10 @@ interface IPayloadHelper { /// @dev reads the payload from the core state registry and decodes liqData for it (to be used in withdraw cases) /// @param dstPayloadId_ is the unique identifier of the payload received in dst core state registry - /// @return bridgeIds are the ids of the bridges to be used /// @return txDatas are the array of txData to be sent to the bridges /// @return tokens are the tokens to be used in the liqData /// @return interimTokens are the interim tokens to be used in the liqData + /// @return bridgeIds are the ids of the bridges to be used /// @return liqDstChainIds are the final destination chain id for the underlying token (can be arbitrary on /// withdraws) /// @return amountsIn are the from amounts to the liquidity bridge @@ -54,10 +54,10 @@ interface IPayloadHelper { external view returns ( - uint8[] memory bridgeIds, bytes[] memory txDatas, address[] memory tokens, address[] memory interimTokens, + uint8[] memory bridgeIds, uint64[] memory liqDstChainIds, uint256[] memory amountsIn, uint256[] memory nativeAmounts diff --git a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol index 0d1c5d2e8..604a33bfd 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol @@ -266,7 +266,7 @@ contract PayloadHelperMultiTest is ProtocolActions { vm.selectFork(FORKS[DST_CHAINS[0]]); CheckDstPayloadLiqDataInternalVars memory v; - (v.bridgeIds, v.txDatas, v.tokens,, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( + (v.txDatas, v.tokens,, v.bridgeIds, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))] ).decodeCoreStateRegistryPayloadLiqData(2); diff --git a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol index 177e8c66a..b89c3e8ce 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol @@ -297,7 +297,7 @@ contract PayloadHelperSingleTest is ProtocolActions { vm.selectFork(FORKS[DST_CHAINS[0]]); CheckDstPayloadLiqDataInternalVars memory v; - (v.bridgeIds, v.txDatas, v.tokens,, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( + (v.txDatas, v.tokens,, v.bridgeIds, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))] ).decodeCoreStateRegistryPayloadLiqData(2); From d66c14c390d074b2019936868abecd2c6309200e Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Mon, 25 Dec 2023 18:12:33 -0600 Subject: [PATCH 180/210] chore: final readthrough --- src/BaseRouter.sol | 3 +- src/BaseRouterImplementation.sol | 5 +- src/SuperPositions.sol | 1 + src/SuperformFactory.sol | 2 +- .../extensions/TimelockStateRegistry.sol | 2 +- src/crosschain-data/utils/QuorumManager.sol | 2 +- .../socket/SocketValidator.sol | 2 +- src/forms/ERC4626Form.sol | 2 +- src/forms/ERC4626FormImplementation.sol | 2 +- src/forms/ERC4626KYCDaoForm.sol | 3 +- src/forms/interfaces/IERC4626Form.sol | 2 +- src/interfaces/IAmbImplementation.sol | 2 +- src/interfaces/IBaseRouter.sol | 2 +- src/interfaces/IBaseRouterImplementation.sol | 2 +- src/interfaces/IBaseStateRegistry.sol | 2 +- src/interfaces/IBridgeValidator.sol | 2 +- .../IBroadcastAmbImplementation.sol | 2 +- src/interfaces/IBroadcastRegistry.sol | 2 +- src/interfaces/ICoreStateRegistry.sol | 2 +- src/interfaces/IDstSwapper.sol | 2 +- src/interfaces/IEmergencyQueue.sol | 3 + src/interfaces/IPayMaster.sol | 2 +- src/interfaces/IPayloadHelper.sol | 2 +- src/interfaces/IPaymentHelper.sol | 2 +- src/interfaces/IQuorumManager.sol | 2 +- src/interfaces/ISuperPositions.sol | 2 +- src/interfaces/ISuperRBAC.sol | 2 +- src/interfaces/ISuperRegistry.sol | 2 +- src/interfaces/ISuperformFactory.sol | 2 +- src/interfaces/ITimelockStateRegistry.sol | 2 +- src/libraries/Error.sol | 97 ++++++++++++------- src/settings/SuperRBAC.sol | 2 +- 32 files changed, 95 insertions(+), 69 deletions(-) diff --git a/src/BaseRouter.sol b/src/BaseRouter.sol index dd5a06a01..d65137006 100644 --- a/src/BaseRouter.sol +++ b/src/BaseRouter.sol @@ -9,8 +9,7 @@ import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title BaseRouter -/// @dev Routes users funds and action information to a remote execution chain. -/// @dev abstract implementation that allows inheriting contract to implement the logic +/// @dev Abstract implementation that allows Routers to implement the logic /// @author Zeropoint Labs abstract contract BaseRouter is IBaseRouter { diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index f7b3d247f..a78551608 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -610,7 +610,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou false, retain4626_, receiverAddress_, - /// needed if user if keeping 4626 extraFormData_ ), srcSender_ @@ -689,7 +688,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); /// @dev if retain4626 is set to True, set the amount of SuperPositions to mint to 0 - if (v.shares[i] != 0 && args_.vaultData.retain4626s[i]) { v.shares[i] = 0; } @@ -857,7 +855,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } } - /// if it reaches this point then is valid return true; } @@ -1002,7 +999,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou abi.decode(permit2data_, (uint256, uint256, bytes)); /// @dev moves the tokens from the user to the router - IPermit2(v.permit2).permitTransferFrom( // The permit message. IPermit2.PermitTransferFrom({ @@ -1095,6 +1091,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou abi.decode(permit2data_, (uint256, uint256, bytes)); v.permit2 = _getPermit2(); + /// @dev moves the tokens from the user to the router IPermit2(v.permit2).permitTransferFrom( // The permit message. diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index a23a5afcc..21e1564fe 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -32,6 +32,7 @@ contract SuperPositions is ISuperPositions, ERC1155A { ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// + ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; bytes32 constant DEPLOY_NEW_AERC20 = keccak256("DEPLOY_NEW_AERC20"); diff --git a/src/SuperformFactory.sol b/src/SuperformFactory.sol index a030ce8df..33f8f56b3 100644 --- a/src/SuperformFactory.sol +++ b/src/SuperformFactory.sol @@ -218,7 +218,7 @@ contract SuperformFactory is ISuperformFactory { vaultToSuperforms[vault_].push(superformId_); - /// @dev Mapping vaults to formImplementationId for use in Backend + /// @dev map vaults to formImplementationId vaultToFormImplementationId[vault_].push(formImplementationId_); vaultFormImplCombinationToSuperforms[vaultFormImplementationCombination] = superformId_; diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index 279a723c9..c39fa639c 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -85,7 +85,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(ISuperRegistry superRegistry_) BaseStateRegistry(superRegistry_) { } + constructor(ISuperRegistry superRegistry_) BaseStateRegistry(superRegistry_) {} ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/crosschain-data/utils/QuorumManager.sol b/src/crosschain-data/utils/QuorumManager.sol index 185a411ef..42c596e15 100644 --- a/src/crosschain-data/utils/QuorumManager.sol +++ b/src/crosschain-data/utils/QuorumManager.sol @@ -5,7 +5,7 @@ import { IQuorumManager } from "src/interfaces/IQuorumManager.sol"; import { Error } from "src/libraries/Error.sol"; /// @title QuorumManager -/// @dev Quorum management to send messages from chain to chain +/// @dev Quorum thresholds using in sending proofs from chain to chain /// @author ZeroPoint Labs abstract contract QuorumManager is IQuorumManager { diff --git a/src/crosschain-liquidity/socket/SocketValidator.sol b/src/crosschain-liquidity/socket/SocketValidator.sol index 4355cbe52..7097d05e8 100644 --- a/src/crosschain-liquidity/socket/SocketValidator.sol +++ b/src/crosschain-liquidity/socket/SocketValidator.sol @@ -6,7 +6,7 @@ import { Error } from "src/libraries/Error.sol"; import { ISocketRegistry } from "src/vendor/socket/ISocketRegistry.sol"; /// @title SocketValidator -/// @dev Asserts Socket x-chain input txData is valid +/// @dev Asserts Socket x-chain input txData is valid /// @author Zeropoint Labs contract SocketValidator is BridgeValidator { diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index bd80e103c..7bee1544d 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -6,7 +6,7 @@ import { BaseForm } from "src/BaseForm.sol"; import { InitSingleVaultData } from "src/types/DataTypes.sol"; /// @title ERC4626Form -/// @dev The Form implementation for IERC4626 vaults +/// @dev The Form implementation for normal ERC4626 vaults /// @author Zeropoint Labs contract ERC4626Form is ERC4626FormImplementation { diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index c77de1765..8743c2039 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -13,7 +13,7 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; /// @title ERC4626FormImplementation -/// @dev Has common internal functions that can be re-used by actual form implementations +/// @dev Has common ERC4626 internal functions that can be re-used by implementations /// @author Zeropoint Labs abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index 0805d203b..d565f1335 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -12,8 +12,7 @@ import { ERC721Holder } from "openzeppelin-contracts/contracts/token/ERC721/util /// @title ERC4626KYCDaoForm -/// @dev The Form implementation for IERC4626 vaults with kycDAO NFT checks -/// @dev This form must hold a kycDAO NFT to operate +/// @dev The Form implementation for kycDAO-gated ERC4626 vaults, must hold kycDAO NFT /// @author Zeropoint Labs contract ERC4626KYCDaoForm is ERC4626FormImplementation, ERC721Holder { diff --git a/src/forms/interfaces/IERC4626Form.sol b/src/forms/interfaces/IERC4626Form.sol index dd0ff1668..14cb791f1 100644 --- a/src/forms/interfaces/IERC4626Form.sol +++ b/src/forms/interfaces/IERC4626Form.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; /// @title IERC4626Form -/// @dev The Interface for the ERC4626Form +/// @dev Interface for ERC4626Form /// @author Zeropoint Labs interface IERC4626Form is IERC20 { diff --git a/src/interfaces/IAmbImplementation.sol b/src/interfaces/IAmbImplementation.sol index 9928298cc..29e6ccf81 100644 --- a/src/interfaces/IAmbImplementation.sol +++ b/src/interfaces/IAmbImplementation.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title IAmbImplementation -/// @dev interface for arbitrary message bridge implementation +/// @dev Interface for arbitrary message bridge (AMB) implementations /// @author ZeroPoint Labs interface IAmbImplementation { diff --git a/src/interfaces/IBaseRouter.sol b/src/interfaces/IBaseRouter.sol index 4e6683836..7679081b7 100644 --- a/src/interfaces/IBaseRouter.sol +++ b/src/interfaces/IBaseRouter.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import "src/types/DataTypes.sol"; /// @title IBaseRouter -/// @dev interface for abstract Router +/// @dev Interface for abstract BaseRouter /// @author Zeropoint Labs interface IBaseRouter { diff --git a/src/interfaces/IBaseRouterImplementation.sol b/src/interfaces/IBaseRouterImplementation.sol index 619c12f16..91c097203 100644 --- a/src/interfaces/IBaseRouterImplementation.sol +++ b/src/interfaces/IBaseRouterImplementation.sol @@ -5,7 +5,7 @@ import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import "src/types/DataTypes.sol"; /// @title IBaseRouterImplementation -/// @dev interface for BaseRouterImplementation +/// @dev Interface for BaseRouterImplementation /// @author Zeropoint Labs interface IBaseRouterImplementation is IBaseRouter { diff --git a/src/interfaces/IBaseStateRegistry.sol b/src/interfaces/IBaseStateRegistry.sol index 929475d7d..52c75fa9b 100644 --- a/src/interfaces/IBaseStateRegistry.sol +++ b/src/interfaces/IBaseStateRegistry.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import "src/types/DataTypes.sol"; /// @title IBaseStateRegistry -/// @dev Crosschain interaction point: send, store & process crosschain messages +/// @dev Interface for BaseStateRegistry /// @author ZeroPoint Labs interface IBaseStateRegistry { diff --git a/src/interfaces/IBridgeValidator.sol b/src/interfaces/IBridgeValidator.sol index 229f39bbe..3f9dd43a9 100644 --- a/src/interfaces/IBridgeValidator.sol +++ b/src/interfaces/IBridgeValidator.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title Bridge Validator Interface -/// @dev Validate and handle bridging of tokens +/// @dev Interface all Bridge Validators must follow /// @author Zeropoint Labs interface IBridgeValidator { diff --git a/src/interfaces/IBroadcastAmbImplementation.sol b/src/interfaces/IBroadcastAmbImplementation.sol index 55e20b6df..545c045bf 100644 --- a/src/interfaces/IBroadcastAmbImplementation.sol +++ b/src/interfaces/IBroadcastAmbImplementation.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title IBroadcastAmbImplementation -/// @dev interface for arbitrary message bridge implementation the supports broadcasting +/// @dev Interface for AMBs used in Broadcasting /// @author ZeroPoint Labs interface IBroadcastAmbImplementation { diff --git a/src/interfaces/IBroadcastRegistry.sol b/src/interfaces/IBroadcastRegistry.sol index 31d586a93..d875fe3e8 100644 --- a/src/interfaces/IBroadcastRegistry.sol +++ b/src/interfaces/IBroadcastRegistry.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title IBroadcastRegistry -/// @dev is an helper for base state registry with broadcasting abilities +/// @dev Interface for BroadcastRegistry /// @author ZeroPoint Labs interface IBroadcastRegistry { diff --git a/src/interfaces/ICoreStateRegistry.sol b/src/interfaces/ICoreStateRegistry.sol index 4a79d6274..e45c79681 100644 --- a/src/interfaces/ICoreStateRegistry.sol +++ b/src/interfaces/ICoreStateRegistry.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title ICoreStateRegistry -/// @dev Interface for Core State Registry +/// @dev Interface for CoreStateRegistry /// @author ZeroPoint Labs interface ICoreStateRegistry { diff --git a/src/interfaces/IDstSwapper.sol b/src/interfaces/IDstSwapper.sol index e0abc6d3b..62bad9b90 100644 --- a/src/interfaces/IDstSwapper.sol +++ b/src/interfaces/IDstSwapper.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title IDstSwapper -/// @dev handles all destination chain swaps, accessed by superform keepers +/// @dev Interface for DstSwapper /// @author Zeropoint Labs interface IDstSwapper { diff --git a/src/interfaces/IEmergencyQueue.sol b/src/interfaces/IEmergencyQueue.sol index bd6c307ec..5d2daa982 100644 --- a/src/interfaces/IEmergencyQueue.sol +++ b/src/interfaces/IEmergencyQueue.sol @@ -3,6 +3,9 @@ pragma solidity ^0.8.23; import { InitSingleVaultData } from "src/types/DataTypes.sol"; +/// @title IEmergencyQueue +/// @dev Interface for EmergencyQueue +/// @author ZeroPoint Labs interface IEmergencyQueue { ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IPayMaster.sol b/src/interfaces/IPayMaster.sol index 6b067bf50..50448e658 100644 --- a/src/interfaces/IPayMaster.sol +++ b/src/interfaces/IPayMaster.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import { LiqRequest } from "src/types/DataTypes.sol"; /// @title IPayMaster -/// @dev contract for destination transaction costs payment +/// @dev Interface for PayMaster /// @author ZeroPoint Labs interface IPayMaster { diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index d86502b27..ea313c771 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title IPayloadHelper -/// @dev helps decoding the bytes payload and returns meaningful information +/// @dev Interface for PayloadHelper /// @author ZeroPoint Labs interface IPayloadHelper { diff --git a/src/interfaces/IPaymentHelper.sol b/src/interfaces/IPaymentHelper.sol index 5217d9d78..c84019d6d 100644 --- a/src/interfaces/IPaymentHelper.sol +++ b/src/interfaces/IPaymentHelper.sol @@ -11,7 +11,7 @@ import { } from "src/types/DataTypes.sol"; /// @title IPaymentHelper -/// @dev helps decoding the bytes payload and returns meaningful information +/// @dev Interface for PaymentHelper /// @author ZeroPoint Labs interface IPaymentHelper { diff --git a/src/interfaces/IQuorumManager.sol b/src/interfaces/IQuorumManager.sol index 1f632fd25..813d1d0e2 100644 --- a/src/interfaces/IQuorumManager.sol +++ b/src/interfaces/IQuorumManager.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title IQuorumManager -/// @dev interface to manage the quorum needed to send messages from chain to chain +/// @dev Interface for QuorumManager /// @author ZeroPoint Labs interface IQuorumManager { diff --git a/src/interfaces/ISuperPositions.sol b/src/interfaces/ISuperPositions.sol index a88d07184..1f1dd069a 100644 --- a/src/interfaces/ISuperPositions.sol +++ b/src/interfaces/ISuperPositions.sol @@ -5,7 +5,7 @@ import { IERC1155A } from "ERC1155A/interfaces/IERC1155A.sol"; import { AMBMessage } from "../types/DataTypes.sol"; /// @title ISuperPositions -/// @dev interface for SuperPositions +/// @dev Interface for SuperPositions /// @author Zeropoint Labs interface ISuperPositions is IERC1155A { diff --git a/src/interfaces/ISuperRBAC.sol b/src/interfaces/ISuperRBAC.sol index 8ad7debd5..3b9a6abb1 100644 --- a/src/interfaces/ISuperRBAC.sol +++ b/src/interfaces/ISuperRBAC.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import { IAccessControl } from "openzeppelin-contracts/contracts/access/IAccessControl.sol"; /// @title ISuperRBAC -/// @dev interface for Super RBAC +/// @dev Interface for SuperRBAC /// @author Zeropoint Labs interface ISuperRBAC is IAccessControl { diff --git a/src/interfaces/ISuperRegistry.sol b/src/interfaces/ISuperRegistry.sol index 6c4f265f5..e5e31511b 100644 --- a/src/interfaces/ISuperRegistry.sol +++ b/src/interfaces/ISuperRegistry.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title ISuperRegistry -/// @dev interface for SuperRegistry +/// @dev Interface for SuperRegistry /// @author Zeropoint Labs interface ISuperRegistry { diff --git a/src/interfaces/ISuperformFactory.sol b/src/interfaces/ISuperformFactory.sol index b3fb7022a..d1d7e4c0d 100644 --- a/src/interfaces/ISuperformFactory.sol +++ b/src/interfaces/ISuperformFactory.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.23; /// @title ISuperformFactory -/// @dev Interface for Superform Factory +/// @dev Interface for SuperformFactory /// @author ZeroPoint Labs interface ISuperformFactory { diff --git a/src/interfaces/ITimelockStateRegistry.sol b/src/interfaces/ITimelockStateRegistry.sol index 215b0f999..760ef4e4a 100644 --- a/src/interfaces/ITimelockStateRegistry.sol +++ b/src/interfaces/ITimelockStateRegistry.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import { InitSingleVaultData, TimelockPayload } from "src/types/DataTypes.sol"; /// @title ITimelockStateRegistry -/// @dev Interface for Timelock Form State Registry +/// @dev Interface for TimelockStateRegistry /// @author ZeroPoint Labs interface ITimelockStateRegistry { diff --git a/src/libraries/Error.sol b/src/libraries/Error.sol index 934703d79..1c86dbf50 100644 --- a/src/libraries/Error.sol +++ b/src/libraries/Error.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.23; library Error { + ////////////////////////////////////////////////////////////// // CONFIGURATION ERRORS // ////////////////////////////////////////////////////////////// @@ -22,17 +23,14 @@ library Error { /// @dev thrown if rescue delay is not yet set for a chain error DELAY_NOT_SET(); - /// @dev thrown if wormhole relayer is not set - error RELAYER_NOT_SET(); - /// @dev thrown if get native token price estimate in paymentHelper is 0 error INVALID_NATIVE_TOKEN_PRICE(); - /// @dev thrown if indices are out of bounds - error INDEX_OUT_OF_BOUNDS(); + /// @dev thrown if wormhole refund chain id is not set + error REFUND_CHAIN_ID_NOT_SET(); - /// @dev thrown if indices have duplicates - error DUPLICATE_INDEX(); + /// @dev thrown if wormhole relayer is not set + error RELAYER_NOT_SET(); /// @dev thrown if a role to be revoked is not assigned error ROLE_NOT_ASSIGNED(); @@ -43,6 +41,8 @@ library Error { ///@notice errors thrown if functions cannot be called /// COMMON AUTHORIZATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if caller is not address(this), internal call error INVALID_INTERNAL_CALL(); @@ -73,9 +73,6 @@ library Error { /// @dev thrown if msg.sender is not minter state registry error NOT_MINTER_STATE_REGISTRY_ROLE(); - /// @dev thrown if refund chain id is not set - error REFUND_CHAIN_ID_NOT_SET(); - /// @dev thrown if msg.sender is not paymaster error NOT_PAYMASTER(); @@ -113,6 +110,8 @@ library Error { error NOT_PRIVILEGED_CALLER(bytes32 role); /// STATE REGISTRY AUTHORIZATION ERRORS + /// --------------------------------------------------------- + /// @dev layerzero adapter specific error, thrown if caller not layerzero endpoint error CALLER_NOT_ENDPOINT(); @@ -131,12 +130,17 @@ library Error { ///@notice errors thrown if input variables are not valid /// COMMON INPUT VALIDATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if there is an array length mismatch error ARRAY_LENGTH_MISMATCH(); /// @dev thrown if payload id does not exist error INVALID_PAYLOAD_ID(); + /// @dev error thrown when msg value should be zero in certain payable functions + error MSG_VALUE_NOT_ZERO(); + /// @dev thrown if amb ids length is 0 error ZERO_AMB_ID_LENGTH(); @@ -150,6 +154,8 @@ library Error { error ZERO_INPUT_VALUE(); /// SUPERFORM ROUTER INPUT VALIDATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if the vaults data is invalid error INVALID_SUPERFORMS_DATA(); @@ -157,6 +163,8 @@ library Error { error RECEIVER_ADDRESS_NOT_SET(); /// SUPERFORM FACTORY INPUT VALIDATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if a form is not ERC165 compatible error ERC165_UNSUPPORTED(); @@ -182,6 +190,8 @@ library Error { error VAULT_FORM_IMPLEMENTATION_COMBINATION_EXISTS(); /// FORM INPUT VALIDATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if in case of no txData, if liqData.token != vault.asset() /// in case of txData, if token output of swap != vault.asset() error DIFFERENT_TOKENS(); @@ -193,6 +203,8 @@ library Error { error XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); /// LIQUIDITY BRIDGE INPUT VALIDATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if a certain action of the user is not allowed given the txData provided error INVALID_ACTION(); @@ -218,6 +230,8 @@ library Error { error NO_TXDATA_PRESENT(); /// STATE REGISTRY INPUT VALIDATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if payload is being updated with final amounts length different than amounts length error DIFFERENT_PAYLOAD_UPDATE_AMOUNTS_LENGTH(); @@ -255,21 +269,22 @@ library Error { error SLIPPAGE_OUT_OF_BOUNDS(); /// SUPERPOSITION INPUT VALIDATION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if src senders mismatch in state sync error SRC_SENDER_MISMATCH(); /// @dev thrown if src tx types mismatch in state sync error SRC_TX_TYPE_MISMATCH(); - /// @dev error thrown when msg value should be zero in certain payable functions - error MSG_VALUE_NOT_ZERO(); - ////////////////////////////////////////////////////////////// // EXECUTION ERRORS // ////////////////////////////////////////////////////////////// ///@notice errors thrown due to function execution logic /// COMMON EXECUTION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if the swap in a direct deposit resulted in insufficient tokens error DIRECT_DEPOSIT_SWAP_FAILED(); @@ -282,6 +297,9 @@ library Error { /// @dev thrown if allowance is not correct to deposit error INSUFFICIENT_ALLOWANCE_FOR_DEPOSIT(); + /// @dev thrown if contract has insufficient balance for operations + error INSUFFICIENT_BALANCE(); + /// @dev thrown if native amount is not at least equal to the amount in the request error INSUFFICIENT_NATIVE_AMOUNT(); @@ -294,10 +312,9 @@ library Error { /// @dev thrown if payload type is invalid error INVALID_PAYLOAD_TYPE(); - /// @dev thrown if contract has insufficient balance for operations - error INSUFFICIENT_BALANCE(); - /// LIQUIDITY BRIDGE EXECUTION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if we try to decode the final swap output token in a xChain liquidity bridging action error CANNOT_DECODE_FINAL_SWAP_OUTPUT_TOKEN(); @@ -308,6 +325,8 @@ library Error { error INVALID_DEPOSIT_TOKEN(); /// STATE REGISTRY EXECUTION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if bridge tokens haven't arrived to destination error BRIDGE_TOKENS_PENDING(); @@ -362,33 +381,20 @@ library Error { /// @dev thrown if payload hash is zero during `retryMessage` on Layezero implementation error ZERO_PAYLOAD_HASH(); - /// @dev thrown in forms where a certain functionality is not allowed or implemented - error NOT_IMPLEMENTED(); - - /// @dev thrown when redeeming from vault yields zero collateral - error WITHDRAW_ZERO_COLLATERAL(); - - /*/////////////////////////////////////////////////////////////// - PAYMASTER ERRORS - //////////////////////////////////////////////////////////////*/ - /// @dev cannot forward 4626 shares from any form - error CANNOT_FORWARD_4646_TOKEN(); - /// DST SWAPPER EXECUTION ERRORS - /// @dev forbid xChain deposits with destination swaps without interim token set (for user protection) - error INVALID_INTERIM_TOKEN(); + /// --------------------------------------------------------- /// @dev thrown if process dst swap is tried for processed payload id error DST_SWAP_ALREADY_PROCESSED(); + /// @dev thrown if indices have duplicates + error DUPLICATE_INDEX(); + /// @dev thrown if failed dst swap is already updated error FAILED_DST_SWAP_ALREADY_UPDATED(); - /// @dev thrown if failed dst swap is already processed - error FAILED_DST_SWAP_ALREADY_PROCESSED(); - - /// @dev thrown if dst swap output is less than minimum expected - error INVALID_SWAP_OUTPUT(); + /// @dev thrown if indices are out of bounds + error INDEX_OUT_OF_BOUNDS(); /// @dev thrown if failed swap token amount is 0 error INVALID_DST_SWAPPER_FAILED_SWAP(); @@ -399,11 +405,24 @@ library Error { /// @dev thrown if failed swap token amount is not 0 and if native amount is less than amount (non zero) error INVALID_DST_SWAPPER_FAILED_SWAP_NO_NATIVE_BALANCE(); + /// @dev forbid xChain deposits with destination swaps without interim token set (for user protection) + error INVALID_INTERIM_TOKEN(); + + /// @dev thrown if dst swap output is less than minimum expected + error INVALID_SWAP_OUTPUT(); + /// FORM EXECUTION ERRORS + /// --------------------------------------------------------- + + /// @dev thrown if try to forward 4626 share from the superform + error CANNOT_FORWARD_4646_TOKEN(); /// @dev thrown in KYCDAO form if no KYC token is present error NO_VALID_KYC_TOKEN(); + /// @dev thrown in forms where a certain functionality is not allowed or implemented + error NOT_IMPLEMENTED(); + /// @dev thrown if form implementation is PAUSED, users cannot perform any action error PAUSED(); @@ -416,7 +435,12 @@ library Error { /// @dev thrown if withdrawal tx data is not updated error WITHDRAW_TX_DATA_NOT_UPDATED(); + /// @dev thrown when redeeming from vault yields zero collateral + error WITHDRAW_ZERO_COLLATERAL(); + /// PAYMENT HELPER EXECUTION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if chainlink is reporting an improper price error CHAINLINK_MALFUNCTION(); @@ -427,6 +451,7 @@ library Error { error CHAINLINK_UNSUPPORTED_DECIMAL(); /// EMERGENCY QUEUE EXECUTION ERRORS + /// --------------------------------------------------------- /// @dev thrown if emergency withdraw is not queued error EMERGENCY_WITHDRAW_NOT_QUEUED(); @@ -435,6 +460,8 @@ library Error { error EMERGENCY_WITHDRAW_PROCESSED_ALREADY(); /// SUPERPOSITION EXECUTION ERRORS + /// --------------------------------------------------------- + /// @dev thrown if uri cannot be updated error DYNAMIC_URI_FROZEN(); diff --git a/src/settings/SuperRBAC.sol b/src/settings/SuperRBAC.sol index 86ae60e80..f1b21b54c 100644 --- a/src/settings/SuperRBAC.sol +++ b/src/settings/SuperRBAC.sol @@ -9,7 +9,7 @@ import { BroadcastMessage } from "src/types/DataTypes.sol"; import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol"; /// @title SuperRBAC -/// @dev Contract to manage roles in the entire superform protocol +/// @dev Contract to manage roles in the Superform protocol /// @author Zeropoint Labs contract SuperRBAC is ISuperRBAC, AccessControlEnumerable { From ed930315c6f6f4f2891d31b8a7287a59cc8d9c94 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Tue, 26 Dec 2023 14:21:23 +0530 Subject: [PATCH 181/210] chore: handle reverting oracle --- src/payments/PaymentHelper.sol | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 52e57698a..55b958d19 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -928,10 +928,15 @@ contract PaymentHelper is IPaymentHelper { function _getGasPrice(uint64 chainId_) internal view returns (uint256) { address oracleAddr = address(gasPriceOracle[chainId_]); if (oracleAddr != address(0)) { - (, int256 value,, uint256 updatedAt,) = AggregatorV3Interface(oracleAddr).latestRoundData(); - if (value <= 0) revert Error.CHAINLINK_MALFUNCTION(); - if (updatedAt == 0) revert Error.CHAINLINK_INCOMPLETE_ROUND(); - return uint256(value); + try AggregatorV3Interface(oracleAddr).latestRoundData() returns ( + uint80, int256 value, uint256, uint256 updatedAt, uint80 + ) { + if (value <= 0) revert Error.CHAINLINK_MALFUNCTION(); + if (updatedAt == 0) revert Error.CHAINLINK_INCOMPLETE_ROUND(); + return uint256(value); + } catch { + /// @dev do nothing and return the default price at the end of the function + } } return gasPrice[chainId_]; @@ -942,10 +947,15 @@ contract PaymentHelper is IPaymentHelper { function _getNativeTokenPrice(uint64 chainId_) internal view returns (uint256) { address oracleAddr = address(nativeFeedOracle[chainId_]); if (oracleAddr != address(0)) { - (, int256 dstTokenPrice,, uint256 updatedAt,) = AggregatorV3Interface(oracleAddr).latestRoundData(); - if (dstTokenPrice <= 0) revert Error.CHAINLINK_MALFUNCTION(); - if (updatedAt == 0) revert Error.CHAINLINK_INCOMPLETE_ROUND(); - return uint256(dstTokenPrice); + try AggregatorV3Interface(oracleAddr).latestRoundData() returns ( + uint80, int256 dstTokenPrice, uint256, uint256 updatedAt, uint80 + ) { + if (dstTokenPrice <= 0) revert Error.CHAINLINK_MALFUNCTION(); + if (updatedAt == 0) revert Error.CHAINLINK_INCOMPLETE_ROUND(); + return uint256(dstTokenPrice); + } catch { + /// @dev do nothing and return the default price at the end of the function + } } return nativePrice[chainId_]; From f58d79c83d88e71984e9da7ef80d8f7e8de55f65 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 26 Dec 2023 10:26:00 +0000 Subject: [PATCH 182/210] chore: remove extra unneeded check in DISABLED on superRegistry --- src/settings/SuperRegistry.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/settings/SuperRegistry.sol b/src/settings/SuperRegistry.sol index b9c5b7c6f..55453cff1 100644 --- a/src/settings/SuperRegistry.sol +++ b/src/settings/SuperRegistry.sol @@ -10,7 +10,6 @@ import { Error } from "src/libraries/Error.sol"; /// @dev Keeps information on all addresses used in the Superform ecosystem /// @author Zeropoint Labs contract SuperRegistry is ISuperRegistry, QuorumManager { - ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// @@ -346,7 +345,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { if (ambAddress == address(0)) revert Error.ZERO_ADDRESS(); if (ambId == 0) revert Error.ZERO_INPUT_VALUE(); - if (ambAddresses[ambId] != address(0) || ambIds[ambAddress] != 0) revert Error.DISABLED(); + if (ambAddresses[ambId] != address(0)) revert Error.DISABLED(); ambAddresses[ambId] = ambAddress; ambIds[ambAddress] = ambId; @@ -372,7 +371,7 @@ contract SuperRegistry is ISuperRegistry, QuorumManager { uint8 registryId = registryId_[i]; if (registryAddress == address(0)) revert Error.ZERO_ADDRESS(); if (registryId == 0) revert Error.ZERO_INPUT_VALUE(); - if (registryAddresses[registryId] != address(0) || stateRegistryIds[registryAddress] != 0) { + if (registryAddresses[registryId] != address(0)) { revert Error.DISABLED(); } From cf04982506a343d28c7ad6eb0abc551f84169088 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 26 Dec 2023 14:34:02 +0000 Subject: [PATCH 183/210] chore: fix comments --- src/SuperPositions.sol | 4 +--- src/crosschain-liquidity/DstSwapper.sol | 10 +++++----- src/crosschain-liquidity/LiquidityHandler.sol | 3 +-- src/forms/ERC4626Form.sol | 3 +-- src/forms/ERC4626KYCDaoForm.sol | 4 +--- src/forms/ERC4626TimelockForm.sol | 3 +-- .../utils/PayloadHelper.multiVault.t.sol | 6 +++--- 7 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/SuperPositions.sol b/src/SuperPositions.sol index c9a5eab94..eb3423e60 100644 --- a/src/SuperPositions.sol +++ b/src/SuperPositions.sol @@ -26,18 +26,16 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol /// @dev Cross-chain LP token minted on source chain /// @author Zeropoint Labs contract SuperPositions is ISuperPositions, ERC1155A { - using DataLib for uint256; ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - ISuperRegistry public immutable superRegistry; uint64 public immutable CHAIN_ID; uint8 internal constant CORE_STATE_REGISTRY_ID = 1; - bytes32 constant DEPLOY_NEW_AERC20 = keccak256("DEPLOY_NEW_AERC20"); + bytes32 internal constant DEPLOY_NEW_AERC20 = keccak256("DEPLOY_NEW_AERC20"); ////////////////////////////////////////////////////////////// // STATE VARIABLES // diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index bd065315f..c79cd5744 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -83,7 +83,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { if (superRegistry_ == address(0)) { revert Error.ZERO_ADDRESS(); } - + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } @@ -167,14 +167,14 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { uint256 payloadId_, uint256[] calldata indices_, uint8[] calldata bridgeIds_, - bytes[] calldata txDatas_ + bytes[] calldata txData_ ) external override nonReentrant onlySwapper { - uint256 len = txDatas_.length; + uint256 len = txData_.length; if (len == 0) revert Error.ZERO_INPUT_VALUE(); if (len != indices_.length && len != bridgeIds_.length) revert Error.ARRAY_LENGTH_MISMATCH(); @@ -198,7 +198,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { } _processTx( - payloadId_, index, bridgeIds_[i], txDatas_[i], data.liqData[index].interimToken, coreStateRegistry + payloadId_, index, bridgeIds_[i], txData_[i], data.liqData[index].interimToken, coreStateRegistry ); } } @@ -375,7 +375,7 @@ contract DstSwapper is IDstSwapper, ReentrancyGuard, LiquidityHandler { v.balanceDiff = v.balanceAfter - v.balanceBefore; /// @dev if actual underlying is less than expAmount adjusted with maxSlippage, invariant breaks - if (v.balanceDiff * ENTIRE_SLIPPAGE < v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) { + if (v.balanceDiff * ENTIRE_SLIPPAGE < v.expAmount * (ENTIRE_SLIPPAGE - v.maxSlippage)) { revert Error.SLIPPAGE_OUT_OF_BOUNDS(); } diff --git a/src/crosschain-liquidity/LiquidityHandler.sol b/src/crosschain-liquidity/LiquidityHandler.sol index 1475c3a07..cb5b8a045 100644 --- a/src/crosschain-liquidity/LiquidityHandler.sol +++ b/src/crosschain-liquidity/LiquidityHandler.sol @@ -10,14 +10,13 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa /// @dev To be inherited by contracts that move liquidity /// @author ZeroPoint Labs abstract contract LiquidityHandler { - using SafeERC20 for IERC20; ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - address immutable NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; ////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS // diff --git a/src/forms/ERC4626Form.sol b/src/forms/ERC4626Form.sol index 7bee1544d..a9c537b2f 100644 --- a/src/forms/ERC4626Form.sol +++ b/src/forms/ERC4626Form.sol @@ -9,12 +9,11 @@ import { InitSingleVaultData } from "src/types/DataTypes.sol"; /// @dev The Form implementation for normal ERC4626 vaults /// @author Zeropoint Labs contract ERC4626Form is ERC4626FormImplementation { - ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - uint8 immutable stateRegistryId = 1; // CoreStateRegistry + uint8 constant stateRegistryId = 1; // CoreStateRegistry ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/forms/ERC4626KYCDaoForm.sol b/src/forms/ERC4626KYCDaoForm.sol index d565f1335..1c60e4850 100644 --- a/src/forms/ERC4626KYCDaoForm.sol +++ b/src/forms/ERC4626KYCDaoForm.sol @@ -10,17 +10,15 @@ import { InitSingleVaultData } from "src/types/DataTypes.sol"; import { kycDAO4626 } from "super-vaults/kycdao-4626/kycdao4626.sol"; import { ERC721Holder } from "openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol"; - /// @title ERC4626KYCDaoForm /// @dev The Form implementation for kycDAO-gated ERC4626 vaults, must hold kycDAO NFT /// @author Zeropoint Labs contract ERC4626KYCDaoForm is ERC4626FormImplementation, ERC721Holder { - ////////////////////////////////////////////////////////////// // CONSTANTS // ////////////////////////////////////////////////////////////// - uint8 immutable stateRegistryId = 1; // CoreStateRegistry + uint8 constant stateRegistryId = 1; // CoreStateRegistry ////////////////////////////////////////////////////////////// // CONSTRUCTOR // diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index e2b716431..97a640145 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -17,7 +17,6 @@ import { IERC4626TimelockVault } from "super-vaults/interfaces/IERC4626TimelockV /// @dev Form implementation to handle timelock extension for ERC4626 vaults /// @author Zeropoint Labs contract ERC4626TimelockForm is ERC4626FormImplementation { - using SafeERC20 for IERC20; using SafeERC20 for IERC4626TimelockVault; using DataLib for uint256; @@ -26,7 +25,7 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { // CONSTANTS // ////////////////////////////////////////////////////////////// - uint8 immutable stateRegistryId = 2; // TimelockStateRegistry + uint8 constant stateRegistryId = 2; // TimelockStateRegistry ////////////////////////////////////////////////////////////// // STRUCTS // diff --git a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol index 604a33bfd..428d178e9 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol @@ -255,7 +255,7 @@ contract PayloadHelperMultiTest is ProtocolActions { struct CheckDstPayloadLiqDataInternalVars { uint8[] bridgeIds; - bytes[] txDatas; + bytes[] txData; address[] tokens; uint64[] liqDstChainIds; uint256[] amounts; @@ -266,13 +266,13 @@ contract PayloadHelperMultiTest is ProtocolActions { vm.selectFork(FORKS[DST_CHAINS[0]]); CheckDstPayloadLiqDataInternalVars memory v; - (v.txDatas, v.tokens,, v.bridgeIds, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( + (v.txData, v.tokens,, v.bridgeIds, v.liqDstChainIds, v.amounts, v.nativeAmounts) = IPayloadHelper( contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))] ).decodeCoreStateRegistryPayloadLiqData(2); assertEq(v.bridgeIds[0], 1); - assertGt(v.txDatas[0].length, 0); + assertGt(v.txData[0].length, 0); assertEq(v.tokens[0], externalToken_); From f599082cdaf835c3ce330fa15c353b063fd7962b Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 26 Dec 2023 16:11:21 +0000 Subject: [PATCH 184/210] chore: re-org folders, add 1155a, fix invariant tests --- lib/ERC1155A | 2 +- .../1/Ethereum-latest.json} | 0 script/ctf_deployment/10/Optimism-latest.json | 0 script/ctf_deployment/137/Polygon-latest.json | 0 .../ctf_deployment/42161/Arbitrum-latest.json | 0 .../43114/Avalanche-latest.json | 0 script/ctf_deployment/56/Binance-latest.json | 0 script/ctf_deployment/8453/Base-latest.json | 0 test/utils/InvariantProtocolActions.sol | 239 +++++++++++------- 9 files changed, 154 insertions(+), 87 deletions(-) rename script/{output/250/Fantom-latest.json => ctf_deployment/1/Ethereum-latest.json} (100%) create mode 100644 script/ctf_deployment/10/Optimism-latest.json create mode 100644 script/ctf_deployment/137/Polygon-latest.json create mode 100644 script/ctf_deployment/42161/Arbitrum-latest.json create mode 100644 script/ctf_deployment/43114/Avalanche-latest.json create mode 100644 script/ctf_deployment/56/Binance-latest.json create mode 100644 script/ctf_deployment/8453/Base-latest.json diff --git a/lib/ERC1155A b/lib/ERC1155A index e7d53f306..f46fa5420 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 +Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 diff --git a/script/output/250/Fantom-latest.json b/script/ctf_deployment/1/Ethereum-latest.json similarity index 100% rename from script/output/250/Fantom-latest.json rename to script/ctf_deployment/1/Ethereum-latest.json diff --git a/script/ctf_deployment/10/Optimism-latest.json b/script/ctf_deployment/10/Optimism-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/ctf_deployment/137/Polygon-latest.json b/script/ctf_deployment/137/Polygon-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/ctf_deployment/42161/Arbitrum-latest.json b/script/ctf_deployment/42161/Arbitrum-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/ctf_deployment/43114/Avalanche-latest.json b/script/ctf_deployment/43114/Avalanche-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/ctf_deployment/56/Binance-latest.json b/script/ctf_deployment/56/Binance-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/script/ctf_deployment/8453/Base-latest.json b/script/ctf_deployment/8453/Base-latest.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index bcbb85fb0..a907cffdb 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -272,7 +272,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vars.toDst[0], vars.underlyingSrcToken[0], vars.underlyingDstToken[0], - address(0), + action.dstSwap ? getContract(vars.DST_CHAINS[i], UNDERLYING_TOKENS[0]) : address(0), vars.targetSuperformIds[0], finalAmount, vars.liqBridges[0], @@ -705,48 +705,21 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { ); if (action.testType == TestType.Pass) { - if (action.dstSwap) { - /// @dev calling state variables again to obtain fresh memory values corresponding to - /// DST - (,, vars.underlyingDstToken,) = _targetVaults( - vars.CHAIN_0, - vars.DST_CHAINS[i], - vars.targetVaults[i], - vars.targetFormKinds[i], - vars.targetUnderlyings[i] - ); - vars.liqBridges = vars.targetLiqBridges[i]; - - /// @dev dst swap is performed to ensure tokens reach CoreStateRegistry on deposits - if (action.multiVaults) { - _batchProcessDstSwap( - vars.liqBridges, - vars.CHAIN_0, - aV[i].toChainId, - vars.underlyingDstToken, - vars.multiVaultsPayloadArg.amounts, - action.slippage - ); - } else { - _processDstSwap( - vars.liqBridges[0], - vars.CHAIN_0, - aV[i].toChainId, - vars.underlyingDstToken[0], - vars.singleVaultsPayloadArg.amount, - action.slippage - ); - } - } - /// @dev this is the step where the amounts are updated taking into account the final /// slippage if (action.multiVaults) { - _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + _updateMultiVaultDepositPayload( + vars.multiVaultsPayloadArg, + vars.underlyingWithBridgeSlippages, + vars.targetUnderlyings[i] + ); } else if (singleSuperformsData.length > 0) { - _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, + vars.underlyingWithBridgeSlippage, + vars.targetUnderlyings[i][0] + ); } - vm.recordLogs(); /// @dev payload processing. This performs the action down to the form level and builds any /// acknowledgement data needed to bring it back to source @@ -761,9 +734,17 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { } else if (action.testType == TestType.RevertProcessPayload) { /// @dev this logic is essentially repeated from above if (action.multiVaults) { - _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + _updateMultiVaultDepositPayload( + vars.multiVaultsPayloadArg, + vars.underlyingWithBridgeSlippages, + vars.targetUnderlyings[i] + ); } else if (singleSuperformsData.length > 0) { - _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, + vars.underlyingWithBridgeSlippage, + vars.targetUnderlyings[i][0] + ); } /// @dev process payload will revert in here success = _processPayload( @@ -778,9 +759,17 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { ) { /// @dev branch used just for reverts of updatePayload (process payload is not even called) if (action.multiVaults) { - success = _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + success = _updateMultiVaultDepositPayload( + vars.multiVaultsPayloadArg, + vars.underlyingWithBridgeSlippages, + vars.targetUnderlyings[i] + ); } else { - success = _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + success = _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, + vars.underlyingWithBridgeSlippage, + vars.targetUnderlyings[i][0] + ); } if (!success) { @@ -874,9 +863,16 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { if (len == 0) revert LEN_MISMATCH(); uint256[] memory finalAmounts = new uint256[](len); uint256[] memory maxSlippageTemp = new uint256[](len); + address uniqueInterimToken; + for (uint256 i = 0; i < len; ++i) { finalAmounts[i] = args.amounts[i]; + if (i < 3 && args.dstSwap && args.action != Actions.Withdraw) { + /// @dev hack to support unique interim tokens -assuming dst swap scenario cases have less than 3 vaults + uniqueInterimToken = getContract(args.toChainId, UNDERLYING_TOKENS[i]); + } + /// @dev FOR TESTING AND MAINNET:: in sameChain actions, slippage is encoded in the request with the amount /// (extracted from bridge api) if ( @@ -899,7 +895,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { args.toDst[i], args.underlyingTokens[i], args.underlyingTokensDst[i], - address(0), + uniqueInterimToken, args.superformIds[i], finalAmounts[i], args.liqBridges[i], @@ -923,6 +919,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { } liqRequests[i] = superformData.liqRequest; + if (args.dstSwap && args.action != Actions.Withdraw) liqRequests[i].interimToken = uniqueInterimToken; maxSlippageTemp[i] = args.maxSlippage; v.totalAmount += finalAmounts[i]; @@ -973,8 +970,13 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { uint256 decimal1; uint256 decimal2; uint256 decimal3; + uint256 decimal4; uint256 amountTemp; uint256 amount; + int256 USDPerUnderlyingOrInterimTokenDst; + int256 USDPerUnderlyingTokenDst; + int256 USDPerExternalToken; + int256 USDPerUnderlyingToken; LiqRequest liqReq; } @@ -991,17 +993,34 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { v.from = args.fromSrc; /// @dev build permit2 calldata vm.selectFork(FORKS[args.toChainId]); - v.decimal2 = args.underlyingTokenDst != NATIVE_TOKEN ? MockERC20(args.underlyingTokenDst).decimals() : 18; + /// @dev decimals of interimToken in case it exists (dstSwaps), otherwise decimals of final token + /// (underlyingToken) + /// @dev hack for when args.dstSwap == true + if (args.uniqueInterimToken != address(0)) { + v.decimal2 = args.uniqueInterimToken != NATIVE_TOKEN ? MockERC20(args.uniqueInterimToken).decimals() : 18; - (, int256 USDPerUnderlyingTokenDst,,,) = - AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.underlyingTokenDst]).latestRoundData(); + (, v.USDPerUnderlyingOrInterimTokenDst,,,) = + AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.uniqueInterimToken]).latestRoundData(); + + v.decimal4 = args.underlyingTokenDst != NATIVE_TOKEN ? MockERC20(args.underlyingTokenDst).decimals() : 18; + + (, v.USDPerUnderlyingTokenDst,,,) = + AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.underlyingTokenDst]).latestRoundData(); + } else { + v.decimal2 = args.underlyingTokenDst != NATIVE_TOKEN ? MockERC20(args.underlyingTokenDst).decimals() : 18; + + (, v.USDPerUnderlyingOrInterimTokenDst,,,) = + AggregatorV3Interface(tokenPriceFeeds[args.toChainId][args.underlyingTokenDst]).latestRoundData(); + } vm.selectFork(FORKS[args.srcChainId]); + /// @dev decimals of externalToken v.decimal1 = args.externalToken != NATIVE_TOKEN ? MockERC20(args.externalToken).decimals() : 18; + /// @dev decimals of underlyingToken on source v.decimal3 = args.underlyingToken != NATIVE_TOKEN ? MockERC20(args.underlyingToken).decimals() : 18; - (, int256 USDPerExternalToken,,,) = + (, v.USDPerExternalToken,,,) = AggregatorV3Interface(tokenPriceFeeds[args.srcChainId][args.externalToken]).latestRoundData(); - (, int256 USDPerUnderlyingToken,,,) = + (, v.USDPerUnderlyingToken,,,) = AggregatorV3Interface(tokenPriceFeeds[args.srcChainId][args.underlyingToken]).latestRoundData(); /// @dev this is to attach v.amount pre dst slippage with the correct decimals to avoid intermediary truncation @@ -1021,7 +1040,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { args.liqBridge, args.externalToken, args.underlyingToken, - args.underlyingTokenDst, + args.uniqueInterimToken != address(0) ? args.uniqueInterimToken : args.underlyingTokenDst, v.from, args.srcChainId, args.toChainId, @@ -1033,9 +1052,9 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { //v.amount, false, args.slippage, - uint256(USDPerExternalToken), - uint256(USDPerUnderlyingTokenDst), - uint256(USDPerUnderlyingToken) + uint256(v.USDPerExternalToken), + uint256(v.USDPerUnderlyingOrInterimTokenDst), + uint256(v.USDPerUnderlyingToken) ); v.txData = _buildLiqBridgeTxData(liqBridgeTxDataArgs, args.srcChainId == args.toChainId); @@ -1084,6 +1103,11 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { } } + /// @dev the next steps are to create the user intent amount that goes in the state request. + /// @dev the values here have to be calculated in terms of decimal differences and slippage in the different + /// stages + /// @dev this calculation would be done automatically by Superform Protocol API on mainnet + /// @dev for e.g. externalToken = DAI, underlyingTokenDst = USDC, daiAmount = 100 /// => usdcAmount = ((USDPerDai / 10e18) / (USDPerUsdc / 10e6)) * daiAmount console.log("test amount pre-swap", args.amount); @@ -1098,36 +1122,51 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { /// @dev decimal1 = decimals of args.externalToken (src chain), decimal2 = decimals of args.underlyingToken /// (src chain) if (decimal1 > decimal2) { - args.amount = (args.amount * uint256(USDPerExternalToken)) - / (uint256(USDPerUnderlyingToken) * 10 ** (decimal1 - decimal2)); + args.amount = (args.amount * uint256(v.USDPerExternalToken)) + / (uint256(v.USDPerUnderlyingToken) * 10 ** (decimal1 - decimal2)); } else { - args.amount = ((args.amount * uint256(USDPerExternalToken)) * 10 ** (decimal2 - decimal1)) - / uint256(USDPerUnderlyingToken); + args.amount = ((args.amount * uint256(v.USDPerExternalToken)) * 10 ** (decimal2 - decimal1)) + / uint256(v.USDPerUnderlyingToken); } console.log("test amount post-swap", args.amount); } + /// @dev applying only bridge slippage here as dstSwap slippage is applied in _updateSingleVaultDepositPayload() + /// and _updateMultiVaultDepositPayload() int256 slippage = args.slippage; if (args.srcChainId == args.toChainId) slippage = 0; + /// @dev REMOVE THIS LINE IF THEORY IS CORRECT (this is full amount) + // else if (args.dstSwap) slippage = (slippage * int256(100 - MULTI_TX_SLIPPAGE_SHARE)) / 100; - /// @dev applying 100% x-chain slippage at once i.e. bridge + dstSwap slippage (as opposed to 2 steps in - /// LiFiMock) coz this code will only be executed once (as opposed to twice in LiFiMock, once for bridge and - /// other for dstSwap) args.amount = (args.amount * uint256(10_000 - slippage)) / 10_000; console.log("test amount pre-bridge, post-slippage", v.amount); /// @dev if args.externalToken == args.underlyingToken, USDPerExternalToken == USDPerUnderlyingToken /// @dev v.decimal3 = decimals of args.underlyingToken (args.externalToken too if above holds true) (src chain), - /// v.decimal2 = decimals of args.underlyingTokenDst (dst chain) + /// v.decimal2 = decimals of args.underlyingTokenDst (dst chain) - interimToken in case of dstSwap if (v.decimal3 > v.decimal2) { - v.amount = (args.amount * uint256(USDPerUnderlyingToken)) - / (uint256(USDPerUnderlyingTokenDst) * 10 ** (v.decimal3 - v.decimal2)); + v.amount = (args.amount * uint256(v.USDPerUnderlyingToken)) + / (uint256(v.USDPerUnderlyingOrInterimTokenDst) * 10 ** (v.decimal3 - v.decimal2)); } else { - v.amount = (args.amount * uint256(USDPerUnderlyingToken) * 10 ** (v.decimal2 - v.decimal3)) - / uint256(USDPerUnderlyingTokenDst); + v.amount = (args.amount * uint256(v.USDPerUnderlyingToken) * 10 ** (v.decimal2 - v.decimal3)) + / uint256(v.USDPerUnderlyingOrInterimTokenDst); } + console.log("test amount post-bridge", v.amount); + /// @dev extra step to convert interim token on dst to underlying token on dst (if there is a dst Swap) + if (args.uniqueInterimToken != address(0)) { + if (v.decimal2 > v.decimal4) { + v.amount = (v.amount * uint256(v.USDPerUnderlyingOrInterimTokenDst)) + / (uint256(v.USDPerUnderlyingTokenDst) * 10 ** (v.decimal2 - v.decimal4)); + } else { + v.amount = (v.amount * uint256(v.USDPerUnderlyingOrInterimTokenDst) * 10 ** (v.decimal4 - v.decimal2)) + / uint256(v.USDPerUnderlyingTokenDst); + } + } + + console.log("test amount post-dst swap --", v.amount); + vm.selectFork(v.initialFork); /// @dev extraData is unused here so false is encoded (it is currently used to send in the partialWithdraw @@ -1347,7 +1386,14 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { return superformIds_; } - function _updateMultiVaultDepositPayload(updateMultiVaultDepositPayloadArgs memory args) internal returns (bool) { + function _updateMultiVaultDepositPayload( + updateMultiVaultDepositPayloadArgs memory args, + uint256[] memory finalAmountsThatReachedCSR, + uint256[] memory targetUnderlyings + ) + internal + returns (bool) + { uint256 initialFork = vm.activeFork(); vm.selectFork(FORKS[args.targetChainId]); @@ -1357,16 +1403,21 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { int256 dstSwapSlippage; - /// @dev slippage calculation + for (uint256 i; i < len; ++i) { + bridgedTokens[i] = getContract(args.targetChainId, UNDERLYING_TOKENS[targetUnderlyings[i]]); + } + for (uint256 i = 0; i < len; ++i) { finalAmounts[i] = args.amounts[i]; if (args.slippage > 0) { - /// @dev bridge slippage is already applied in _buildSingleVaultDepositCallData() - //finalAmounts[i] = (finalAmounts[i] * uint256(10_000 - args.slippage)) / 10_000; - + /// @dev finalAmounts[i] has full slippage applied (final user expectedAmount) + uint256 amountPostDstSwap; if (args.isdstSwap) { dstSwapSlippage = (args.slippage * int256(MULTI_TX_SLIPPAGE_SHARE)) / 100; - finalAmounts[i] = (finalAmounts[i] * uint256(10_000 - dstSwapSlippage)) / 10_000; + amountPostDstSwap = (finalAmountsThatReachedCSR[i] * uint256(10_000 - dstSwapSlippage)) / 10_000; + if (amountPostDstSwap < finalAmounts[i]) { + finalAmounts[i] = amountPostDstSwap; + } } } } @@ -1407,7 +1458,11 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { return true; } - function _updateSingleVaultDepositPayload(updateSingleVaultDepositPayloadArgs memory args) + function _updateSingleVaultDepositPayload( + updateSingleVaultDepositPayloadArgs memory args, + uint256 finalAmountsThatReachedCSR, + uint256 targetUnderlying + ) internal returns (bool) { @@ -1415,17 +1470,20 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.selectFork(FORKS[args.targetChainId]); uint256 finalAmount; - address bridgedToken; + address bridgedToken = getContract(args.targetChainId, UNDERLYING_TOKENS[targetUnderlying]); finalAmount = args.amount; int256 dstSwapSlippage; - finalAmount = (finalAmount * uint256(10_000 - args.slippage)) / 10_000; - if (args.isdstSwap) { dstSwapSlippage = (args.slippage * int256(MULTI_TX_SLIPPAGE_SHARE)) / 100; - finalAmount = (finalAmount * uint256(10_000 - dstSwapSlippage)) / 10_000; + uint256 amountPostDstSwap; + + amountPostDstSwap = (finalAmountsThatReachedCSR * uint256(10_000 - dstSwapSlippage)) / 10_000; + if (amountPostDstSwap < finalAmount) { + finalAmount = amountPostDstSwap; + } } /// @dev if test type is RevertProcessPayload, revert is further down the call chain @@ -1567,27 +1625,31 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { uint64, /*srcChainId_*/ uint64 targetChainId_, address underlyingTokenDst_, - uint256 amount_, - int256 slippage_ + int256 slippage_, + uint256 underlyingWithBridgeSlippage_ ) internal { uint256 initialFork = vm.activeFork(); vm.selectFork(FORKS[targetChainId_]); + /// @dev replace socket bridge with socket one inch impl for dst swap + if (liqBridgeKind_ == 2) { + liqBridgeKind_ = 3; + } + /// @dev liqData is rebuilt here to perform to send the tokens from dstSwapProcessor to CoreStateRegistry bytes memory txData = _buildLiqBridgeTxDataDstSwap( liqBridgeKind_, - underlyingTokenDst_, + getContract(targetChainId_, UNDERLYING_TOKENS[0]), underlyingTokenDst_, getContract(targetChainId_, "DstSwapper"), targetChainId_, - amount_, + underlyingWithBridgeSlippage_, slippage_ ); vm.prank(deployer); - DstSwapper(payable(getContract(targetChainId_, "DstSwapper"))).processTx(1, liqBridgeKind_, txData); vm.selectFork(initialFork); } @@ -1597,8 +1659,8 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { uint64, /*srcChainId_*/ uint64 targetChainId_, address[] memory underlyingTokensDst_, - uint256[] memory amounts_, - int256 slippage_ + int256 slippage_, + uint256[] memory underlyingWithBridgeSlippages_ ) internal { @@ -1606,24 +1668,29 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.selectFork(FORKS[targetChainId_]); bytes[] memory txDatas = new bytes[](underlyingTokensDst_.length); + /// @dev replace socket bridge with socket one inch impl for dst swap + for (uint256 i; i < liqBridgeKinds_.length; ++i) { + if (liqBridgeKinds_[i] == 2) liqBridgeKinds_[i] = 3; + } + /// @dev liqData is rebuilt here to perform to send the tokens from dstSwapProcessor to CoreStateRegistry for (uint256 i = 0; i < underlyingTokensDst_.length; ++i) { txDatas[i] = _buildLiqBridgeTxDataDstSwap( liqBridgeKinds_[i], - underlyingTokensDst_[i], + getContract(targetChainId_, UNDERLYING_TOKENS[i]), underlyingTokensDst_[i], getContract(targetChainId_, "DstSwapper"), targetChainId_, - amounts_[i], + underlyingWithBridgeSlippages_[i], slippage_ ); } vm.prank(deployer); - uint256[] memory indices = new uint256[](amounts_.length); + uint256[] memory indices = new uint256[](underlyingWithBridgeSlippages_.length); - for (uint256 i; i < amounts_.length; ++i) { + for (uint256 i; i < underlyingWithBridgeSlippages_.length; ++i) { indices[i] = i; } From f1a55e89883d91350cdcfe6096f77a19be11a3f2 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 10:25:41 -0600 Subject: [PATCH 185/210] chore: adding output amount --- src/BaseRouterImplementation.sol | 54 ++++++++++++------- .../extensions/CoreStateRegistry.sol | 13 +++-- src/forms/ERC4626FormImplementation.sol | 6 +-- src/forms/ERC4626TimelockForm.sol | 3 +- src/libraries/ArrayCastLib.sol | 4 ++ src/payments/PaymentHelper.sol | 2 + src/types/DataTypes.sol | 7 ++- test/unit/libraries/ArrayCastLib.t.sol | 2 +- 8 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 43f4194bc..c41dfb756 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -109,8 +109,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if ( !_validateSuperformData( req_.superformData.superformId, - req_.superformData.maxSlippage, req_.superformData.amount, + req_.superformData.outputAmount, + req_.superformData.maxSlippage, req_.superformData.receiverAddress, req_.superformData.receiverAddressSP, CHAIN_ID, @@ -126,6 +127,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou 0, req_.superformData.superformId, req_.superformData.amount, + req_.superformData.outputAmount, req_.superformData.maxSlippage, req_.superformData.liqRequest, false, @@ -152,8 +154,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if ( !_validateSuperformData( req_.superformData.superformId, - req_.superformData.maxSlippage, req_.superformData.amount, + req_.superformData.outputAmount, + req_.superformData.maxSlippage, req_.superformData.receiverAddress, req_.superformData.receiverAddressSP, req_.dstChainId, @@ -171,6 +174,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.currentPayloadId, req_.superformData.superformId, req_.superformData.amount, + req_.superformData.outputAmount, req_.superformData.maxSlippage, req_.superformData.liqRequest, req_.superformData.hasDstSwap, @@ -235,6 +239,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou 0, req_.superformData.superformIds, req_.superformData.amounts, + req_.superformData.outputAmounts, req_.superformData.maxSlippages, req_.superformData.liqRequests, new bool[](req_.superformData.amounts.length), @@ -270,6 +275,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.currentPayloadId, req_.superformsData.superformIds, req_.superformsData.amounts, + req_.superformsData.outputAmounts, req_.superformsData.maxSlippages, req_.superformsData.liqRequests, req_.superformsData.hasDstSwaps, @@ -331,8 +337,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if ( !_validateSuperformData( req_.superformData.superformId, - req_.superformData.maxSlippage, req_.superformData.amount, + req_.superformData.outputAmount, + req_.superformData.maxSlippage, req_.superformData.receiverAddress, req_.superformData.receiverAddressSP, CHAIN_ID, @@ -352,6 +359,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou 0, req_.superformData.superformId, req_.superformData.amount, + req_.superformData.outputAmount, req_.superformData.maxSlippage, req_.superformData.liqRequest, false, @@ -379,8 +387,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if ( !_validateSuperformData( req_.superformData.superformId, - req_.superformData.maxSlippage, req_.superformData.amount, + req_.superformData.outputAmount, + req_.superformData.maxSlippage, req_.superformData.receiverAddress, req_.superformData.receiverAddressSP, req_.dstChainId, @@ -402,6 +411,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.currentPayloadId, req_.superformData.superformId, req_.superformData.amount, + req_.superformData.outputAmount, req_.superformData.maxSlippage, req_.superformData.liqRequest, false, @@ -453,6 +463,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou 0, req_.superformData.superformIds, req_.superformData.amounts, + req_.superformData.outputAmounts, req_.superformData.maxSlippages, req_.superformData.liqRequests, new bool[](req_.superformData.superformIds.length), @@ -490,6 +501,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vars.currentPayloadId, req_.superformsData.superformIds, req_.superformsData.amounts, + req_.superformsData.outputAmounts, req_.superformsData.maxSlippages, req_.superformsData.liqRequests, new bool[](req_.superformsData.amounts.length), @@ -586,6 +598,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou uint256 payloadId_, uint256 superformId_, uint256 amount_, + uint256 outputAmount_, uint256 maxSlippage_, bool retain4626_, LiqRequest memory liqData_, @@ -604,6 +617,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou payloadId_, superformId_, amount_, + outputAmount_, maxSlippage_, liqData_, false, @@ -640,6 +654,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vaultData_.payloadId, vaultData_.superformId, vaultData_.amount, + vaultData_.outputAmount, vaultData_.maxSlippage, vaultData_.retain4626, vaultData_.liqData, @@ -678,6 +693,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou args_.vaultData.payloadId, args_.vaultData.superformIds[i], args_.vaultData.amounts[i], + args_.vaultData.outputAmounts[i], args_.vaultData.maxSlippages[i], args_.vaultData.retain4626s[i], args_.vaultData.liqData[i], @@ -710,6 +726,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou uint256 payloadId_, uint256 superformId_, uint256 amount_, + uint256 outputAmount_, uint256 maxSlippage_, LiqRequest memory liqData_, bool retain4626_, @@ -726,6 +743,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou payloadId_, superformId_, amount_, + outputAmount_, maxSlippage_, liqData_, false, @@ -748,6 +766,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vaultData_.payloadId, vaultData_.superformId, vaultData_.amount, + vaultData_.outputAmount, vaultData_.maxSlippage, vaultData_.liqData, vaultData_.retain4626, @@ -771,6 +790,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou vaultData_.payloadId, vaultData_.superformIds[i], vaultData_.amounts[i], + vaultData_.outputAmounts[i], vaultData_.maxSlippages[i], vaultData_.liqData[i], vaultData_.retain4626s[i], @@ -800,8 +820,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou function _validateSuperformData( uint256 superformId_, - uint256 maxSlippage_, uint256 amount_, + uint256 outputAmount_, + uint256 maxSlippage_, address receiverAddress_, address receiverAddressSP_, uint64 dstChainId_, @@ -827,8 +848,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev 10000 = 100% slippage if (maxSlippage_ > 10_000) return false; - /// @dev amount can't be 0 - if (amount_ == 0) return false; + /// @dev amounts can't be 0 + if (amount_ == 0 || outputAmount_ == 0) return false; /// @dev only validate this for non multi case (multi case is validated in _validateSuperformsData) /// @dev ensure that receiver address is set always @@ -877,19 +898,15 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (len == 0 || liqRequestsLen == 0) return false; if (len != liqRequestsLen) return false; - /// @dev deposits beyond multi vault limit for a given destination chain blocked - if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { - return false; - } - - /// @dev Additional length checks for hasDstSwaps and retain4626s - if (lenSuperforms != superformsData_.hasDstSwaps.length || lenSuperforms != superformsData_.retain4626s.length) - { + /// @dev all other length checks + if (lenSuperforms != len || lenSuperforms != superformsData_.outputAmounts.length || + lenSuperforms != superformsData_.maxSlippages.length ||lenSuperforms != superformsData_.hasDstSwaps.length || + lenSuperforms != superformsData_.retain4626s.length) { return false; } - /// @dev superformIds/amounts/slippages array sizes validation - if (!(lenSuperforms == len && lenSuperforms == superformsData_.maxSlippages.length)) { + /// @dev deposits beyond multi vault limit for a given destination chain blocked + if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { return false; } @@ -915,8 +932,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou for (uint256 i; i < len; ++i) { valid = _validateSuperformData( superformsData_.superformIds[i], - superformsData_.maxSlippages[i], superformsData_.amounts[i], + superformsData_.outputAmounts[i], + superformsData_.maxSlippages[i], superformsData_.receiverAddress, superformsData_.receiverAddressSP, dstChainId_, diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index d22a8b4a2..32015e9f8 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -448,28 +448,31 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { if (validLen != 0) { uint256[] memory finalSuperformIds = new uint256[](validLen); uint256[] memory finalAmounts = new uint256[](validLen); + uint256[] memory outputAmounts = new uint256[](validLen); uint256[] memory maxSlippage = new uint256[](validLen); bool[] memory hasDstSwaps = new bool[](validLen); - bool[] memory finalRetain4626s = new bool[](validLen); + bool[] memory retain4626s = new bool[](validLen); uint256 currLen; for (uint256 i; i < arrLen; ++i) { if (multiVaultData.amounts[i] != 0) { finalSuperformIds[currLen] = multiVaultData.superformIds[i]; finalAmounts[currLen] = multiVaultData.amounts[i]; + outputAmounts[currLen] = multiVaultData.outputAmounts[i]; maxSlippage[currLen] = multiVaultData.maxSlippages[i]; hasDstSwaps[currLen] = multiVaultData.hasDstSwaps[i]; - finalRetain4626s[currLen] = multiVaultData.retain4626s[i]; + retain4626s[currLen] = multiVaultData.retain4626s[i]; ++currLen; } } - multiVaultData.amounts = finalAmounts; multiVaultData.superformIds = finalSuperformIds; + multiVaultData.amounts = finalAmounts; + multiVaultData.outputAmounts = outputAmounts; multiVaultData.maxSlippages = maxSlippage; multiVaultData.hasDstSwaps = hasDstSwaps; - multiVaultData.retain4626s = finalRetain4626s; + multiVaultData.retain4626s = retain4626s; finalState_ = PayloadState.UPDATED; } else { finalState_ = PayloadState.PROCESSED; @@ -722,6 +725,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { payloadId: multiVaultData.payloadId, superformId: multiVaultData.superformIds[i], amount: multiVaultData.amounts[i], + outputAmount: multiVaultData.outputAmounts[i], maxSlippage: multiVaultData.maxSlippages[i], liqData: multiVaultData.liqData[i], hasDstSwap: false, @@ -790,6 +794,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { payloadId: multiVaultData.payloadId, superformId: multiVaultData.superformIds[i], amount: multiVaultData.amounts[i], + outputAmount: multiVaultData.outputAmounts[i], maxSlippage: multiVaultData.maxSlippages[i], liqData: emptyRequest, hasDstSwap: false, diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 0cb31372e..0ca3cc913 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -408,12 +408,11 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { { address sharesReceiver = singleVaultData_.retain4626 ? singleVaultData_.receiverAddress : address(this); uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); - uint256 sharesExpected = v.convertToShares(assetDifference); shares = v.deposit(assetDifference, sharesReceiver); uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); if ((sharesBalanceAfter - sharesBalanceBefore != shares) || - (shares < ((sharesExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + (shares < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -429,12 +428,11 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { { address assetsReceiver = singleVaultData_.liqData.txData.length == 0 ? singleVaultData_.receiverAddress : address(this); uint256 assetsBalanceBefore = a.balanceOf(assetsReceiver); - uint256 assetsExpected = v.convertToAssets(singleVaultData_.amount); assets = v.redeem(singleVaultData_.amount, assetsReceiver, address(this)); uint256 assetsBalanceAfter = a.balanceOf(assetsReceiver); if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + (assets < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index 287ce82de..a42e21037 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -100,11 +100,10 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { IERC20 assetERC = IERC20(vars.asset); uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); - uint256 assetsExpected = v.convertToAssets(p_.data.amount); assets = v.redeem(p_.data.amount, vars.receiver, address(this)); uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (assets < ((assetsExpected * (ENTIRE_SLIPPAGE - p_.data.maxSlippage)) / ENTIRE_SLIPPAGE)) + (assets < ((p_.data.outputAmount * (ENTIRE_SLIPPAGE - p_.data.maxSlippage)) / ENTIRE_SLIPPAGE)) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } diff --git a/src/libraries/ArrayCastLib.sol b/src/libraries/ArrayCastLib.sol index e22427d83..fa44e7ae0 100644 --- a/src/libraries/ArrayCastLib.sol +++ b/src/libraries/ArrayCastLib.sol @@ -29,6 +29,9 @@ library ArrayCastLib { uint256[] memory amounts = new uint256[](1); amounts[0] = data_.amount; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = data_.outputAmount; + uint256[] memory maxSlippage = new uint256[](1); maxSlippage[0] = data_.maxSlippage; @@ -39,6 +42,7 @@ library ArrayCastLib { data_.payloadId, superformIds, amounts, + outputAmounts, maxSlippage, liqData, castBoolToArray(data_.hasDstSwap), diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 18350c13e..021654551 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -822,6 +822,7 @@ contract PaymentHelper is IPaymentHelper { _getNextPayloadId(), sfData_.superformId, sfData_.amount, + sfData_.outputAmount, sfData_.maxSlippage, sfData_.liqRequest, sfData_.hasDstSwap, @@ -844,6 +845,7 @@ contract PaymentHelper is IPaymentHelper { _getNextPayloadId(), sfData_.superformIds, sfData_.amounts, + sfData_.outputAmounts, sfData_.maxSlippages, sfData_.liqRequests, sfData_.hasDstSwaps, diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index 583a2522f..265b4d415 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -46,7 +46,8 @@ struct LiqRequest { struct MultiVaultSFData { // superformids must have same destination. Can have different underlyings uint256[] superformIds; - uint256[] amounts; + uint256[] amounts; // on deposits, amount of token to deposit on dst, on withdrawals, superpositions to burn + uint256[] outputAmounts; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive uint256[] maxSlippages; LiqRequest[] liqRequests; // if length = 1; amount = sum(amounts) | else amounts must match the amounts being sent bytes permit2data; @@ -64,6 +65,7 @@ struct SingleVaultSFData { // superformids must have same destination. Can have different underlyings uint256 superformId; uint256 amount; + uint256 outputAmount; uint256 maxSlippage; LiqRequest liqRequest; // if length = 1; amount = sum(amounts)| else amounts must match the amounts being sent bytes permit2data; @@ -115,10 +117,12 @@ struct SingleDirectMultiVaultStateReq { } /// @dev struct for SuperRouter with re-arranged data for the message (contains the payloadId) +/// @dev realize that receiverAddressSP is not passed, only needed on source chain to mint struct InitMultiVaultData { uint256 payloadId; uint256[] superformIds; uint256[] amounts; + uint256[] outputAmounts; uint256[] maxSlippages; LiqRequest[] liqData; bool[] hasDstSwaps; @@ -132,6 +136,7 @@ struct InitSingleVaultData { uint256 payloadId; uint256 superformId; uint256 amount; + uint256 outputAmount; uint256 maxSlippage; LiqRequest liqData; bool hasDstSwap; diff --git a/test/unit/libraries/ArrayCastLib.t.sol b/test/unit/libraries/ArrayCastLib.t.sol index 56e5a5635..08d21e299 100644 --- a/test/unit/libraries/ArrayCastLib.t.sol +++ b/test/unit/libraries/ArrayCastLib.t.sol @@ -46,7 +46,7 @@ contract ArrayCastLibTest is Test { function test_castToMultiVaultData() external { InitSingleVaultData memory data = InitSingleVaultData( - 1, 1, 1e18, 100, LiqRequest(bytes(""), address(0), address(0), 1, 1, 0), true, true, address(0), "" + 1, 1, 1e18, 1e18, 100, LiqRequest(bytes(""), address(0), address(0), 1, 1, 0), true, true, address(0), "" ); InitMultiVaultData memory castedValue = arrayCastLib.castToMultiVaultData(data); assertEq(castedValue.superformIds.length, 1); From 4bf9eac58659bdd2fe5beb8618e7e5ebfc3af689 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 11:23:15 -0600 Subject: [PATCH 186/210] chore: fix tests --- .../extensions/CoreStateRegistry.t.sol | 6 + .../TwoStepsFormStateRegistry.t.sol | 2 + .../crosschain-liquidity/DstSwapper.t.sol | 25 +- test/unit/emergency/EmergencyQueue.t.sol | 22 +- test/unit/payments/PayMaster.t.sol | 1 + test/unit/payments/PaymentHelper.t.sol | 13 + .../superform-form.ERC4626Form.t.sol | 19 ++ .../superform-form.ERC4626KYCDao.t.sol | 2 + .../superform-form.ERC4626Timelock.t.sol | 5 + .../superform-form.forwardDust.t.sol | 2 + .../superform-router/SuperformRouter.AA.t.sol | 4 + .../superform-router/SuperformRouter.t.sol | 310 +++++++++++++++++- test/utils/InvariantProtocolActions.sol | 6 + test/utils/ProtocolActions.sol | 9 + test/utils/TestTypes.sol | 3 + 15 files changed, 420 insertions(+), 9 deletions(-) diff --git a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol index 9b0a98bf1..5ba26446e 100644 --- a/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/CoreStateRegistry.t.sol @@ -146,6 +146,7 @@ contract CoreStateRegistryTest is ProtocolActions { superformIds, uint256MemArr, uint256MemArr, + uint256MemArr, liqReqArr, bytes(""), new bool[](4), @@ -618,6 +619,7 @@ contract CoreStateRegistryTest is ProtocolActions { superformId, /// @dev 1e18 after decimal corrections and bridge slippage would give the following value 999_900_000_000_000_000, + 999_900_000_000_000_000, 100, LiqRequest( _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), getContract(ETH, "DAI"), address(0), 1, AVAX, 0 @@ -684,6 +686,7 @@ contract CoreStateRegistryTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ETH, 0), bytes(""), @@ -770,6 +773,7 @@ contract CoreStateRegistryTest is ProtocolActions { superformIds, uint256MemArr, uint256MemArr, + uint256MemArr, liqReqArr, bytes(""), new bool[](2), @@ -830,6 +834,7 @@ contract CoreStateRegistryTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amountArr, + amountArr, maxSlippages, liqReqArr, bytes(""), @@ -915,6 +920,7 @@ contract CoreStateRegistryTest is ProtocolActions { superformIds, uint256MemArr, uint256MemArr, + uint256MemArr, liqReqArr, bytes(""), new bool[](2), diff --git a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol index 404352843..79070a402 100644 --- a/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol +++ b/test/unit/crosschain-data/extensions/TwoStepsFormStateRegistry.t.sol @@ -60,6 +60,7 @@ contract TimelockStateRegistryTest is ProtocolActions { 1, superformId, 420, + 420, 0, LiqRequest( _buildLiqBridgeTxData(liqBridgeTxDataArgs, true), getContract(ETH, "DAI"), address(0), 1, ETH, 0 @@ -93,6 +94,7 @@ contract TimelockStateRegistryTest is ProtocolActions { 1, superformId, 420, + 420, 1000, /// @dev note txData (2nd arg) is empty and token (3rd arg) is not address(0) to /// indicate keeper to create and update txData using finalizePayload() diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index a28fa95f3..46211d194 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -112,6 +112,10 @@ contract DstSwapperTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + uint256[] memory slippages = new uint256[](2); slippages[0] = 1000; slippages[1] = 1000; @@ -138,6 +142,7 @@ contract DstSwapperTest is ProtocolActions { 1, superformIds, amounts, + outputAmounts, new uint256[](2), liqs, hasDstSwaps, @@ -645,6 +650,7 @@ contract DstSwapperTest is ProtocolActions { 1, superformId, 1_798_823_082_965_464_723_525, + 1_798_823_082_965_464_723_525, 0, liq, true, @@ -729,7 +735,7 @@ contract DstSwapperTest is ProtocolActions { abi.encode( new uint8[](0), abi.encode( - InitSingleVaultData(1, superformId, amount, 0, liq, true, false, receiverAddress, bytes("")) + InitSingleVaultData(1, superformId, amount, amount, 0, liq, true, false, receiverAddress, bytes("")) ) ) ) @@ -766,7 +772,7 @@ contract DstSwapperTest is ProtocolActions { ), abi.encode( new uint8[](0), - abi.encode(InitSingleVaultData(1, superformId, 1e18, 1000, liq, true, false, users[0], bytes(""))) + abi.encode(InitSingleVaultData(1, superformId, 1e18, 1e18, 1000, liq, true, false, users[0], bytes(""))) ) ) ); @@ -799,6 +805,10 @@ contract DstSwapperTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + bool[] memory hasDstSwaps = new bool[](2); hasDstSwaps[0] = true; hasDstSwaps[1] = true; @@ -824,6 +834,7 @@ contract DstSwapperTest is ProtocolActions { 1, superformIds, amounts, + outputAmounts, maxSlippages, liq, hasDstSwaps, @@ -862,6 +873,10 @@ contract DstSwapperTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + bool[] memory hasDstSwaps = new bool[](2); hasDstSwaps[0] = false; hasDstSwaps[1] = true; @@ -887,6 +902,7 @@ contract DstSwapperTest is ProtocolActions { 1, superformIds, amounts, + outputAmounts, maxSlippages, liq, hasDstSwaps, @@ -920,6 +936,10 @@ contract DstSwapperTest is ProtocolActions { amounts[0] = amount; amounts[1] = amount; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = amount; + outputAmounts[1] = amount; + bool[] memory hasDstSwaps = new bool[](2); hasDstSwaps[0] = true; hasDstSwaps[1] = true; @@ -944,6 +964,7 @@ contract DstSwapperTest is ProtocolActions { 1, superformIds, amounts, + outputAmounts, new uint256[](2), liq, hasDstSwaps, diff --git a/test/unit/emergency/EmergencyQueue.t.sol b/test/unit/emergency/EmergencyQueue.t.sol index 32aa54da6..3ad1b7974 100644 --- a/test/unit/emergency/EmergencyQueue.t.sol +++ b/test/unit/emergency/EmergencyQueue.t.sol @@ -55,7 +55,8 @@ contract EmergencyQueueTest is ProtocolActions { InitSingleVaultData( 1, _getTestSuperformId(), - 1e18, // good hacker tries to take only 1e18 + 1e18, // good hacker tries to take only 1e18, + 1e18, 1000, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), false, @@ -85,7 +86,8 @@ contract EmergencyQueueTest is ProtocolActions { InitSingleVaultData( 1, superformId, - 1e18, // good hacker tries to take only 1e18 + 1e18, // good hacker tries to take only 1e18, + 1e18, 1000, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), false, @@ -116,6 +118,7 @@ contract EmergencyQueueTest is ProtocolActions { 1, superformId, 1e18, // good hacker tries to take only 1e18 + 1e18, 1000, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), false, @@ -483,6 +486,7 @@ contract EmergencyQueueTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( _getTestSuperformId(), 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -517,6 +521,10 @@ contract EmergencyQueueTest is ProtocolActions { amounts[0] = 0.9e18; amounts[1] = 0.9e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 0.9e18; + outputAmounts[1] = 0.9e18; + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 100; maxSlippages[1] = 100; @@ -528,6 +536,7 @@ contract EmergencyQueueTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqRequests, "", @@ -564,6 +573,7 @@ contract EmergencyQueueTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 1000, LiqRequest("", address(0), address(0), 1, ETH, 0), "", @@ -640,6 +650,10 @@ contract EmergencyQueueTest is ProtocolActions { amounts[0] = 0.9e18; amounts[1] = 0.9e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 0.9e18; + outputAmounts[1] = 0.9e18; + uint256[] memory slippages = new uint256[](2); slippages[0] = 100; slippages[1] = 100; @@ -651,6 +665,7 @@ contract EmergencyQueueTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, slippages, liqRequests, "", @@ -740,7 +755,7 @@ contract EmergencyQueueTest is ProtocolActions { uint256 superformId = _getTestSuperformId(); SingleVaultSFData memory data = SingleVaultSFData( - superformId, 2e18, 100, LiqRequest("", dai, address(0), 1, 1, 0), "", false, false, mrperfect, mrperfect, "" + superformId, 2e18, 2e18, 100, LiqRequest("", dai, address(0), 1, 1, 0), "", false, false, mrperfect, mrperfect, "" ); SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); @@ -796,6 +811,7 @@ contract EmergencyQueueTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 2e18, + 2e18, 1000, LiqRequest( _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), getContract(ETH, "DAI"), address(0), 1, ARBI, 0 diff --git a/test/unit/payments/PayMaster.t.sol b/test/unit/payments/PayMaster.t.sol index f305cb726..ddcc92137 100644 --- a/test/unit/payments/PayMaster.t.sol +++ b/test/unit/payments/PayMaster.t.sol @@ -346,6 +346,7 @@ contract PayMasterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ETH, 0), bytes(""), diff --git a/test/unit/payments/PaymentHelper.t.sol b/test/unit/payments/PaymentHelper.t.sol index 5dfb681dc..d8f2e0dc1 100644 --- a/test/unit/payments/PaymentHelper.t.sol +++ b/test/unit/payments/PaymentHelper.t.sol @@ -48,6 +48,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(emptyBytes, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -84,6 +85,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(emptyBytes, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -110,6 +112,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(emptyBytes, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -131,6 +134,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(emptyBytes, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -152,6 +156,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(emptyBytes, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -187,6 +192,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock uint256MemoryArray, uint256MemoryArray, + uint256MemoryArray, liqRequestMemoryArray, emptyBytes, new bool[](1), @@ -208,6 +214,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock uint256MemoryArray, uint256MemoryArray, + uint256MemoryArray, liqRequestMemoryArray, emptyBytes, new bool[](1), @@ -260,6 +267,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(txData, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -310,6 +318,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(txData, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -350,6 +359,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(txData, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -423,6 +433,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(txData, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -482,6 +493,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(txData, address(0), address(0), 1, ETH, 420), emptyBytes, false, @@ -532,6 +544,7 @@ contract PaymentHelperTest is ProtocolActions { /// timelock 420, 420, + 420, LiqRequest(txData, address(0), address(0), 1, ETH, 420), emptyBytes, false, diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index ce588071e..57021e6c7 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -371,6 +371,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -410,6 +411,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 2e18, + 2e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -467,6 +469,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 2e18, + 2e18, 100, LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -507,6 +510,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(receiverAddress, superformId), + SuperPositions(getContract(ETH, "SuperPositions")).balanceOf(receiverAddress, superformId), 100, LiqRequest(_buildMaliciousTxData(1, DAI, superform, ETH, 2e18, receiverAddress), DAI, address(0), 1, ETH, 0), "", @@ -552,6 +556,7 @@ contract SuperformERC4626FormTest is ProtocolActions { 1, superformId, 1e18, + 1e18, 100, LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, @@ -587,6 +592,7 @@ contract SuperformERC4626FormTest is ProtocolActions { 1, 1, 1e18, + 1e18, 100, LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, @@ -623,6 +629,7 @@ contract SuperformERC4626FormTest is ProtocolActions { 1, superformId, amount, + amount, 100, LiqRequest( _buildMaliciousTxData(1, getContract(ETH, "DAI"), superform, ARBI, 2e18, receiverAddress), @@ -690,6 +697,9 @@ contract SuperformERC4626FormTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 1000; @@ -700,6 +710,7 @@ contract SuperformERC4626FormTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", @@ -738,6 +749,9 @@ contract SuperformERC4626FormTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 1000; @@ -759,6 +773,7 @@ contract SuperformERC4626FormTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", @@ -793,6 +808,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -820,6 +836,7 @@ contract SuperformERC4626FormTest is ProtocolActions { data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest( _buildDummyTxDataUnitTests( @@ -890,6 +907,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, daiAmount, + daiAmount, 100, LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -934,6 +952,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", diff --git a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol index 1e8b539b8..f7514d1b1 100644 --- a/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626KYCDao.t.sol @@ -28,6 +28,7 @@ contract SuperformERC4626KYCDaoFormTest is BaseSetup { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -68,6 +69,7 @@ contract SuperformERC4626KYCDaoFormTest is BaseSetup { 1, superformId, 1e18, + 1e18, 100, LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, diff --git a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol index eafd794a6..46be92f86 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol @@ -40,6 +40,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { 1, superformId, 1e18, + 1e18, 100, LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ARBI, 0), false, @@ -81,6 +82,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { 1, superformId, 1e18, + 1e18, 100, LiqRequest(invalidNonEmptyTxData, address(0), address(0), 1, ETH, 0), false, @@ -120,6 +122,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { 1, superformId, 1e18, + 1e18, 100, LiqRequest("", address(0), address(0), 1, ETH, 0), false, @@ -178,6 +181,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { 1, superformId, 1e18, + 1e18, 100, LiqRequest( _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), getContract(ETH, "DAI"), address(0), 1, ETH, 0 @@ -216,6 +220,7 @@ contract SuperformERC4626TimelockFormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest(bytes(""), getContract(ETH, "DAI"), address(0), 1, ETH, 0), bytes(""), diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index da92a5d79..5fcfe66cd 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -97,6 +97,7 @@ contract ForwardDustFormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, amountToDeposit_, + amountToDeposit_, 100, LiqRequest("", getContract(ARBI, "WETH"), address(0), 1, ARBI, 0), "", @@ -126,6 +127,7 @@ contract ForwardDustFormTest is ProtocolActions { 1, superformId, spAmountToRedeem_ == 0 ? superPositionBalance : spAmountToRedeem_, + spAmountToRedeem_ == 0 ? superPositionBalance : spAmountToRedeem_, 100, LiqRequest( _buildDummyTxDataUnitTests( diff --git a/test/unit/superform-router/SuperformRouter.AA.t.sol b/test/unit/superform-router/SuperformRouter.AA.t.sol index 9bcebcc9b..454c039a7 100644 --- a/test/unit/superform-router/SuperformRouter.AA.t.sol +++ b/test/unit/superform-router/SuperformRouter.AA.t.sol @@ -205,6 +205,7 @@ contract SuperformRouterAATest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 10_000, /// @dev invalid slippage LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ARBI, 0), @@ -299,6 +300,7 @@ contract SuperformRouterAATest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 10_000, /// @dev invalid slippage LiqRequest( @@ -434,6 +436,7 @@ contract SuperformRouterAATest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( v.superformId, 1e18, + 1e18, 1000, LiqRequest( _buildLiqBridgeTxData( @@ -517,6 +520,7 @@ contract SuperformRouterAATest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( v.superformId, 1e18, + 1e18, 1000, LiqRequest( _buildLiqBridgeTxData( diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index a349f7bd9..72d147931 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -11,6 +11,7 @@ contract SuperformRouterTest is ProtocolActions { address superformRouter; uint256[] superformIds; uint256[] amounts; + uint256[] outputAmounts; uint256[] maxSlippages; bool[] hasDstSwaps; bool[] retain4626s; @@ -47,6 +48,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -81,6 +83,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -117,6 +120,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -156,6 +160,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -172,6 +179,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -211,6 +219,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -227,7 +238,7 @@ contract SuperformRouterTest is ProtocolActions { liqReq[0] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); MultiVaultSFData memory data = MultiVaultSFData( - superformIds, amounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, address(0), address(0), "" + superformIds, amounts, outputAmounts, maxSlippages, liqReq, "", hasDstSwaps, retain4626s, address(0), address(0), "" ); SingleDirectMultiVaultStateReq memory req = SingleDirectMultiVaultStateReq(data); @@ -261,6 +272,10 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 100; maxSlippages[1] = 100; @@ -280,6 +295,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -323,6 +339,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -340,6 +359,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -375,6 +395,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 10_001, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -418,6 +439,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -435,6 +459,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -471,6 +496,8 @@ contract SuperformRouterTest is ProtocolActions { uint256 amount = 1e18; + uint256 outputAmount = 1e18; + uint256 maxSlippage = 100; uint8[] memory ambIds = new uint8[](1); @@ -479,7 +506,7 @@ contract SuperformRouterTest is ProtocolActions { LiqRequest memory liqReq = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); SingleVaultSFData memory data = SingleVaultSFData( - superformId, amount, maxSlippage, liqReq, "", false, false, receiverAddress, receiverAddress, "" + superformId, amount, outputAmount, maxSlippage, liqReq, "", false, false, receiverAddress, receiverAddress, "" ); SingleXChainSingleVaultStateReq memory req = SingleXChainSingleVaultStateReq(ambIds, ETH, data); @@ -508,6 +535,8 @@ contract SuperformRouterTest is ProtocolActions { uint256 amount = 1e18; + uint256 outputAmount = 1e18; + uint256 maxSlippage = 100; uint8[] memory ambIds = new uint8[](1); @@ -516,7 +545,7 @@ contract SuperformRouterTest is ProtocolActions { LiqRequest memory liqReq = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); SingleVaultSFData memory data = SingleVaultSFData( - superformId, amount, maxSlippage, liqReq, "", false, false, receiverAddress, receiverAddress, "" + superformId, amount, outputAmount, maxSlippage, liqReq, "", false, false, receiverAddress, receiverAddress, "" ); SingleXChainSingleVaultStateReq memory req = SingleXChainSingleVaultStateReq(ambIds, ARBI, data); @@ -548,6 +577,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](0); uint8[] memory ambIds = new uint8[](1); @@ -563,6 +595,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -597,6 +630,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](0); uint8[] memory ambIds = new uint8[](1); @@ -612,6 +648,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -648,6 +685,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -664,6 +704,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -699,6 +740,64 @@ contract SuperformRouterTest is ProtocolActions { /// @dev 0 amounts length uint256[] memory amounts = new uint256[](0); + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + + uint256[] memory maxSlippages = new uint256[](1); + maxSlippages[0] = 100; + + uint8[] memory ambIds = new uint8[](1); + ambIds[0] = 1; + + bool[] memory hasDstSwaps = new bool[](1); + + bool[] memory retain4626s = new bool[](1); + + LiqRequest[] memory liqReq = new LiqRequest[](1); + liqReq[0] = LiqRequest("", getContract(ARBI, "DAI"), address(0), 1, ETH, 0); + + MultiVaultSFData memory data = MultiVaultSFData( + superformIds, + amounts, + outputAmounts, + maxSlippages, + liqReq, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" + ); + + SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); + address superformRouter = getContract(ETH, "SuperformRouter"); + /// @dev approves before call + MockERC20(getContract(ETH, "DAI")).approve(superformRouter, 1e18); + + vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); + SuperformRouter(payable(superformRouter)).singleXChainMultiVaultDeposit(req); + } + + function test_depositWithWrongOutputAmountsLength() public { + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + address superform = getContract( + ARBI, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ); + + uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ARBI); + + uint256[] memory superformIds = new uint256[](1); + superformIds[0] = superformId; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1e18; + + /// @dev 0 amounts length + uint256[] memory outputAmounts = new uint256[](0); + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -715,6 +814,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -752,6 +852,9 @@ contract SuperformRouterTest is ProtocolActions { amounts[1] = 1e18; /// @dev new amount + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -768,6 +871,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -803,6 +907,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 10_001; /// @dev invalid max slippage @@ -820,6 +927,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -867,6 +975,10 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 1000; maxSlippages[1] = 1000; @@ -882,6 +994,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", @@ -931,6 +1044,79 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](0); + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + + uint256[] memory maxSlippages = new uint256[](2); + maxSlippages[0] = 1000; + maxSlippages[1] = 1000; + + bool[] memory hasDstSwaps = new bool[](2); + + bool[] memory retain4626s = new bool[](2); + + LiqRequest[] memory liqReqs = new LiqRequest[](2); + liqReqs[0] = LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0); + liqReqs[1] = LiqRequest("", getContract(ETH, "WETH"), address(0), 1, ETH, 0); + + MultiVaultSFData memory data = MultiVaultSFData( + superformIds, + amounts, + outputAmounts, + maxSlippages, + liqReqs, + "", + hasDstSwaps, + retain4626s, + receiverAddress, + receiverAddress, + "" + ); + uint8[] memory ambIds = new uint8[](2); + ambIds[0] = 1; + ambIds[1] = 2; + + SingleXChainMultiVaultStateReq memory req = SingleXChainMultiVaultStateReq(ambIds, ARBI, data); + + /// @dev approves before call + MockERC20(getContract(ETH, "DAI")).approve(superformRouter, 1e18); + MockERC20(getContract(ETH, "WETH")).approve(superformRouter, 1e18); + + vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); + SuperformRouter(payable(superformRouter)).singleXChainMultiVaultWithdraw{ value: 2 ether }(req); + } + + function test_withdrawWithWrongOutputAmountsLength() public { + _successfulMultiVaultDeposit(); + + /// scenario: user deposits with his own token and has approved enough tokens + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + address superformRouter = getContract(ETH, "SuperformRouter"); + + address superform1 = getContract( + ARBI, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ); + + address superform2 = getContract( + ARBI, string.concat("WETH", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ); + + uint256 superformId1 = DataLib.packSuperform(superform1, FORM_IMPLEMENTATION_IDS[0], ARBI); + uint256 superformId2 = DataLib.packSuperform(superform2, FORM_IMPLEMENTATION_IDS[0], ARBI); + + uint256[] memory superformIds = new uint256[](2); + superformIds[0] = superformId1; + superformIds[1] = superformId2; + + uint256[] memory amounts = new uint256[](0); + amounts[0] = 1e18; + amounts[1] = 1e18; + + uint256[] memory outputAmounts = new uint256[](0); + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 1000; maxSlippages[1] = 1000; @@ -946,6 +1132,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", @@ -997,6 +1184,10 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 10_001; maxSlippages[1] = 99_999; @@ -1012,6 +1203,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", @@ -1049,6 +1241,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -1085,7 +1278,8 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 0, - /// @dev 0 amount here and in the LiqRequest + /// @dev 0 amount here and in the LiqRequest, + 1e18, 100, LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 0), "", @@ -1105,6 +1299,43 @@ contract SuperformRouterTest is ProtocolActions { SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); } + function test_depositWithZeroOutputAmount() public { + /// scenario: deposit to an invalid super form id (which doesn't exist on the chain) + vm.selectFork(FORKS[ETH]); + vm.startPrank(deployer); + + /// try depositing without approval + address superform = getContract( + ETH, string.concat("DAI", "VaultMock", "Superform", Strings.toString(FORM_IMPLEMENTATION_IDS[0])) + ); + + uint256 superformId = DataLib.packSuperform(superform, FORM_IMPLEMENTATION_IDS[0], ETH); + + SingleVaultSFData memory data = SingleVaultSFData( + superformId, + 1e18, + 0, + 100, + LiqRequest("", getContract(ETH, "DAI"), address(0), 1, ETH, 1e18), + "", + false, + false, + receiverAddress, + receiverAddress, + "" + ); + + SingleDirectSingleVaultStateReq memory req = SingleDirectSingleVaultStateReq(data); + + address router = getContract(ETH, "SuperformRouter"); + + /// @dev approves before call + MockERC20(getContract(ETH, "DAI")).approve(router, 1e18); + + vm.expectRevert(Error.INVALID_SUPERFORMS_DATA.selector); + SuperformRouter(payable(getContract(ETH, "SuperformRouter"))).singleDirectSingleVaultDeposit(req); + } + function test_withdrawMultiVaultXChain_InvalidAction() public { /// scenario: withdraw from an paused form form id (which doesn't exist on the chain) vm.selectFork(FORKS[ETH]); @@ -1130,6 +1361,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -1147,6 +1381,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -1192,6 +1427,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -1209,6 +1447,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -1267,6 +1506,9 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; + uint256[] memory outputAmounts = new uint256[](1); + outputAmounts[0] = 1e18; + uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -1283,6 +1525,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReq, "", @@ -1320,6 +1563,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest( _buildDummyTxDataUnitTests( @@ -1388,6 +1632,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts[0] = 1e18; v.amounts[1] = 1e18; + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; + v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; v.maxSlippages[1] = 1000; @@ -1452,6 +1700,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, "", @@ -1489,6 +1738,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 100, LiqRequest( _buildDummyTxDataUnitTests( @@ -1545,6 +1795,7 @@ contract SuperformRouterTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 1e18, + 1e18, 10_001, /// @dev invalid slippage LiqRequest( @@ -1614,6 +1865,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts[0] = 1e18; v.amounts[1] = 1e18; + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; + v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; v.maxSlippages[1] = 1000; @@ -1678,6 +1933,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, "", @@ -1727,6 +1983,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts = new uint256[](2); v.amounts[0] = 1e18; v.amounts[1] = 1e18; + + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; @@ -1804,6 +2064,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, "", @@ -1854,6 +2115,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts[0] = 1e18; v.amounts[1] = 1e18; + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; + v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; v.maxSlippages[1] = 1000; @@ -1933,6 +2198,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, abi.encode( @@ -1977,6 +2243,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts[0] = 1e18; v.amounts[1] = 1e18; + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; + v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; v.maxSlippages[1] = 1000; @@ -2058,6 +2328,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, abi.encode(v.permit.nonce, v.permit.deadline, permitSigned), @@ -2100,6 +2371,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts[0] = 1e18; v.amounts[1] = 1e18; + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; + v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; v.maxSlippages[1] = 1000; @@ -2175,6 +2450,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, "", @@ -2217,6 +2493,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts[0] = 1e18; v.amounts[1] = 1e18; + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; + v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; v.maxSlippages[1] = 1000; @@ -2292,6 +2572,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, "", @@ -2334,6 +2615,10 @@ contract SuperformRouterTest is ProtocolActions { v.amounts[0] = 1e18; v.amounts[1] = 1e18; + v.outputAmounts = new uint256[](2); + v.outputAmounts[0] = 1e18; + v.outputAmounts[1] = 1e18; + v.maxSlippages = new uint256[](2); v.maxSlippages[0] = 1000; v.maxSlippages[1] = 1000; @@ -2367,6 +2652,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData( v.superformIds, v.amounts, + v.outputAmounts, v.maxSlippages, v.liqReqs, v.permit2Data, @@ -2406,6 +2692,10 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 1000; maxSlippages[1] = 1000; @@ -2418,6 +2708,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", @@ -2461,6 +2752,10 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 1000; maxSlippages[1] = 1000; @@ -2477,6 +2772,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", @@ -2619,6 +2915,7 @@ contract SuperformRouterTest is ProtocolActions { v.data = SingleVaultSFData( superformId, 2e18, + 2e18, 1000, LiqRequest( _buildLiqBridgeTxData( @@ -2780,6 +3077,10 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 1000; maxSlippages[1] = 1000; @@ -2844,6 +3145,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, + outputAmounts, maxSlippages, liqReqs, "", diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index 55ccf4733..cd233572a 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -228,6 +228,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vars.underlyingDstToken, vars.targetSuperformIds, vars.amounts, + vars.amounts, vars.liqBridges, vars.receive4626, 1000, @@ -275,6 +276,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { address(0), vars.targetSuperformIds[0], finalAmount, + finalAmount, vars.liqBridges[0], vars.receive4626[0], 1000, @@ -902,6 +904,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { address(0), args.superformIds[i], finalAmounts[i], + finalAmounts[i], args.liqBridges[i], args.receive4626[i], args.maxSlippage, @@ -951,6 +954,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { superformsData = MultiVaultSFData( args.superformIds, finalAmounts, + args.outputAmounts, maxSlippageTemp, liqRequests, v.permit2data, @@ -1135,6 +1139,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { superformData = SingleVaultSFData( args.superformId, v.amount, + args.outputAmount, args.maxSlippage, v.liqReq, v.permit2Calldata, @@ -1245,6 +1250,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { superformData = SingleVaultSFData( args.superformId, args.amount, + args.outputAmount, args.maxSlippage, vars.liqReq, "", diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index e5e659146..af16bb7ac 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -399,6 +399,8 @@ abstract contract ProtocolActions is CommonProtocolActions { vars.amounts = AMOUNTS[DST_CHAINS[i]][actionIndex]; + vars.outputAmounts = vars.amounts; + vars.liqBridges = LIQ_BRIDGES[DST_CHAINS[i]][actionIndex]; vars.receive4626 = RECEIVE_4626[DST_CHAINS[i]][actionIndex]; @@ -416,6 +418,7 @@ abstract contract ProtocolActions is CommonProtocolActions { vars.underlyingDstToken, vars.targetSuperformIds, vars.amounts, + vars.outputAmounts, vars.liqBridges, vars.receive4626, MAX_SLIPPAGE, @@ -463,6 +466,7 @@ abstract contract ProtocolActions is CommonProtocolActions { action.dstSwap ? getContract(DST_CHAINS[i], UNDERLYING_TOKENS[0]) : address(0), vars.targetSuperformIds[0], finalAmount, + finalAmount, vars.liqBridges[0], vars.receive4626[0], MAX_SLIPPAGE, @@ -1571,6 +1575,7 @@ abstract contract ProtocolActions is CommonProtocolActions { uniqueInterimToken, args.superformIds[i], finalAmounts[i], + finalAmounts[i], args.liqBridges[i], args.receive4626[i], args.maxSlippage, @@ -1621,6 +1626,7 @@ abstract contract ProtocolActions is CommonProtocolActions { superformsData = MultiVaultSFData( args.superformIds, finalAmounts, + args.outputAmounts, maxSlippageTemp, liqRequests, v.permit2data, @@ -1846,6 +1852,7 @@ abstract contract ProtocolActions is CommonProtocolActions { superformData = SingleVaultSFData( args.superformId, v.amount, + args.outputAmount, args.maxSlippage, v.liqReq, v.permit2Calldata, @@ -1959,6 +1966,7 @@ abstract contract ProtocolActions is CommonProtocolActions { superformData = SingleVaultSFData( args.superformId, args.amount, + args.outputAmount, args.maxSlippage, vars.liqReq, "", @@ -3534,6 +3542,7 @@ abstract contract ProtocolActions is CommonProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, 2e18, + 2e18, 1000, LiqRequest( _buildLiqBridgeTxData( diff --git a/test/utils/TestTypes.sol b/test/utils/TestTypes.sol index fdc20564d..ff6c31adb 100644 --- a/test/utils/TestTypes.sol +++ b/test/utils/TestTypes.sol @@ -52,6 +52,7 @@ struct StagesLocalVars { address[] toDst; uint256[] targetSuperformIds; uint256[] amounts; + uint256[] outputAmounts; uint8[] liqBridges; bool[] receive4626; uint256 chain0Index; @@ -193,6 +194,7 @@ struct SingleVaultCallDataArgs { address uniqueInterimToken; uint256 superformId; uint256 amount; + uint256 outputAmount; uint8 liqBridge; bool receive4626; uint256 maxSlippage; @@ -216,6 +218,7 @@ struct MultiVaultCallDataArgs { address[] underlyingTokensDst; uint256[] superformIds; uint256[] amounts; + uint256[] outputAmounts; uint8[] liqBridges; bool[] receive4626; uint256 maxSlippage; From a30a49ccf834766e42533efb14bf2ba2a1665bfe Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 11:32:30 -0600 Subject: [PATCH 187/210] chore: cross-multiply --- src/forms/ERC4626FormImplementation.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 0ca3cc913..2a92af2e6 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -412,7 +412,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); if ((sharesBalanceAfter - sharesBalanceBefore != shares) || - (shares < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + (ENTIRE_SLIPPAGE * shares < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) )) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -432,7 +432,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { uint256 assetsBalanceAfter = a.balanceOf(assetsReceiver); if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (assets < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) / ENTIRE_SLIPPAGE)) + (ENTIRE_SLIPPAGE * assets < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) )) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -451,7 +451,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { { if ( bridgeDecodedAmount_ > redeemedAmount_ - || bridgeDecodedAmount_ < ((redeemedAmount_ * (ENTIRE_SLIPPAGE - slippage_)) / ENTIRE_SLIPPAGE) + || ((bridgeDecodedAmount_ * ENTIRE_SLIPPAGE) < (redeemedAmount_ * (ENTIRE_SLIPPAGE - slippage_))) ) return true; } From 54007a648545f759af0005779e42f360eb9e2d59 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:53:13 +0000 Subject: [PATCH 188/210] chore: configure deployment for ctf launch --- .env.example | 3 - foundry.toml | 2 - script/Abstract.Deploy.Single.s.sol | 235 ++++++++++++++----------- script/Mainnet.Deploy.NewChain.s.sol | 6 +- script/Tenderly.Deploy.s.sol | 2 +- script/output/1/Ethereum-latest.json | 19 ++ script/output/56/Binance-latest.json | 40 ++--- utils/run_script_mainnet.sh | 14 +- utils/run_script_mainnet_new_chain.sh | 1 + utils/run_script_tenderly.sh | 27 +-- utils/run_script_tenderly_new_chain.sh | 13 +- 11 files changed, 208 insertions(+), 154 deletions(-) diff --git a/.env.example b/.env.example index 8c510d408..794c272b4 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,6 @@ REPORT_GAS=false PRODUCTION=false POLYGON_RPC_URL= AVALANCHE_RPC_URL= -FANTOM_RPC_URL= BSC_RPC_URL= ARBITRUM_RPC_URL= OPTIMISM_RPC_URL= @@ -15,11 +14,9 @@ BSC_LOCAL_URL=http://127.0.0.1:8546 AVALANCHE_LOCAL_URL=http://127.0.0.1:8547 ARBITRUM_LOCAL_URL=http://127.0.0.1:8549 OPTIMISM_LOCAL_URL=http://127.0.0.1:8550 -FANTOM_LOCAL_URL=http://127.0.0.1:8551 BASE_LOCAL_URL=http://127.0.0.1:8552 GNOSIS_LOCAL_URL=http://127.0.0.1:8553 OWNER_ADDRESS= -MULTI_SIG_ADDRESS= DEPLOYER_KEY= FOUNDRY_EXPORTS_OVERWRITE_LATEST=true RUST_BACKTRACE=full diff --git a/foundry.toml b/foundry.toml index 5e053ddcf..049f0609c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -43,7 +43,6 @@ bsc = "${BSC_RPC_URL}" avalanche = "${AVALANCHE_RPC_URL}" arbitrum = "${ARBITRUM_RPC_URL}" optimism = "${OPTIMISM_RPC_URL}" -fantom = "${FANTOM_RPC_URL}" base = "${BASE_RPC_URL}" gnosis = "${GNOSIS_RPC_URL}" ethereum_fork = "${ETHEREUM_LOCAL_URL}" @@ -52,7 +51,6 @@ bsc_fork = "${BSC_LOCAL_URL}" avalanche_fork = "${AVALANCHE_LOCAL_URL}" arbitrum_fork = "${ARBITRUM_LOCAL_URL}" optimism_fork = "${OPTIMISM_LOCAL_URL}" -fantom_fork = "${FANTOM_LOCAL_URL}" base_fork = "${BASE_LOCAL_URL}" gnosis_fork = "${GNOSIS_LOCAL_URL}" diff --git a/script/Abstract.Deploy.Single.s.sol b/script/Abstract.Deploy.Single.s.sol index 70ff784f1..4b226041a 100644 --- a/script/Abstract.Deploy.Single.s.sol +++ b/script/Abstract.Deploy.Single.s.sol @@ -88,22 +88,22 @@ abstract contract AbstractDeploySingle is Script { address public constant CANONICAL_PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; mapping(uint64 chainId => mapping(bytes32 implementation => address at)) public contracts; - string[23] public contractNames = [ + string[17] public contractNames = [ "CoreStateRegistry", - "TimelockStateRegistry", - "BroadcastRegistry", + //"TimelockStateRegistry", + //"BroadcastRegistry", "LayerzeroImplementation", "HyperlaneImplementation", "WormholeARImplementation", - "WormholeSRImplementation", + //"WormholeSRImplementation", "LiFiValidator", "SocketValidator", - "SocketOneInchValidator", + //"SocketOneInchValidator", "DstSwapper", "SuperformFactory", "ERC4626Form", - "ERC4626TimelockForm", - "ERC4626KYCDaoForm", + //"ERC4626TimelockForm", + //"ERC4626KYCDaoForm", "SuperformRouter", "SuperPositions", "SuperRegistry", @@ -121,7 +121,6 @@ abstract contract AbstractDeploySingle is Script { Avalanche, Arbitrum, Optimism, - Fantom, Base, Gnosis, Ethereum_Fork, @@ -130,7 +129,6 @@ abstract contract AbstractDeploySingle is Script { Avalanche_Fork, Arbitrum_Fork, Optimism_Fork, - Fantom_Fork, Base_Fork, Gnosis_Fork } @@ -140,11 +138,6 @@ abstract contract AbstractDeploySingle is Script { Prod } - uint256 public deployerPrivateKey; - address public ownerAddress; - address public burnerPrivateKey; - address public multiSigAddress; - /// @dev Mapping of chain enum to rpc url mapping(Chains chains => string rpcUrls) public forks; @@ -156,8 +149,9 @@ abstract contract AbstractDeploySingle is Script { uint32[] public FORM_IMPLEMENTATION_IDS = [uint32(1), uint32(2), uint32(3)]; string[] public VAULT_KINDS = ["Vault", "TimelockedVault", "KYCDaoVault"]; - /// @dev liquidity bridge ids 1 is lifi, 2 is socket, 3 is socket one inch implementation - uint8[] public bridgeIds = [1, 2, 3]; + /// @dev liquidity bridge ids 1 is lifi, 2 is socket, 3 is socket one inch implementation (not added to this + /// release) + uint8[] public bridgeIds = [1, 2]; mapping(uint64 chainId => address[] bridgeAddresses) public BRIDGE_ADDRESSES; @@ -165,9 +159,9 @@ abstract contract AbstractDeploySingle is Script { /// @notice id 1 is layerzero /// @notice id 2 is hyperlane /// @notice id 3 is wormhole AR - /// @notice 4 is wormhole SR - uint8[] public ambIds = [uint8(1), 2, 3, 4]; - bool[] public broadcastAMB = [false, false, false, true]; + /// @notice FIXME 4 is wormhole SR - not added + uint8[] public ambIds = [uint8(1), 2, 3]; + bool[] public broadcastAMB = [false, false, false]; /*////////////////////////////////////////////////////////////// AMB VARIABLES @@ -181,7 +175,6 @@ abstract contract AbstractDeploySingle is Script { address public constant POLY_lzEndpoint = 0x3c2269811836af69497E5F486A85D7316753cf62; address public constant ARBI_lzEndpoint = 0x3c2269811836af69497E5F486A85D7316753cf62; address public constant OP_lzEndpoint = 0x3c2269811836af69497E5F486A85D7316753cf62; - address public constant FTM_lzEndpoint = 0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7; address public constant BASE_lzEndpoint = 0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7; address public constant GNOSIS_lzEndpoint = 0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4; @@ -195,11 +188,9 @@ abstract contract AbstractDeploySingle is Script { 0x3c2269811836af69497E5F486A85D7316753cf62, 0x3c2269811836af69497E5F486A85D7316753cf62, 0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7, - 0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7, 0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4 ]; - /// @dev NOTE: hyperlane does not support FTM address[] public hyperlaneMailboxes = [ 0xc005dc82818d67AF737725bD4bf75435d065D239, 0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4, @@ -207,7 +198,6 @@ abstract contract AbstractDeploySingle is Script { 0x5d934f4e2f797775e53561bB72aca21ba36B96BB, 0x979Ca5202784112f4738403dBec5D0F3B9daabB9, 0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D, - address(0), 0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D, 0xaD09d78f4c6b9dA2Ae82b1D34107802d380Bb74f ]; @@ -219,7 +209,6 @@ abstract contract AbstractDeploySingle is Script { 0x0071740Bf129b05C4684abfbBeD248D80971cce2, 0x3b6044acd6767f017e99318AA6Ef93b7B06A5a22, 0xD8A76C4D91fCbB7Cc8eA795DFDF870E48368995C, - address(0), 0xc3F23848Ed2e04C0c6d41bd7804fa8f89F940B94, 0xDd260B99d302f0A3fF885728c086f729c06f227f ]; @@ -231,7 +220,6 @@ abstract contract AbstractDeploySingle is Script { 0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7, 0xa5f208e072434bC67592E4C49C1B991BA79BCA46, 0xEe91C335eab126dF5fDB3797EA9d6aD93aeC9722, - 0x126783A6Cb203a3E35344528B26ca3a0489a1485, 0xbebdb6C8ddC678FfA9f8748f85C815C556Dd8ac6, 0xa321448d90d4e5b0A732867c18eA198e75CAC48E ]; @@ -247,18 +235,17 @@ abstract contract AbstractDeploySingle is Script { uint64 public constant POLY = 137; uint64 public constant ARBI = 42_161; uint64 public constant OP = 10; - uint64 public constant FTM = 250; uint64 public constant BASE = 8453; uint64 public constant GNOSIS = 100; - uint64[] public chainIds = [1, 56, 43_114, 137, 42_161, 10, 250, 8453, 100]; + uint64[] public chainIds = [1, 56, 43_114, 137, 42_161, 10, 8453, 100]; string[] public chainNames = ["Ethereum", "Binance", "Avalanche", "Polygon", "Arbitrum", "Optimism", "Fantom", "Base", "Gnosis"]; /// @dev vendor chain ids - uint16[] public lz_chainIds = [101, 102, 106, 109, 110, 111, 112, 184, 145]; - uint32[] public hyperlane_chainIds = [1, 56, 43_114, 137, 42_161, 10, 250, 8453, 100]; - uint16[] public wormhole_chainIds = [2, 4, 6, 5, 23, 24, 10, 30, 25]; + uint16[] public lz_chainIds = [101, 102, 106, 109, 110, 111, 184, 145]; + uint32[] public hyperlane_chainIds = [1, 56, 43_114, 137, 42_161, 10, 8453, 100]; + uint16[] public wormhole_chainIds = [2, 4, 6, 5, 23, 24, 30, 25]; uint256 public constant milionTokensE18 = 1 ether; @@ -279,20 +266,46 @@ abstract contract AbstractDeploySingle is Script { 0x205E10d3c4C87E26eB66B1B270b71b7708494dB9, address(0), address(0), - address(0), address(0) ]; + /*////////////////////////////////////////////////////////////// + RBAC VARIABLES + //////////////////////////////////////////////////////////////*/ + + uint256 public deployerPrivateKey; + + address public ownerAddress; + + address constant EMERGENCY_ADMIN = 0x73009CE7cFFc6C4c5363734d1b429f0b848e0490; + + address[] public PROTOCOL_ADMINS = [ + 0xd26b38a64C812403fD3F87717624C80852cD6D61, + /// @dev ETH https://app.onchainden.com/safes/eth:0xd26b38a64c812403fd3f87717624c80852cd6d61 + 0xf70A19b67ACC4169cA6136728016E04931D550ae, + /// @dev BSC https://app.onchainden.com/safes/bnb:0xf70a19b67acc4169ca6136728016e04931d550ae + 0x79DD9868A1a89720981bF077A02a4A43c57080d2, + /// @dev AVAX https://app.onchainden.com/safes/avax:0x79dd9868a1a89720981bf077a02a4a43c57080d2 + 0x5022b05721025159c82E02abCb0Daa87e357f437, + /// @dev POLY https://app.onchainden.com/safes/matic:0x5022b05721025159c82e02abcb0daa87e357f437 + 0x7Fc07cAFb65d1552849BcF151F7035C5210B76f4, + /// @dev ARBI https://app.onchainden.com/safes/arb1:0x7fc07cafb65d1552849bcf151f7035c5210b76f4 + 0x99620a926D68746D5F085B3f7cD62F4fFB71f0C1, + /// @dev OP https://app.onchainden.com/safes/oeth:0x99620a926d68746d5f085b3f7cd62f4ffb71f0c1 + 0x2F973806f8863E860A553d4F2E7c2AB4A9F3b87C, + /// @dev BASE https://app.onchainden.com/safes/base:0x2f973806f8863e860a553d4f2e7c2ab4a9f3b87c + address(0) + /// @dev GNOSIS FIXME - PROTOCOL ADMIN NOT SET FOR GNOSIS + ]; + /// @dev environment variable setup for upgrade /// @param cycle deployment cycle (dev, prod) modifier setEnvDeploy(Cycle cycle) { if (cycle == Cycle.Dev) { (ownerAddress, deployerPrivateKey) = makeAddrAndKey("tenderly"); - //multiSigAddress = vm.envAddress("MULTI_SIG_ADDRESS"); } else { deployerPrivateKey = vm.envUint("DEPLOYER_KEY"); ownerAddress = vm.envAddress("OWNER_ADDRESS"); - multiSigAddress = vm.envAddress("MULTI_SIG_ADDRESS"); } _; @@ -306,7 +319,6 @@ abstract contract AbstractDeploySingle is Script { forks[Chains.Avalanche] = "avalanche"; forks[Chains.Arbitrum] = "arbitrum"; forks[Chains.Optimism] = "optimism"; - forks[Chains.Fantom] = "fantom"; forks[Chains.Base] = "base"; forks[Chains.Gnosis] = "gnosis"; @@ -317,7 +329,6 @@ abstract contract AbstractDeploySingle is Script { forks[Chains.Avalanche_Fork] = "avalanche_fork"; forks[Chains.Arbitrum_Fork] = "arbitrum_fork"; forks[Chains.Optimism_Fork] = "optimism_fork"; - forks[Chains.Fantom_Fork] = "fantom_fork"; forks[Chains.Base_Fork] = "base_fork"; forks[Chains.Gnosis_Fork] = "gnosis_fork"; } @@ -354,13 +365,16 @@ abstract contract AbstractDeploySingle is Script { emergencyAdmin: ownerAddress, paymentAdmin: 0xD911673eAF0D3e15fe662D58De15511c5509bAbB, csrProcessor: 0x23c658FE050B4eAeB9401768bF5911D11621629c, - tlProcessor: ownerAddress, - brProcessor: ownerAddress, + tlProcessor: EMERGENCY_ADMIN, + /// @dev Temporary, as we are not using this processor in this release + brProcessor: EMERGENCY_ADMIN, + /// @dev Temporary, as we are not using this processor in this release csrUpdater: 0xaEbb4b9f7e16BEE2a0963569a5E33eE10E478a5f, - srcVaaRelayer: ownerAddress, + srcVaaRelayer: EMERGENCY_ADMIN, + /// @dev Temporary, as we are not using this processor in this release dstSwapper: 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, csrRescuer: 0x90ed07A867bDb6a73565D7abBc7434Dd810Fafc5, - csrDisputer: ownerAddress + csrDisputer: 0x7c9c8C0A9aA5D8a2c2e6C746641117Cc9591296a }) ) ); @@ -384,29 +398,34 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress(vars.superRegistryC.CORE_STATE_REGISTRY(), vars.coreStateRegistry, vars.chainId); - /// @dev 3.2 - deploy Form State Registry + /* + /// @dev 3.2 - deploy Timelock State Registry vars.timelockStateRegistry = address(new TimelockStateRegistry{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("TimelockStateRegistry"))] = vars.timelockStateRegistry; + vars.superRegistryC.setAddress( vars.superRegistryC.TIMELOCK_STATE_REGISTRY(), vars.timelockStateRegistry, vars.chainId ); + */ + /* /// @dev 3.3 - deploy Broadcast State Registry vars.broadcastRegistry = address(new BroadcastRegistry{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("BroadcastRegistry"))] = vars.broadcastRegistry; vars.superRegistryC.setAddress(vars.superRegistryC.BROADCAST_REGISTRY(), vars.broadcastRegistry, vars.chainId); + */ - address[] memory registryAddresses = new address[](3); + address[] memory registryAddresses = new address[](1); registryAddresses[0] = vars.coreStateRegistry; - registryAddresses[1] = vars.timelockStateRegistry; - registryAddresses[2] = vars.broadcastRegistry; + //registryAddresses[1] = vars.timelockStateRegistry; + //registryAddresses[2] = vars.broadcastRegistry; - uint8[] memory registryIds = new uint8[](3); + uint8[] memory registryIds = new uint8[](1); registryIds[0] = 1; - registryIds[1] = 2; - registryIds[2] = 3; + //registryIds[1] = 2; + //registryIds[2] = 3; vars.superRegistryC.setStateRegistryAddress(registryIds, registryAddresses); @@ -436,6 +455,7 @@ abstract contract AbstractDeploySingle is Script { WormholeARImplementation(vars.wormholeImplementation).setWormholeRelayer(wormholeRelayer); WormholeARImplementation(vars.wormholeImplementation).setRefundChainId(wormhole_chainIds[i]); + /* /// @dev 6.5- deploy Wormhole Specialized Relayer Implementation vars.wormholeSRImplementation = address(new WormholeSRImplementation{ salt: salt }(vars.superRegistryC)); contracts[vars.chainId][bytes32(bytes("WormholeSRImplementation"))] = vars.wormholeSRImplementation; @@ -443,11 +463,12 @@ abstract contract AbstractDeploySingle is Script { WormholeSRImplementation(vars.wormholeSRImplementation).setWormholeCore(wormholeCore[trueIndex]); /// @dev FIXME who is the wormhole relayer on mainnet? WormholeSRImplementation(vars.wormholeSRImplementation).setRelayer(ownerAddress); + */ vars.ambAddresses[0] = vars.lzImplementation; vars.ambAddresses[1] = vars.hyperlaneImplementation; vars.ambAddresses[2] = vars.wormholeImplementation; - vars.ambAddresses[3] = vars.wormholeSRImplementation; + //vars.ambAddresses[3] = vars.wormholeSRImplementation; /// @dev 6- deploy liquidity validators vars.lifiValidator = address(new LiFiValidator{ salt: salt }(vars.superRegistry)); @@ -456,12 +477,14 @@ abstract contract AbstractDeploySingle is Script { vars.socketValidator = address(new SocketValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SocketValidator"))] = vars.socketValidator; + /* vars.socketOneInchValidator = address(new SocketOneInchValidator{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SocketOneInchValidator"))] = vars.socketOneInchValidator; + */ bridgeValidators[0] = vars.lifiValidator; bridgeValidators[1] = vars.socketValidator; - bridgeValidators[2] = vars.socketOneInchValidator; + //bridgeValidators[2] = vars.socketOneInchValidator; /// @dev 7 - Deploy SuperformFactory vars.factory = address(new SuperformFactory{ salt: salt }(vars.superRegistry)); @@ -478,20 +501,21 @@ abstract contract AbstractDeploySingle is Script { contracts[vars.chainId][bytes32(bytes("ERC4626Form"))] = vars.erc4626Form; // Timelock + ERC4626 Form - vars.erc4626TimelockForm = address(new ERC4626TimelockForm{ salt: salt }(vars.superRegistry)); - contracts[vars.chainId][bytes32(bytes("ERC4626TimelockForm"))] = vars.erc4626TimelockForm; + //vars.erc4626TimelockForm = address(new ERC4626TimelockForm{ salt: salt }(vars.superRegistry)); + //contracts[vars.chainId][bytes32(bytes("ERC4626TimelockForm"))] = vars.erc4626TimelockForm; /// 9 KYCDao ERC4626 Form - vars.kycDao4626Form = address(new ERC4626KYCDaoForm{ salt: salt }(vars.superRegistry)); - contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; + //vars.kycDao4626Form = address(new ERC4626KYCDaoForm{ salt: salt }(vars.superRegistry)); + //contracts[vars.chainId][bytes32(bytes("ERC4626KYCDaoForm"))] = vars.kycDao4626Form; /// @dev 9 - Add newly deployed form implementations to Factory, formImplementationId 1 ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626Form, FORM_IMPLEMENTATION_IDS[0], 1); /// passing 2 cuz timelock state registry id is 2 - ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1], 2); + //ISuperformFactory(vars.factory).addFormImplementation(vars.erc4626TimelockForm, FORM_IMPLEMENTATION_IDS[1], + // 2); - ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 1); + //ISuperformFactory(vars.factory).addFormImplementation(vars.kycDao4626Form, FORM_IMPLEMENTATION_IDS[2], 1); /// @dev 10 - Deploy SuperformRouter vars.superformRouter = address(new SuperformRouter{ salt: salt }(vars.superRegistry)); @@ -560,19 +584,27 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_PROCESSOR(), 0x23c658FE050B4eAeB9401768bF5911D11621629c, vars.chainId ); - vars.superRegistryC.setAddress(vars.superRegistryC.BROADCAST_REGISTRY_PROCESSOR(), ownerAddress, vars.chainId); - vars.superRegistryC.setAddress(vars.superRegistryC.TIMELOCK_REGISTRY_PROCESSOR(), ownerAddress, vars.chainId); + /// @dev FIXME setting this temporarily to EMERGENCY_ADMIN as we are not using it in this release + vars.superRegistryC.setAddress( + vars.superRegistryC.BROADCAST_REGISTRY_PROCESSOR(), EMERGENCY_ADMIN, vars.chainId + ); + /// @dev FIXME setting this temporarily to EMERGENCY_ADMIN as we are not using it in this release + vars.superRegistryC.setAddress(vars.superRegistryC.TIMELOCK_REGISTRY_PROCESSOR(), EMERGENCY_ADMIN, vars.chainId); vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_UPDATER(), 0xaEbb4b9f7e16BEE2a0963569a5E33eE10E478a5f, vars.chainId ); vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_RESCUER(), 0x90ed07A867bDb6a73565D7abBc7434Dd810Fafc5, vars.chainId ); - vars.superRegistryC.setAddress(vars.superRegistryC.CORE_REGISTRY_DISPUTER(), ownerAddress, vars.chainId); + vars.superRegistryC.setAddress( + vars.superRegistryC.CORE_REGISTRY_DISPUTER(), 0x7c9c8C0A9aA5D8a2c2e6C746641117Cc9591296a, vars.chainId + ); vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, vars.chainId ); - vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_RECEIVER(), ownerAddress, vars.chainId); + vars.superRegistryC.setAddress( + vars.superRegistryC.SUPERFORM_RECEIVER(), 0x1a6805487322565202848f239C1B5bC32303C2FE, vars.chainId + ); vars.superRegistryC.setDelay(86_400); /// @dev 17 deploy emergency queue @@ -622,7 +654,8 @@ abstract contract AbstractDeploySingle is Script { vars.lzImplementation = _readContract(chainNames[trueIndex], vars.chainId, "LayerzeroImplementation"); vars.hyperlaneImplementation = _readContract(chainNames[trueIndex], vars.chainId, "HyperlaneImplementation"); vars.wormholeImplementation = _readContract(chainNames[trueIndex], vars.chainId, "WormholeARImplementation"); - vars.wormholeSRImplementation = _readContract(chainNames[trueIndex], vars.chainId, "WormholeSRImplementation"); + //vars.wormholeSRImplementation = _readContract(chainNames[trueIndex], vars.chainId, + // "WormholeSRImplementation"); vars.superRegistry = _readContract(chainNames[trueIndex], vars.chainId, "SuperRegistry"); vars.paymentHelper = _readContract(chainNames[trueIndex], vars.chainId, "PaymentHelper"); vars.superRegistryC = SuperRegistry(vars.superRegistry); @@ -675,8 +708,9 @@ abstract contract AbstractDeploySingle is Script { SuperRBAC srbac = SuperRBAC(payable(_readContract(chainNames[trueIndex], vars.chainId, "SuperRBAC"))); bytes32 protocolAdminRole = srbac.PROTOCOL_ADMIN_ROLE(); bytes32 emergencyAdminRole = srbac.EMERGENCY_ADMIN_ROLE(); - srbac.grantRole(protocolAdminRole, multiSigAddress); - srbac.grantRole(emergencyAdminRole, multiSigAddress); + + srbac.grantRole(protocolAdminRole, PROTOCOL_ADMINS[trueIndex]); + srbac.grantRole(emergencyAdminRole, EMERGENCY_ADMIN); srbac.revokeRole(emergencyAdminRole, ownerAddress); srbac.revokeRole(protocolAdminRole, ownerAddress); @@ -706,7 +740,8 @@ abstract contract AbstractDeploySingle is Script { vars.lzImplementation = _readContract(chainNames[trueIndex], vars.chainId, "LayerzeroImplementation"); vars.hyperlaneImplementation = _readContract(chainNames[trueIndex], vars.chainId, "HyperlaneImplementation"); vars.wormholeImplementation = _readContract(chainNames[trueIndex], vars.chainId, "WormholeARImplementation"); - vars.wormholeSRImplementation = _readContract(chainNames[trueIndex], vars.chainId, "WormholeSRImplementation"); + //vars.wormholeSRImplementation = _readContract(chainNames[trueIndex], vars.chainId, + // "WormholeSRImplementation"); vars.superRegistry = _readContract(chainNames[trueIndex], vars.chainId, "SuperRegistry"); vars.paymentHelper = _readContract(chainNames[trueIndex], vars.chainId, "PaymentHelper"); vars.superRegistryC = SuperRegistry(payable(vars.superRegistry)); @@ -774,8 +809,10 @@ abstract contract AbstractDeploySingle is Script { _readContract(chainNames[vars.dstTrueIndex], vars.dstChainId, "HyperlaneImplementation"); vars.dstWormholeARImplementation = _readContract(chainNames[vars.dstTrueIndex], vars.dstChainId, "WormholeARImplementation"); + /* vars.dstWormholeSRImplementation = _readContract(chainNames[vars.dstTrueIndex], vars.dstChainId, "WormholeSRImplementation"); + */ LayerzeroImplementation(payable(vars.lzImplementation)).setTrustedRemote( vars.dstLzChainId, abi.encodePacked(vars.dstLzImplementation, vars.lzImplementation) ); @@ -806,6 +843,7 @@ abstract contract AbstractDeploySingle is Script { vars.dstChainId, vars.dstWormholeChainId ); + /* WormholeSRImplementation(payable(vars.wormholeSRImplementation)).setChainId( vars.dstChainId, vars.dstWormholeChainId ); @@ -814,7 +852,8 @@ abstract contract AbstractDeploySingle is Script { vars.dstWormholeChainId, vars.dstWormholeSRImplementation ); - /// @dev FIXME missing attribution of WORMHOLE_VAA_RELAYER_ROLE + /// @dev FIXME missing attribution of WORMHOLE_VAA_RELAYER_ROLE + */ SuperRegistry(payable(vars.superRegistry)).setRequiredMessagingQuorum(vars.dstChainId, 1); @@ -883,17 +922,21 @@ abstract contract AbstractDeploySingle is Script { vars.dstChainId ); + /* vars.superRegistryC.setAddress( vars.superRegistryC.TIMELOCK_STATE_REGISTRY(), _readContract(chainNames[vars.dstTrueIndex], vars.dstChainId, "TimelockStateRegistry"), vars.dstChainId ); + */ + /* vars.superRegistryC.setAddress( vars.superRegistryC.BROADCAST_REGISTRY(), _readContract(chainNames[vars.dstTrueIndex], vars.dstChainId, "BroadcastRegistry"), vars.dstChainId ); + */ vars.superRegistryC.setAddress( vars.superRegistryC.SUPER_POSITIONS(), @@ -929,20 +972,30 @@ abstract contract AbstractDeploySingle is Script { vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_UPDATER(), 0xaEbb4b9f7e16BEE2a0963569a5E33eE10E478a5f, vars.dstChainId ); + /// @dev FIXME setting this temporarily to EMERGENCY_ADMIN as we are not using it in this release + + vars.superRegistryC.setAddress( + vars.superRegistryC.BROADCAST_REGISTRY_PROCESSOR(), EMERGENCY_ADMIN, vars.dstChainId + ); + /// @dev FIXME setting this temporarily to EMERGENCY_ADMIN as we are not using it in this release + vars.superRegistryC.setAddress( - vars.superRegistryC.BROADCAST_REGISTRY_PROCESSOR(), ownerAddress, vars.dstChainId + vars.superRegistryC.TIMELOCK_REGISTRY_PROCESSOR(), EMERGENCY_ADMIN, vars.dstChainId ); - vars.superRegistryC.setAddress(vars.superRegistryC.TIMELOCK_REGISTRY_PROCESSOR(), ownerAddress, vars.dstChainId); vars.superRegistryC.setAddress( vars.superRegistryC.CORE_REGISTRY_RESCUER(), 0x90ed07A867bDb6a73565D7abBc7434Dd810Fafc5, vars.dstChainId ); - vars.superRegistryC.setAddress(vars.superRegistryC.CORE_REGISTRY_DISPUTER(), ownerAddress, vars.dstChainId); + vars.superRegistryC.setAddress( + vars.superRegistryC.CORE_REGISTRY_DISPUTER(), 0x7c9c8C0A9aA5D8a2c2e6C746641117Cc9591296a, vars.dstChainId + ); vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), 0x1666660D2F506e754CB5c8E21BDedC7DdEc6Be1C, vars.dstChainId ); - vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_RECEIVER(), ownerAddress, vars.dstChainId); + vars.superRegistryC.setAddress( + vars.superRegistryC.SUPERFORM_RECEIVER(), 0x1a6805487322565202848f239C1B5bC32303C2FE, vars.dstChainId + ); } function _preDeploymentSetup() internal { @@ -953,51 +1006,33 @@ abstract contract AbstractDeploySingle is Script { lzEndpointsStorage[POLY] = POLY_lzEndpoint; lzEndpointsStorage[ARBI] = ARBI_lzEndpoint; lzEndpointsStorage[OP] = OP_lzEndpoint; - lzEndpointsStorage[FTM] = FTM_lzEndpoint; lzEndpointsStorage[BASE] = BASE_lzEndpoint; lzEndpointsStorage[GNOSIS] = GNOSIS_lzEndpoint; mapping(uint64 chainId => address[] bridgeAddresses) storage bridgeAddresses = BRIDGE_ADDRESSES; - bridgeAddresses[ETH] = [ - 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0, - 0x2ddf16BA6d0180e5357d5e170eF1917a01b41fc0 - ]; - bridgeAddresses[BSC] = [ - 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0, - 0xd286595d2e3D879596FAB51f83A702D10a6db27b + bridgeAddresses[ETH] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0 + //0x2ddf16BA6d0180e5357d5e170eF1917a01b41fc0 ]; - bridgeAddresses[AVAX] = [ - 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0x2b42AFFD4b7C14d9B7C2579229495c052672Ccd3, - 0xbDf50eAe568ECef74796ed6022a0d453e8432410 + bridgeAddresses[BSC] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0 + //0xd286595d2e3D879596FAB51f83A702D10a6db27b ]; - bridgeAddresses[POLY] = [ - 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0, - 0x2ddf16BA6d0180e5357d5e170eF1917a01b41fc0 + bridgeAddresses[AVAX] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, 0x2b42AFFD4b7C14d9B7C2579229495c052672Ccd3 + //0xbDf50eAe568ECef74796ed6022a0d453e8432410 ]; - bridgeAddresses[ARBI] = [ - 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0, - 0xaa3d9fA3aB930aE635b001d00C612aa5b14d750e + bridgeAddresses[POLY] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0 + //0x2ddf16BA6d0180e5357d5e170eF1917a01b41fc0 ]; - bridgeAddresses[OP] = [ - 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0, - 0xbDf50eAe568ECef74796ed6022a0d453e8432410 + bridgeAddresses[ARBI] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0 + //0xaa3d9fA3aB930aE635b001d00C612aa5b14d750e ]; - bridgeAddresses[FTM] = [ - 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0, - 0x957301825Dc21d4A92919C9E72dC9E6C6a29e7f8 + bridgeAddresses[OP] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0 + //0xbDf50eAe568ECef74796ed6022a0d453e8432410 ]; - bridgeAddresses[BASE] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, address(0), address(0)]; + bridgeAddresses[BASE] = [0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, address(0)]; bridgeAddresses[GNOSIS] = [ 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE, - 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0, - 0x565810cbfa3Cf1390963E5aFa2fB953795686339 + 0xc30141B657f4216252dc59Af2e7CdB9D8792e1B0 + //0x565810cbfa3Cf1390963E5aFa2fB953795686339 ]; /// price feeds on all chains diff --git a/script/Mainnet.Deploy.NewChain.s.sol b/script/Mainnet.Deploy.NewChain.s.sol index 537a93edf..e470c0910 100644 --- a/script/Mainnet.Deploy.NewChain.s.sol +++ b/script/Mainnet.Deploy.NewChain.s.sol @@ -20,9 +20,9 @@ contract MainnetDeployNewChain is AbstractDeploySingle { uint64[] FINAL_DEPLOYED_CHAINS = [ETH, AVAX, GNOSIS]; */ - uint64[] TARGET_DEPLOYMENT_CHAINS = [BSC]; - uint64[] FINAL_DEPLOYED_CHAINS = [BSC, POLY, AVAX, GNOSIS]; - uint64[] PREVIOUS_DEPLOYMENT = [POLY, AVAX, GNOSIS]; + uint64[] TARGET_DEPLOYMENT_CHAINS = [BASE]; + uint64[] FINAL_DEPLOYED_CHAINS = [BASE, BSC, POLY, AVAX]; + uint64[] PREVIOUS_DEPLOYMENT = [BSC, POLY, AVAX]; ///@dev ORIGINAL SALT bytes32 constant salt = "CANTINA_DEPLOYMENT_4"; diff --git a/script/Tenderly.Deploy.s.sol b/script/Tenderly.Deploy.s.sol index fc76a7b1d..5100760a4 100644 --- a/script/Tenderly.Deploy.s.sol +++ b/script/Tenderly.Deploy.s.sol @@ -8,7 +8,7 @@ contract TenderlyDeploy is AbstractDeploySingle { SELECT CHAIN IDS TO DEPLOY HERE //////////////////////////////////////////////////////////////*/ - uint64[] TARGET_DEPLOYMENT_CHAINS = [OP, POLY, ARBI]; + uint64[] TARGET_DEPLOYMENT_CHAINS = [ETH, OP, ARBI]; /// @notice The main stage 1 script entrypoint function deployStage1(uint256 selectedChainIndex, uint256 salt) external { diff --git a/script/output/1/Ethereum-latest.json b/script/output/1/Ethereum-latest.json index e69de29bb..41e0de0fc 100644 --- a/script/output/1/Ethereum-latest.json +++ b/script/output/1/Ethereum-latest.json @@ -0,0 +1,19 @@ +{ + "CoreStateRegistry": "0x6eB91a9d418F665BD1407baBD6F478AB36394e84", + "DstSwapper": "0xDeEC5c1b762a41E9F92E41b079fA3334E0a7f774", + "ERC4626Form": "0x4fBbD6b886b2bFAbc028Bc50250EEb79E174Fb3d", + "EmergencyQueue": "0x729982cc4Ac4bC5bdDC9177025d6d81520aB20cd", + "HyperlaneImplementation": "0x6c0d942f5FBCF94Af9c58d8840bA3700CF45784a", + "LayerzeroImplementation": "0x9de423671Dc1e5f77f172374C4f0Bdc744F2CED2", + "LiFiValidator": "0x3549646aa62e372b7b04264F89624929e1b16d92", + "PayMaster": "0x2a9eF1519b97e8616d67E28fae493ceDFa3b801C", + "PayloadHelper": "0x702E94ff55ae09Be1E923393b5637c2D5c69F54f", + "PaymentHelper": "0xAe8af9cFd939d0eE0f7b354ab774A75Df539Af08", + "SocketValidator": "0x2CF947a38ec484eE1544A6112a1e80e65e7E4f21", + "SuperPositions": "0x400360FdDe552189Df6f4b616cB35fbA069FCE2B", + "SuperRBAC": "0xeE3294bcb48d8db603E0eB80F5e786560Db3eec5", + "SuperRegistry": "0x75Aad21aE992ae703A75343Ce22563Dd604c65d8", + "SuperformFactory": "0xB00943Be26BC510753153bBA687903B84b2EB167", + "SuperformRouter": "0x83D25df8e3A3c2e888A8392c03DA5bC9ABB8D36a", + "WormholeARImplementation": "0x425974B27f4f9F81E11496924D8d09B73dF2Fb96" +} \ No newline at end of file diff --git a/script/output/56/Binance-latest.json b/script/output/56/Binance-latest.json index 16602521e..41e0de0fc 100644 --- a/script/output/56/Binance-latest.json +++ b/script/output/56/Binance-latest.json @@ -1,25 +1,19 @@ { - "BroadcastRegistry": "0x91A4a6E08401FFC5Cf155d7d6A7234AA0302B160", - "CoreStateRegistry": "0xC525e2EE88E0014F46cb031C33c5148A153108eB", - "DstSwapper": "0x363A6294897577522795c80447f2f2829DCc85c4", - "ERC4626Form": "0x3bfEe78d526063e0207B1a55fD4B284306882247", - "ERC4626KYCDaoForm": "0xd72Ec34384b1ba5bCeC852Fa88420D0f6F90363c", - "ERC4626TimelockForm": "0x87D539863EaB9f3CB99B405929464f6aAb77e81B", - "EmergencyQueue": "0x8Ef837576f37C29BAcd1efb2Eb0ddAadB01DA189", - "HyperlaneImplementation": "0x922d821ddfA8958890d69053CA79a7E619A2790E", - "LayerzeroImplementation": "0x22adbC6BBb1A8C4eFB579268772E7516869E2Cc6", - "LiFiValidator": "0xe1E7b5011E0DcFb823916E8a91DBA9eC383E82C2", - "PayMaster": "0x917455CE06FCD3acFB697781D5E937e1ABcb7694", - "PayloadHelper": "0x3fF04DB7C5D74A544bC76BFabE37732196d56e34", - "PaymentHelper": "0xa4498fa6b5f964a84432Fa007B04255610E21992", - "SocketOneInchValidator": "0xceb161DAC215389B44FE15634A3e207bC886fa09", - "SocketValidator": "0x156889A11Ed41fdAAF3da7394D5cF577bb69eaC4", - "SuperPositions": "0xD240a9674E9a306009071Bd60966F66eA33341Fd", - "SuperRBAC": "0x3487eD8b15c93138573CDC1226CC3ecBb4CD31af", - "SuperRegistry": "0xB0bBFC88896c1a218fbAFab6C8dcf43eD587Ad63", - "SuperformFactory": "0x7791026F1770780c00cEe224F9d0B61c962E9fF8", - "SuperformRouter": "0x51d0a7a59F4e54a273FCbA4Fd4ea9E647e785d95", - "TimelockStateRegistry": "0x1cbf6A3B019dAef506e13bf6A353e3C47Cd8250c", - "WormholeARImplementation": "0x6f1d34A20C0d62A4Fc2eCA0919Fb6fDD73F37428", - "WormholeSRImplementation": "0x63a62c7AF0Ed62C394420dBC7Aa0f803236886aC" + "CoreStateRegistry": "0x6eB91a9d418F665BD1407baBD6F478AB36394e84", + "DstSwapper": "0xDeEC5c1b762a41E9F92E41b079fA3334E0a7f774", + "ERC4626Form": "0x4fBbD6b886b2bFAbc028Bc50250EEb79E174Fb3d", + "EmergencyQueue": "0x729982cc4Ac4bC5bdDC9177025d6d81520aB20cd", + "HyperlaneImplementation": "0x6c0d942f5FBCF94Af9c58d8840bA3700CF45784a", + "LayerzeroImplementation": "0x9de423671Dc1e5f77f172374C4f0Bdc744F2CED2", + "LiFiValidator": "0x3549646aa62e372b7b04264F89624929e1b16d92", + "PayMaster": "0x2a9eF1519b97e8616d67E28fae493ceDFa3b801C", + "PayloadHelper": "0x702E94ff55ae09Be1E923393b5637c2D5c69F54f", + "PaymentHelper": "0xAe8af9cFd939d0eE0f7b354ab774A75Df539Af08", + "SocketValidator": "0x2CF947a38ec484eE1544A6112a1e80e65e7E4f21", + "SuperPositions": "0x400360FdDe552189Df6f4b616cB35fbA069FCE2B", + "SuperRBAC": "0xeE3294bcb48d8db603E0eB80F5e786560Db3eec5", + "SuperRegistry": "0x75Aad21aE992ae703A75343Ce22563Dd604c65d8", + "SuperformFactory": "0xB00943Be26BC510753153bBA687903B84b2EB167", + "SuperformRouter": "0x83D25df8e3A3c2e888A8392c03DA5bC9ABB8D36a", + "WormholeARImplementation": "0x425974B27f4f9F81E11496924D8d09B73dF2Fb96" } \ No newline at end of file diff --git a/utils/run_script_mainnet.sh b/utils/run_script_mainnet.sh index 5860b8be4..7acafaa8b 100755 --- a/utils/run_script_mainnet.sh +++ b/utils/run_script_mainnet.sh @@ -33,18 +33,18 @@ wait FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage2(uint256)" 2 --rpc-url $AVALANCHE_RPC_URL --broadcast --slow --sender 0x48aB8AdF869Ba9902Ad483FB1Ca2eFDAb6eabe92 -#wait +wait -#echo Running Stage 3: ... +echo Running Stage 3: ... -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 0 --rpc-url $BSC_RPC_URL --broadcast --slow --sender 0x48aB8AdF869Ba9902Ad483FB1Ca2eFDAb6eabe92 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 0 --rpc-url $BSC_RPC_URL --broadcast --slow --sender 0x48aB8AdF869Ba9902Ad483FB1Ca2eFDAb6eabe92 -#wait +wait -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 1 --rpc-url $POLYGON_RPC_URL --broadcast --slow --sender 0x48aB8AdF869Ba9902Ad483FB1Ca2eFDAb6eabe92 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 1 --rpc-url $POLYGON_RPC_URL --broadcast --slow --sender 0x48aB8AdF869Ba9902Ad483FB1Ca2eFDAb6eabe92 -#wait +wait -#FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 2 --rpc-url $AVALANCHE_RPC_URL --broadcast --slow --sender 0x48aB8AdF869Ba9902Ad483FB1Ca2eFDAb6eabe92 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.s.sol:MainnetDeploy --sig "deployStage3(uint256)" 2 --rpc-url $AVALANCHE_RPC_URL --broadcast --slow --sender 0x48aB8AdF869Ba9902Ad483FB1Ca2eFDAb6eabe92 diff --git a/utils/run_script_mainnet_new_chain.sh b/utils/run_script_mainnet_new_chain.sh index 18ef8c537..7040ad7f0 100755 --- a/utils/run_script_mainnet_new_chain.sh +++ b/utils/run_script_mainnet_new_chain.sh @@ -3,6 +3,7 @@ # Read the RPC URL source .env +# Example here: deployed chains initially were POLY, AVAX and GNOSIS. Now adding BSC # Run the script echo Running Stage 1: ... diff --git a/utils/run_script_tenderly.sh b/utils/run_script_tenderly.sh index 6d5ae74e4..1ab854a65 100755 --- a/utils/run_script_tenderly.sh +++ b/utils/run_script_tenderly.sh @@ -3,19 +3,22 @@ # Read the RPC URL source .env +#BSC_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +#POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +#AVAX_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template avaxdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +ETHEREUM_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template ethereumdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) OPTIMISM_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template optimismdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) -POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) ARBITRUM_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template arbitrumdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) # Run the script echo Running Stage 1: ... -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 0 1337 --rpc-url $OPTIMISM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 0 1337 --rpc-url $ETHEREUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 1 1337 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage1(uint256,uint256)" 1 1337 --rpc-url $OPTIMISM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait @@ -26,27 +29,27 @@ wait echo Running Stage 2: ... -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 0 --rpc-url $OPTIMISM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 0 --rpc-url $ETHEREUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 1 --rpc-url $OPTIMISM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage2(uint256)" 2 --rpc-url $ARBITRUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 -#echo Running Stage 3: ... +echo Running Stage 3: ... -#wait +wait -#FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 0 --rpc-url $ETHEREUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 -#wait +wait -#FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 1 --rpc-url $OPTIMISM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 -#wait +wait -#FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 2 --rpc-url $BASE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Tenderly.Deploy.s.sol:TenderlyDeploy --sig "deployStage3(uint256)" 2 --rpc-url $ARBITRUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 diff --git a/utils/run_script_tenderly_new_chain.sh b/utils/run_script_tenderly_new_chain.sh index d307395f6..39d8994ba 100755 --- a/utils/run_script_tenderly_new_chain.sh +++ b/utils/run_script_tenderly_new_chain.sh @@ -3,6 +3,13 @@ # Read the RPC URL source .env +BASE_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template basevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) + +BSC_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template bscdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +POLYGON_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template polygondevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) +AVAX_DEVNET=$(tenderly devnet spawn-rpc --project $TENDERLY_PROJECT_SLUG --template avaxdevnet --account $TENDERLY_ACCOUNT_ID --access_key $TENDERLY_ACCESS_KEY --return-url) + + # Run the script echo Running Stage 1: ... @@ -28,12 +35,12 @@ wait echo Configuring new chain on Stage 2 of previous chains: ... -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.NewChain.s.sol:MainnetDeployNewChain --sig "configurePreviousChains(uint256)" 0 --rpc-url $ETHEREUM_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.NewChain.s.sol:MainnetDeployNewChain --sig "configurePreviousChains(uint256)" 0 --rpc-url $BSC_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.NewChain.s.sol:MainnetDeployNewChain --sig "configurePreviousChains(uint256)" 1 --rpc-url $AVALANCHE_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.NewChain.s.sol:MainnetDeployNewChain --sig "configurePreviousChains(uint256)" 1 --rpc-url $POLYGON_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 wait -FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.NewChain.s.sol:MainnetDeployNewChain --sig "configurePreviousChains(uint256)" 2 --rpc-url $GNOSIS_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 +FOUNDRY_PROFILE=default forge script script/Mainnet.Deploy.NewChain.s.sol:MainnetDeployNewChain --sig "configurePreviousChains(uint256)" 2 --rpc-url $AVAX_DEVNET --broadcast --unlocked --sender 0x0000000000000000000000000000000000000000 From f67a5022257a31b57155d02872f7695d82137632 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:00:12 -0600 Subject: [PATCH 189/210] chore: fix stack too deep --- src/BaseRouterImplementation.sol | 149 ++++++++++++++++--------------- 1 file changed, 78 insertions(+), 71 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index c41dfb756..aafd9df64 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -48,16 +48,31 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou bool deposit; } + struct DirectDepositArgs { + address superform; + uint256 payloadId; + uint256 superformId; + uint256 amount; + uint256 outputAmount; + uint256 maxSlippage; + bool retain4626; + LiqRequest liqData; + address receiverAddress; + bytes extraFormData; + uint256 msgValue; + address srcSender; + } + struct SingleDepositLocalVars { address superform; uint256 shares; } - struct MultiDepositArgs { + struct SingleDepositArgs { address srcSender; bytes permit2data; address receiverAddressSP; - InitMultiVaultData vaultData; + InitSingleVaultData vaultData; } struct MultiDepositLocalVars { @@ -67,6 +82,13 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou bool[] mints; } + struct MultiDepositArgs { + address srcSender; + bytes permit2data; + address receiverAddressSP; + InitMultiVaultData vaultData; + } + struct SingleTokenForwardLocalVars { IERC20 token; uint256 txDataLength; @@ -138,7 +160,9 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev same chain action & forward residual payment to Paymaster _directSingleDeposit( - msg.sender, req_.superformData.permit2data, req_.superformData.receiverAddressSP, vaultData + SingleDepositArgs( + msg.sender, req_.superformData.permit2data, req_.superformData.receiverAddressSP, vaultData + ) ); emit Completed(); } @@ -593,81 +617,63 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ////////////////////////////////////////////////////////////// /// @notice fulfils the final stage of same chain deposit action - function _directDeposit( - address superform_, - uint256 payloadId_, - uint256 superformId_, - uint256 amount_, - uint256 outputAmount_, - uint256 maxSlippage_, - bool retain4626_, - LiqRequest memory liqData_, - address receiverAddress_, - bytes memory extraFormData_, - uint256 msgValue_, - address srcSender_ - ) + function _directDeposit(DirectDepositArgs memory args) internal virtual returns (uint256 shares) { - /// @dev deposits token to a given vault and mint vault positions directly through the form - shares = IBaseForm(superform_).directDepositIntoVault{ value: msgValue_ }( + // @dev deposits token to a given vault and mint vault positions directly through the form + shares = IBaseForm(args.superform).directDepositIntoVault{ value: args.msgValue }( InitSingleVaultData( - payloadId_, - superformId_, - amount_, - outputAmount_, - maxSlippage_, - liqData_, + args.payloadId, + args.superformId, + args.amount, + args.outputAmount, + args.maxSlippage, + args.liqData, false, - retain4626_, - receiverAddress_, - /// needed if user if keeping 4626 - extraFormData_ + args.retain4626, + args.receiverAddress, + // needed if user is keeping 4626 + args.extraFormData ), - srcSender_ + args.srcSender ); } + /// @notice deposits to single vault on the same chain /// @dev calls `_directDeposit` - function _directSingleDeposit( - address srcSender_, - bytes memory permit2data_, - address receiverAddressSP_, - InitSingleVaultData memory vaultData_ - ) - internal - virtual - { + function _directSingleDeposit(SingleDepositArgs memory args_) internal virtual { SingleDepositLocalVars memory v; - /// @dev decode superforms - (v.superform,,) = vaultData_.superformId.getSuperform(); + // @dev decode superforms + (v.superform,,) = args_.vaultData.superformId.getSuperform(); - _singleVaultTokenForward(srcSender_, v.superform, permit2data_, vaultData_, false); + _singleVaultTokenForward(args_.srcSender, v.superform, args_.permit2data, args_.vaultData, false); - /// @dev deposits token to a given vault and mint vault positions. + // @dev deposits token to a given vault and mint vault positions. v.shares = _directDeposit( - v.superform, - vaultData_.payloadId, - vaultData_.superformId, - vaultData_.amount, - vaultData_.outputAmount, - vaultData_.maxSlippage, - vaultData_.retain4626, - vaultData_.liqData, - vaultData_.receiverAddress, - vaultData_.extraFormData, - vaultData_.liqData.nativeAmount, - srcSender_ + DirectDepositArgs( + v.superform, + args_.vaultData.payloadId, + args_.vaultData.superformId, + args_.vaultData.amount, + args_.vaultData.outputAmount, + args_.vaultData.maxSlippage, + args_.vaultData.retain4626, + args_.vaultData.liqData, + args_.vaultData.receiverAddress, + args_.vaultData.extraFormData, + args_.vaultData.liqData.nativeAmount, + args_.srcSender + ) ); - if (v.shares != 0 && !vaultData_.retain4626) { - /// @dev mint super positions at the end of the deposit action if user doesn't retain 4626 + if (v.shares != 0 && !args_.vaultData.retain4626) { + // @dev mint super positions at the end of the deposit action if user doesn't retain 4626 ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintSingle( - receiverAddressSP_, vaultData_.superformId, v.shares + args_.receiverAddressSP, args_.vaultData.superformId, v.shares ); } } @@ -689,22 +695,23 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou for (uint256 i; i < v.len; ++i) { /// @dev deposits token to a given vault and mint vault positions. v.shares[i] = _directDeposit( - v.superforms[i], - args_.vaultData.payloadId, - args_.vaultData.superformIds[i], - args_.vaultData.amounts[i], - args_.vaultData.outputAmounts[i], - args_.vaultData.maxSlippages[i], - args_.vaultData.retain4626s[i], - args_.vaultData.liqData[i], - args_.vaultData.receiverAddress, - args_.vaultData.extraFormData, - args_.vaultData.liqData[i].nativeAmount, - args_.srcSender + DirectDepositArgs( + v.superforms[i], + args_.vaultData.payloadId, + args_.vaultData.superformIds[i], + args_.vaultData.amounts[i], + args_.vaultData.outputAmounts[i], + args_.vaultData.maxSlippages[i], + args_.vaultData.retain4626s[i], + args_.vaultData.liqData[i], + args_.vaultData.receiverAddress, + args_.vaultData.extraFormData, + args_.vaultData.liqData[i].nativeAmount, + args_.srcSender + ) ); /// @dev if retain4626 is set to True, set the amount of SuperPositions to mint to 0 - if (v.shares[i] != 0 && args_.vaultData.retain4626s[i]) { v.shares[i] = 0; } From 1cdc3d87dc249c2e53983daed1b3bd33eae31435 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:10:31 -0600 Subject: [PATCH 190/210] chore: fixing dstswapper stack too deep --- .../crosschain-liquidity/DstSwapper.t.sol | 94 ++++++++++--------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index 46211d194..244fae46a 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -820,33 +820,33 @@ contract DstSwapperTest is ProtocolActions { LiqRequest[] memory liq = new LiqRequest[](2); liq[0] = LiqRequest("", getContract(OP, "DAI"), interimToken_, 1, OP, 0); liq[1] = LiqRequest("", getContract(OP, "DAI"), interimToken_, 1, OP, 0); - CoreStateRegistry(coreStateRegistry).receivePayload( - ETH, + + InitMultiVaultData memory initMultiVaultData = InitMultiVaultData( + 1, + superformIds, + amounts, + outputAmounts, + maxSlippages, + liq, + hasDstSwaps, + new bool[](2), + users[0], + bytes("") + ); + + bytes memory encodedData = abi.encode( + AMBMessage( + DataLib.packTxInfo( + uint8(TransactionType.DEPOSIT), uint8(CallbackType.INIT), uint8(1), 1, users[0], ETH + ), abi.encode( - AMBMessage( - DataLib.packTxInfo( - uint8(TransactionType.DEPOSIT), uint8(CallbackType.INIT), uint8(1), 1, users[0], ETH - ), - abi.encode( - new uint8[](1), - abi.encode( - InitMultiVaultData( - 1, - superformIds, - amounts, - outputAmounts, - maxSlippages, - liq, - hasDstSwaps, - new bool[](2), - users[0], - bytes("") - ) - ) - ) + new uint8[](1), + abi.encode(initMultiVaultData) ) ) ); + + CoreStateRegistry(coreStateRegistry).receivePayload(ETH, encodedData); } function _simulatePartialMultiVaultExistingPayloadOnOP( @@ -951,31 +951,33 @@ contract DstSwapperTest is ProtocolActions { uint8[] memory ambIds_ = new uint8[](1); ambIds_[0] = 1; - vm.prank(getContract(ETH, "LayerzeroImplementation")); - CoreStateRegistry(coreStateRegistry).receivePayload( - POLY, - abi.encode( - AMBMessage( - DataLib.packTxInfo(1, 0, 1, 1, address(420), uint64(137)), - abi.encode( - ambIds_, - abi.encode( - InitMultiVaultData( - 1, - superformIds, - amounts, - outputAmounts, - new uint256[](2), - liq, - hasDstSwaps, - new bool[](2), - receiverAddress, - bytes("") - ) - ) - ) + + InitMultiVaultData memory initMultiVaultData = InitMultiVaultData( + 1, + superformIds, + amounts, + outputAmounts, + new uint256[](2), // Assuming you want to initialize this with default values + liq, + hasDstSwaps, + new bool[](2), // Assuming you want to initialize this with default values + receiverAddress, + bytes("") + ); + + // Prepare the encoded data for receivePayload + bytes memory encodedData = abi.encode( + AMBMessage( + DataLib.packTxInfo(1, 0, 1, 1, address(420), uint64(137)), + abi.encode( + new uint8[](1), // ambIds_ + abi.encode(initMultiVaultData) ) ) ); + + // Call receivePayload with the prepared data + vm.prank(getContract(ETH, "LayerzeroImplementation")); + CoreStateRegistry(coreStateRegistry).receivePayload(POLY, encodedData); } } From 067d10f0632c9cfeab48a76a3752f52bf387b8ba Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:25:46 -0600 Subject: [PATCH 191/210] chore: not too deep now mfer --- .../crosschain-liquidity/DstSwapper.t.sol | 8 ++-- .../superform-router/SuperformRouter.t.sol | 42 ++++--------------- 2 files changed, 12 insertions(+), 38 deletions(-) diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index 244fae46a..08bc0bc7a 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -951,21 +951,20 @@ contract DstSwapperTest is ProtocolActions { uint8[] memory ambIds_ = new uint8[](1); ambIds_[0] = 1; - + InitMultiVaultData memory initMultiVaultData = InitMultiVaultData( 1, superformIds, amounts, outputAmounts, - new uint256[](2), // Assuming you want to initialize this with default values + new uint256[](2), liq, hasDstSwaps, - new bool[](2), // Assuming you want to initialize this with default values + new bool[](2), receiverAddress, bytes("") ); - // Prepare the encoded data for receivePayload bytes memory encodedData = abi.encode( AMBMessage( DataLib.packTxInfo(1, 0, 1, 1, address(420), uint64(137)), @@ -976,7 +975,6 @@ contract DstSwapperTest is ProtocolActions { ) ); - // Call receivePayload with the prepared data vm.prank(getContract(ETH, "LayerzeroImplementation")); CoreStateRegistry(coreStateRegistry).receivePayload(POLY, encodedData); } diff --git a/test/unit/superform-router/SuperformRouter.t.sol b/test/unit/superform-router/SuperformRouter.t.sol index 72d147931..aeee8c1f0 100644 --- a/test/unit/superform-router/SuperformRouter.t.sol +++ b/test/unit/superform-router/SuperformRouter.t.sol @@ -975,10 +975,6 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; - uint256[] memory outputAmounts = new uint256[](2); - outputAmounts[0] = 1e18; - outputAmounts[1] = 1e18; - uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 1000; maxSlippages[1] = 1000; @@ -994,7 +990,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, - outputAmounts, + amounts, maxSlippages, liqReqs, "", @@ -1004,6 +1000,7 @@ contract SuperformRouterTest is ProtocolActions { receiverAddress, "" ); + uint8[] memory ambIds = new uint8[](2); ambIds[0] = 1; ambIds[1] = 2; @@ -1044,10 +1041,6 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](0); - uint256[] memory outputAmounts = new uint256[](2); - outputAmounts[0] = 1e18; - outputAmounts[1] = 1e18; - uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 1000; maxSlippages[1] = 1000; @@ -1063,7 +1056,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, - outputAmounts, + maxSlippages, maxSlippages, liqReqs, "", @@ -1111,16 +1104,12 @@ contract SuperformRouterTest is ProtocolActions { superformIds[0] = superformId1; superformIds[1] = superformId2; - uint256[] memory amounts = new uint256[](0); + uint256[] memory amounts = new uint256[](2); amounts[0] = 1e18; amounts[1] = 1e18; uint256[] memory outputAmounts = new uint256[](0); - uint256[] memory maxSlippages = new uint256[](2); - maxSlippages[0] = 1000; - maxSlippages[1] = 1000; - bool[] memory hasDstSwaps = new bool[](2); bool[] memory retain4626s = new bool[](2); @@ -1133,7 +1122,7 @@ contract SuperformRouterTest is ProtocolActions { superformIds, amounts, outputAmounts, - maxSlippages, + amounts, liqReqs, "", hasDstSwaps, @@ -1184,10 +1173,6 @@ contract SuperformRouterTest is ProtocolActions { amounts[0] = 1e18; amounts[1] = 1e18; - uint256[] memory outputAmounts = new uint256[](2); - outputAmounts[0] = 1e18; - outputAmounts[1] = 1e18; - uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 10_001; maxSlippages[1] = 99_999; @@ -1203,7 +1188,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, - outputAmounts, + amounts, maxSlippages, liqReqs, "", @@ -1361,9 +1346,6 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; - uint256[] memory outputAmounts = new uint256[](1); - outputAmounts[0] = 1e18; - uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -1381,7 +1363,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, - outputAmounts, + amounts, maxSlippages, liqReq, "", @@ -1427,9 +1409,6 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; - uint256[] memory outputAmounts = new uint256[](1); - outputAmounts[0] = 1e18; - uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -1447,7 +1426,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, - outputAmounts, + amounts, maxSlippages, liqReq, "", @@ -1506,9 +1485,6 @@ contract SuperformRouterTest is ProtocolActions { uint256[] memory amounts = new uint256[](1); amounts[0] = 1e18; - uint256[] memory outputAmounts = new uint256[](1); - outputAmounts[0] = 1e18; - uint256[] memory maxSlippages = new uint256[](1); maxSlippages[0] = 100; @@ -1525,7 +1501,7 @@ contract SuperformRouterTest is ProtocolActions { MultiVaultSFData memory data = MultiVaultSFData( superformIds, amounts, - outputAmounts, + amounts, maxSlippages, liqReq, "", From cd42cbb3376650a46ad58080d1b336f33cce055b Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:35:12 -0600 Subject: [PATCH 192/210] chore: cross multiply timelock --- src/forms/ERC4626TimelockForm.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index a42e21037..f202e06c8 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -103,10 +103,11 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { assets = v.redeem(p_.data.amount, vars.receiver, address(this)); uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (assets < ((p_.data.outputAmount * (ENTIRE_SLIPPAGE - p_.data.maxSlippage)) / ENTIRE_SLIPPAGE)) + (assets * ENTIRE_SLIPPAGE > p_.data.outputAmount * (ENTIRE_SLIPPAGE - p_.data.maxSlippage)) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } + if (assets == 0) revert Error.WITHDRAW_ZERO_COLLATERAL(); /// @dev validate and dispatches the tokens From 16e708f3aede22de6f6ccf5c64b062af45fd1629 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 27 Dec 2023 01:09:29 +0000 Subject: [PATCH 193/210] test: fix majority of tests --- lib/ERC1155A | 2 +- script/output/10/Optimism-latest.json | 19 +++++++++ script/output/42161/Arbitrum-latest.json | 19 +++++++++ src/BaseRouterImplementation.sol | 27 +++++++----- src/forms/ERC4626FormImplementation.sol | 41 +++++++++++-------- src/forms/ERC4626TimelockForm.sol | 7 +++- src/types/DataTypes.sol | 4 +- .../0000.1200.TokenInputNoSlippageAMB12.sol | 6 +-- .../4626.Native.Slippage.AMB23.t.sol | 2 +- .../0.TokenInput.NoSlippage.AMB13.sol | 2 +- .../02.NativeInput.NoSlippage.AMB12.sol | 2 +- .../superform-form.ERC4626Timelock.t.sol | 2 + .../superform-form.forwardDust.t.sol | 2 +- test/utils/BaseSetup.sol | 5 +-- test/utils/InvariantProtocolActions.sol | 14 +++++-- test/utils/ProtocolActions.sol | 17 ++++++-- 16 files changed, 122 insertions(+), 49 deletions(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index e7d53f306..f46fa5420 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 +Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 diff --git a/script/output/10/Optimism-latest.json b/script/output/10/Optimism-latest.json index e69de29bb..41e0de0fc 100644 --- a/script/output/10/Optimism-latest.json +++ b/script/output/10/Optimism-latest.json @@ -0,0 +1,19 @@ +{ + "CoreStateRegistry": "0x6eB91a9d418F665BD1407baBD6F478AB36394e84", + "DstSwapper": "0xDeEC5c1b762a41E9F92E41b079fA3334E0a7f774", + "ERC4626Form": "0x4fBbD6b886b2bFAbc028Bc50250EEb79E174Fb3d", + "EmergencyQueue": "0x729982cc4Ac4bC5bdDC9177025d6d81520aB20cd", + "HyperlaneImplementation": "0x6c0d942f5FBCF94Af9c58d8840bA3700CF45784a", + "LayerzeroImplementation": "0x9de423671Dc1e5f77f172374C4f0Bdc744F2CED2", + "LiFiValidator": "0x3549646aa62e372b7b04264F89624929e1b16d92", + "PayMaster": "0x2a9eF1519b97e8616d67E28fae493ceDFa3b801C", + "PayloadHelper": "0x702E94ff55ae09Be1E923393b5637c2D5c69F54f", + "PaymentHelper": "0xAe8af9cFd939d0eE0f7b354ab774A75Df539Af08", + "SocketValidator": "0x2CF947a38ec484eE1544A6112a1e80e65e7E4f21", + "SuperPositions": "0x400360FdDe552189Df6f4b616cB35fbA069FCE2B", + "SuperRBAC": "0xeE3294bcb48d8db603E0eB80F5e786560Db3eec5", + "SuperRegistry": "0x75Aad21aE992ae703A75343Ce22563Dd604c65d8", + "SuperformFactory": "0xB00943Be26BC510753153bBA687903B84b2EB167", + "SuperformRouter": "0x83D25df8e3A3c2e888A8392c03DA5bC9ABB8D36a", + "WormholeARImplementation": "0x425974B27f4f9F81E11496924D8d09B73dF2Fb96" +} \ No newline at end of file diff --git a/script/output/42161/Arbitrum-latest.json b/script/output/42161/Arbitrum-latest.json index e69de29bb..41e0de0fc 100644 --- a/script/output/42161/Arbitrum-latest.json +++ b/script/output/42161/Arbitrum-latest.json @@ -0,0 +1,19 @@ +{ + "CoreStateRegistry": "0x6eB91a9d418F665BD1407baBD6F478AB36394e84", + "DstSwapper": "0xDeEC5c1b762a41E9F92E41b079fA3334E0a7f774", + "ERC4626Form": "0x4fBbD6b886b2bFAbc028Bc50250EEb79E174Fb3d", + "EmergencyQueue": "0x729982cc4Ac4bC5bdDC9177025d6d81520aB20cd", + "HyperlaneImplementation": "0x6c0d942f5FBCF94Af9c58d8840bA3700CF45784a", + "LayerzeroImplementation": "0x9de423671Dc1e5f77f172374C4f0Bdc744F2CED2", + "LiFiValidator": "0x3549646aa62e372b7b04264F89624929e1b16d92", + "PayMaster": "0x2a9eF1519b97e8616d67E28fae493ceDFa3b801C", + "PayloadHelper": "0x702E94ff55ae09Be1E923393b5637c2D5c69F54f", + "PaymentHelper": "0xAe8af9cFd939d0eE0f7b354ab774A75Df539Af08", + "SocketValidator": "0x2CF947a38ec484eE1544A6112a1e80e65e7E4f21", + "SuperPositions": "0x400360FdDe552189Df6f4b616cB35fbA069FCE2B", + "SuperRBAC": "0xeE3294bcb48d8db603E0eB80F5e786560Db3eec5", + "SuperRegistry": "0x75Aad21aE992ae703A75343Ce22563Dd604c65d8", + "SuperformFactory": "0xB00943Be26BC510753153bBA687903B84b2EB167", + "SuperformRouter": "0x83D25df8e3A3c2e888A8392c03DA5bC9ABB8D36a", + "WormholeARImplementation": "0x425974B27f4f9F81E11496924D8d09B73dF2Fb96" +} \ No newline at end of file diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index aafd9df64..b0bf9ae78 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -21,6 +21,8 @@ import { IPermit2 } from "./vendor/dragonfly-xyz/IPermit2.sol"; import "./crosschain-liquidity/LiquidityHandler.sol"; import "./types/DataTypes.sol"; +import "forge-std/console.sol"; + /// @title BaseRouterImplementation /// @author Zeropoint Labs /// @dev Extends BaseRouter with standard internal execution functions @@ -617,11 +619,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ////////////////////////////////////////////////////////////// /// @notice fulfils the final stage of same chain deposit action - function _directDeposit(DirectDepositArgs memory args) - internal - virtual - returns (uint256 shares) - { + function _directDeposit(DirectDepositArgs memory args) internal virtual returns (uint256 shares) { // @dev deposits token to a given vault and mint vault positions directly through the form shares = IBaseForm(args.superform).directDepositIntoVault{ value: args.msgValue }( InitSingleVaultData( @@ -641,7 +639,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ); } - /// @notice deposits to single vault on the same chain /// @dev calls `_directDeposit` function _directSingleDeposit(SingleDepositArgs memory args_) internal virtual { @@ -855,8 +852,10 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev 10000 = 100% slippage if (maxSlippage_ > 10_000) return false; + console.log(1); /// @dev amounts can't be 0 if (amount_ == 0 || outputAmount_ == 0) return false; + console.log(2); /// @dev only validate this for non multi case (multi case is validated in _validateSuperformsData) /// @dev ensure that receiver address is set always @@ -905,17 +904,23 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (len == 0 || liqRequestsLen == 0) return false; if (len != liqRequestsLen) return false; - /// @dev all other length checks - if (lenSuperforms != len || lenSuperforms != superformsData_.outputAmounts.length || - lenSuperforms != superformsData_.maxSlippages.length ||lenSuperforms != superformsData_.hasDstSwaps.length || - lenSuperforms != superformsData_.retain4626s.length) { + console.log("A"); + /// @dev all other length checks + if ( + lenSuperforms != len || lenSuperforms != superformsData_.outputAmounts.length + || lenSuperforms != superformsData_.maxSlippages.length + || lenSuperforms != superformsData_.hasDstSwaps.length + || lenSuperforms != superformsData_.retain4626s.length + ) { return false; } + console.log("B"); /// @dev deposits beyond multi vault limit for a given destination chain blocked if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { return false; } + console.log("C"); /// @dev since this is a multi case, validate receiverAddress here once if (superformsData_.receiverAddress == address(0)) { @@ -934,6 +939,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); bool valid; + console.log("D"); /// @dev slippage, amount, paused status validation for (uint256 i; i < len; ++i) { @@ -966,6 +972,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } } } + console.log("E"); return true; } diff --git a/src/forms/ERC4626FormImplementation.sol b/src/forms/ERC4626FormImplementation.sol index 2a92af2e6..8200f1d57 100644 --- a/src/forms/ERC4626FormImplementation.sol +++ b/src/forms/ERC4626FormImplementation.sol @@ -237,7 +237,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC20(vars.asset).safeIncreaseAllowance(vault, vars.assetDifference); /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior - shares = _depositAndValidate(singleVaultData_,v,vars.assetDifference); + shares = _depositAndValidate(singleVaultData_, v, vars.assetDifference); } function _processXChainDeposit( @@ -263,7 +263,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { IERC20(asset).safeIncreaseAllowance(vaultLoc, singleVaultData_.amount); /// @dev deposit assets for shares and add extra validation check to ensure intended ERC4626 behavior - shares = _depositAndValidate(singleVaultData_,v,singleVaultData_.amount); + shares = _depositAndValidate(singleVaultData_, v, singleVaultData_.amount); emit Processed(srcChainId_, dstChainId, singleVaultData_.payloadId, singleVaultData_.amount, vaultLoc); } @@ -281,7 +281,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - assets = _withdrawAndValidate(singleVaultData_,v,a); + assets = _withdrawAndValidate(singleVaultData_, v, a); if (singleVaultData_.liqData.txData.length != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); @@ -290,7 +290,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault /// @dev if less it should be within the slippage limit specified by the user - /// @dev important to maintain so that the keeper cannot update with malicious data after successful withdraw + /// @dev important to maintain so that the keeper cannot update with malicious data after successful + /// withdraw if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) { revert Error.DIRECT_WITHDRAW_INVALID_LIQ_REQUEST(); } @@ -352,7 +353,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { vars.asset = address(asset); /// @dev redeem shares for assets and add extra validation check to ensure intended ERC4626 behavior - assets = _withdrawAndValidate(singleVaultData_,v,a); + assets = _withdrawAndValidate(singleVaultData_, v, a); if (len != 0) { vars.bridgeValidator = superRegistry.getBridgeValidator(singleVaultData_.liqData.bridgeId); @@ -361,7 +362,8 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { /// @dev the amount inscribed in liqData must be less or equal than the amount redeemed from the vault /// @dev if less it should be within the slippage limit specified by the user - /// @dev important to maintain so that the keeper cannot update with malicious data after successful withdraw + /// @dev important to maintain so that the keeper cannot update with malicious data after successful + /// withdraw if (_isWithdrawTxDataAmountInvalid(vars.amount, assets, singleVaultData_.maxSlippage)) { revert Error.XCHAIN_WITHDRAW_INVALID_LIQ_REQUEST(); } @@ -402,7 +404,7 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { InitSingleVaultData memory singleVaultData_, IERC4626 v, uint256 assetDifference - ) + ) internal returns (uint256 shares) { @@ -410,9 +412,12 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { uint256 sharesBalanceBefore = v.balanceOf(sharesReceiver); shares = v.deposit(assetDifference, sharesReceiver); uint256 sharesBalanceAfter = v.balanceOf(sharesReceiver); - - if ((sharesBalanceAfter - sharesBalanceBefore != shares) || - (ENTIRE_SLIPPAGE * shares < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) )) + if ( + (sharesBalanceAfter - sharesBalanceBefore != shares) + || ( + ENTIRE_SLIPPAGE * shares + < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage))) + ) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } @@ -422,17 +427,21 @@ abstract contract ERC4626FormImplementation is BaseForm, LiquidityHandler { InitSingleVaultData memory singleVaultData_, IERC4626 v, IERC20 a - ) - internal + ) + internal returns (uint256 assets) { - address assetsReceiver = singleVaultData_.liqData.txData.length == 0 ? singleVaultData_.receiverAddress : address(this); + address assetsReceiver = + singleVaultData_.liqData.txData.length == 0 ? singleVaultData_.receiverAddress : address(this); uint256 assetsBalanceBefore = a.balanceOf(assetsReceiver); assets = v.redeem(singleVaultData_.amount, assetsReceiver, address(this)); uint256 assetsBalanceAfter = a.balanceOf(assetsReceiver); - - if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (ENTIRE_SLIPPAGE * assets < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage)) )) + if ( + (assetsBalanceAfter - assetsBalanceBefore != assets) + || ( + ENTIRE_SLIPPAGE * assets + < ((singleVaultData_.outputAmount * (ENTIRE_SLIPPAGE - singleVaultData_.maxSlippage))) + ) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } diff --git a/src/forms/ERC4626TimelockForm.sol b/src/forms/ERC4626TimelockForm.sol index f202e06c8..5bf55b059 100644 --- a/src/forms/ERC4626TimelockForm.sol +++ b/src/forms/ERC4626TimelockForm.sol @@ -100,10 +100,13 @@ contract ERC4626TimelockForm is ERC4626FormImplementation { IERC20 assetERC = IERC20(vars.asset); uint256 assetsBalanceBefore = assetERC.balanceOf(vars.receiver); + assets = v.redeem(p_.data.amount, vars.receiver, address(this)); uint256 assetsBalanceAfter = assetERC.balanceOf(vars.receiver); - if ((assetsBalanceAfter - assetsBalanceBefore != assets) || - (assets * ENTIRE_SLIPPAGE > p_.data.outputAmount * (ENTIRE_SLIPPAGE - p_.data.maxSlippage)) + + if ( + (assetsBalanceAfter - assetsBalanceBefore != assets) + || (assets * ENTIRE_SLIPPAGE < p_.data.outputAmount * (ENTIRE_SLIPPAGE - p_.data.maxSlippage)) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index 265b4d415..644294a28 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -47,7 +47,7 @@ struct MultiVaultSFData { // superformids must have same destination. Can have different underlyings uint256[] superformIds; uint256[] amounts; // on deposits, amount of token to deposit on dst, on withdrawals, superpositions to burn - uint256[] outputAmounts; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive + uint256[] outputAmounts; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive uint256[] maxSlippages; LiqRequest[] liqRequests; // if length = 1; amount = sum(amounts) | else amounts must match the amounts being sent bytes permit2data; @@ -65,7 +65,7 @@ struct SingleVaultSFData { // superformids must have same destination. Can have different underlyings uint256 superformId; uint256 amount; - uint256 outputAmount; + uint256 outputAmount; // on deposits, amount of shares to receive, on withdrawals, amount of assets to receive uint256 maxSlippage; LiqRequest liqRequest; // if length = 1; amount = sum(amounts)| else amounts must match the amounts being sent bytes permit2data; diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol index 9f91702e8..df92b537d 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol @@ -131,9 +131,9 @@ contract MDMVW00001200TokenInputSlippageAMB12 is ProtocolActions { /// @dev superPostions[0] = superPositions[1] = superPositions[2] for ARBI (as it's the same /// superform) - amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 1, (superPositions[0] / 3) + 1)); - amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 1, (superPositions[1] / 3) + 1)); - amountThreeWithdraw_ = uint128(bound(amountThreeWithdraw_, 1, (superPositions[2] / 3) + 1)); + amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 10, (superPositions[0] / 3) + 1)); + amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 10, (superPositions[1] / 3) + 1)); + amountThreeWithdraw_ = uint128(bound(amountThreeWithdraw_, 10, (superPositions[2] / 3) + 1)); if (PARTIAL[DST_CHAINS[i]][1].length > 0) { AMOUNTS[DST_CHAINS[i]][1] = diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol index 514059163..fefebdba3 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstSingleVaultWithdraw/4626.Native.Slippage.AMB23.t.sol @@ -124,7 +124,7 @@ contract MDSVWNormal4626NativeSlippageAMB23 is ProtocolActions { ); /// @dev bounded to 1 less due to partial withdrawals - amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 1, superPositions[0] - 1)); + amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 1e6, superPositions[0] - 1)); AMOUNTS[DST_CHAINS[i]][1] = [amountOneWithdraw_]; } } diff --git a/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/0.TokenInput.NoSlippage.AMB13.sol b/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/0.TokenInput.NoSlippage.AMB13.sol index 66af086c8..684c29cd8 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/0.TokenInput.NoSlippage.AMB13.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/0.TokenInput.NoSlippage.AMB13.sol @@ -77,7 +77,7 @@ contract SDMVW0TokenInputNoSlippageAMB13 is ProtocolActions { amountOne_ = uint128(bound(amountOne_, 2 * 10 ** 6, TOTAL_SUPPLY_USDC)); AMOUNTS[ARBI][0] = [amountOne_]; /// @dev partial is true - amountTwo_ = uint128(bound(amountTwo_, 1, amountOne_ - 1)); + amountTwo_ = uint128(bound(amountTwo_, 10, amountOne_ - 1)); AMOUNTS[ARBI][1] = [amountTwo_]; for (uint256 act = 0; act < actions.length; ++act) { diff --git a/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/02.NativeInput.NoSlippage.AMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/02.NativeInput.NoSlippage.AMB12.sol index e0eb0b571..627f88a81 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/02.NativeInput.NoSlippage.AMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-singleXChainMultiVaultWithdraw/02.NativeInput.NoSlippage.AMB12.sol @@ -97,7 +97,7 @@ contract SDMVW02NativeInputNoSlippageAMB12 is ProtocolActions { DST_CHAINS[0] ); /// @dev bound to amountTwo_ - 1 as partial is true for second vault - amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 1, superPositions[1] - 1)); + amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 10, superPositions[1] - 1)); AMOUNTS[OP][1] = [superPositions[0], amountTwoWithdraw_]; } diff --git a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol index 46be92f86..bd1b1bfd9 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Timelock.t.sol @@ -10,7 +10,9 @@ import { DataLib } from "src/libraries/DataLib.sol"; import { SuperformRouter } from "src/SuperformRouter.sol"; import { IBaseForm } from "src/interfaces/IBaseForm.sol"; import { ERC4626TimelockForm } from "src/forms/ERC4626TimelockForm.sol"; +import { IERC4626 } from "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; import "src/types/DataTypes.sol"; +import "forge-std/console.sol"; contract SuperformERC4626TimelockFormTest is ProtocolActions { uint64 internal chainId = ETH; diff --git a/test/unit/superform-forms/superform-form.forwardDust.t.sol b/test/unit/superform-forms/superform-form.forwardDust.t.sol index 5fcfe66cd..95121ca4f 100644 --- a/test/unit/superform-forms/superform-form.forwardDust.t.sol +++ b/test/unit/superform-forms/superform-form.forwardDust.t.sol @@ -97,7 +97,7 @@ contract ForwardDustFormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, amountToDeposit_, - amountToDeposit_, + IBaseForm(superform).previewDepositTo(amountToDeposit_), 100, LiqRequest("", getContract(ARBI, "WETH"), address(0), 1, ARBI, 0), "", diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index db59d5995..4c788b12a 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -68,7 +68,6 @@ import { PaymentHelper } from "src/payments/PaymentHelper.sol"; import { IPaymentHelper } from "src/interfaces/IPaymentHelper.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { IBaseStateRegistry } from "src/interfaces/IBaseStateRegistry.sol"; - import { Error } from "src/libraries/Error.sol"; import "src/types/DataTypes.sol"; import "./TestTypes.sol"; @@ -902,9 +901,7 @@ abstract contract BaseSetup is DSTest, StdInvariant, Test { vars.superRegistryC.setAddress( vars.superRegistryC.DST_SWAPPER_PROCESSOR(), deployer, vars.dstChainId ); - vars.superRegistryC.setAddress( - vars.superRegistryC.SUPERFORM_RECEIVER(), deployer, vars.dstChainId - ); + vars.superRegistryC.setAddress(vars.superRegistryC.SUPERFORM_RECEIVER(), deployer, vars.dstChainId); } else { /// ack gas cost: 40000 /// timelock step form cost: 50000 diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index cd233572a..2a8e76e02 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -1132,14 +1132,14 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { } console.log("test amount post-bridge", v.amount); - vm.selectFork(v.initialFork); - + vm.selectFork(FORKS[args.toChainId]); + (address superform,,) = DataLib.getSuperform(args.superformId); /// @dev extraData is unused here so false is encoded (it is currently used to send in the partialWithdraw /// vaults without resorting to extra args, just for withdraws) superformData = SingleVaultSFData( args.superformId, v.amount, - args.outputAmount, + IBaseForm(superform).previewDepositTo(v.amount), args.maxSlippage, v.liqReq, v.permit2Calldata, @@ -1150,6 +1150,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(false) ); + vm.selectFork(v.initialFork); } struct SingleVaultWithdrawLocalVars { @@ -1245,12 +1246,15 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { 0 ); + vm.selectFork(FORKS[args.toChainId]); + (address superform,,) = DataLib.getSuperform(args.superformId); + /// @dev extraData is currently used to send in the partialWithdraw vaults without resorting to extra args, just /// for withdraws superformData = SingleVaultSFData( args.superformId, args.amount, - args.outputAmount, + IBaseForm(superform).previewRedeemFrom(args.amount), args.maxSlippage, vars.liqReq, "", @@ -1260,6 +1264,8 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { users[args.user], abi.encode(false) ); + + vm.selectFork(initialFork); } /*/////////////////////////////////////////////////////////////// diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index af16bb7ac..45b377cd7 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -1602,6 +1602,9 @@ abstract contract ProtocolActions is CommonProtocolActions { v.totalAmount += finalAmounts[i]; finalAmounts[i] = superformData.amount; + console.log("finalAMount", finalAmounts[i]); + args.outputAmounts[i] = superformData.outputAmount; + console.log("args.outputAmounts[i]", args.outputAmounts[i]); } if (action == Actions.DepositPermit2) { @@ -1845,14 +1848,15 @@ abstract contract ProtocolActions is CommonProtocolActions { console.log("test amount post-dst swap --", v.amount); - vm.selectFork(v.initialFork); + vm.selectFork(FORKS[args.toChainId]); + (address superform,,) = DataLib.getSuperform(args.superformId); /// @dev extraData is unused here so false is encoded (it is currently used to send in the partialWithdraw /// vaults without resorting to extra args, just for withdraws) superformData = SingleVaultSFData( args.superformId, v.amount, - args.outputAmount, + IBaseForm(superform).previewDepositTo(v.amount), args.maxSlippage, v.liqReq, v.permit2Calldata, @@ -1863,6 +1867,7 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(false) ); + vm.selectFork(v.initialFork); } struct SingleVaultWithdrawLocalVars { @@ -1961,12 +1966,16 @@ abstract contract ProtocolActions is CommonProtocolActions { 0 ); + vm.selectFork(FORKS[args.toChainId]); + (address superform,,) = DataLib.getSuperform(args.superformId); + console.log("finalAMount", args.amount); + console.log("-- OA---", IBaseForm(superform).previewRedeemFrom(args.amount)); /// @dev extraData is currently used to send in the partialWithdraw vaults without resorting to extra args, just /// for withdraws superformData = SingleVaultSFData( args.superformId, args.amount, - args.outputAmount, + IBaseForm(superform).previewRedeemFrom(args.amount), args.maxSlippage, vars.liqReq, "", @@ -1977,6 +1986,8 @@ abstract contract ProtocolActions is CommonProtocolActions { /// @dev repeat user for receiverAddressSP - not testing AA here abi.encode(args.partialWithdrawVault) ); + + vm.selectFork(initialFork); } /*/////////////////////////////////////////////////////////////// From 1a6e973893f9529e9167e3aeb0431c571526c754 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Tue, 26 Dec 2023 20:53:21 -0600 Subject: [PATCH 194/210] chore: Fix some tests --- lib/ERC1155A | 2 +- .../Multi.0.1.TokenInput.NoSlippage.AMB13.sol | 4 ++-- .../0000.1200.TokenInputNoSlippageAMB12.sol | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index f46fa5420..e7d53f306 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 +Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 diff --git a/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol b/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol index ecd475e3b..5665350b7 100644 --- a/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol +++ b/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol @@ -56,8 +56,8 @@ contract MDMVDMulti01NoDstSwapTokenInputNoSlippageL2AMB13 is ProtocolActions { //////////////////////////////////////////////////////////////*/ function test_scenario(uint128 amountOne_, uint128 amountTwo_) public { - amountOne_ = uint128(bound(amountOne_, 1e6, 1e9)); - amountTwo_ = uint128(bound(amountTwo_, 1e6, 1e9)); + amountOne_ = uint128(bound(amountOne_, 2e6, 2e10)); + amountTwo_ = uint128(bound(amountTwo_, 2e6, 2e10)); AMOUNTS[ETH][0] = [amountOne_, amountTwo_]; AMOUNTS[AVAX][0] = [amountTwo_, amountOne_]; diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol index df92b537d..b29a99696 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol @@ -131,9 +131,9 @@ contract MDMVW00001200TokenInputSlippageAMB12 is ProtocolActions { /// @dev superPostions[0] = superPositions[1] = superPositions[2] for ARBI (as it's the same /// superform) - amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 10, (superPositions[0] / 3) + 1)); - amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 10, (superPositions[1] / 3) + 1)); - amountThreeWithdraw_ = uint128(bound(amountThreeWithdraw_, 10, (superPositions[2] / 3) + 1)); + amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 1e6, (superPositions[0] / 3) + 1)); + amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 1e6, (superPositions[1] / 3) + 1)); + amountThreeWithdraw_ = uint128(bound(amountThreeWithdraw_, 1e6, (superPositions[2] / 3) + 1)); if (PARTIAL[DST_CHAINS[i]][1].length > 0) { AMOUNTS[DST_CHAINS[i]][1] = From 4602a8a1ff6d2d3c7c91e59e22783b66eb262ee5 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 12:07:10 +0530 Subject: [PATCH 195/210] fix: failing tests --- src/BaseRouterImplementation.sol | 6 +++ .../Multi.0.1.TokenInput.NoSlippage.AMB13.sol | 7 ++-- .../0000.1200.TokenInputNoSlippageAMB12.sol | 8 ++-- .../crosschain-liquidity/DstSwapper.t.sol | 40 +++++++------------ test/utils/ProtocolActions.sol | 3 +- 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index b0bf9ae78..01004d42e 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -905,6 +905,12 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (len != liqRequestsLen) return false; console.log("A"); + console.log(len); + console.log(lenSuperforms); + console.log(superformsData_.outputAmounts.length); + console.log(superformsData_.maxSlippages.length); + console.log(superformsData_.hasDstSwaps.length); + console.log(superformsData_.retain4626s.length); /// @dev all other length checks if ( lenSuperforms != len || lenSuperforms != superformsData_.outputAmounts.length diff --git a/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol b/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol index 5665350b7..ad697500c 100644 --- a/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol +++ b/test/fuzz/scenarios/scenarios-deposit-multiDstMultiVaultDeposit/Multi.0.1.TokenInput.NoSlippage.AMB13.sol @@ -55,11 +55,10 @@ contract MDMVDMulti01NoDstSwapTokenInputNoSlippageL2AMB13 is ProtocolActions { SCENARIO TESTS //////////////////////////////////////////////////////////////*/ - function test_scenario(uint128 amountOne_, uint128 amountTwo_) public { + function test_scenario(uint128 amountOne_) public { amountOne_ = uint128(bound(amountOne_, 2e6, 2e10)); - amountTwo_ = uint128(bound(amountTwo_, 2e6, 2e10)); - AMOUNTS[ETH][0] = [amountOne_, amountTwo_]; - AMOUNTS[AVAX][0] = [amountTwo_, amountOne_]; + AMOUNTS[ETH][0] = [amountOne_]; + AMOUNTS[AVAX][0] = [amountOne_]; for (uint256 act; act < actions.length; ++act) { TestAction memory action = actions[act]; diff --git a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol index b29a99696..51a5b2da1 100644 --- a/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol +++ b/test/fuzz/scenarios/scenarios-withdraw-multiDstMultiVaultWithdraw/0000.1200.TokenInputNoSlippageAMB12.sol @@ -107,8 +107,8 @@ contract MDMVW00001200TokenInputSlippageAMB12 is ProtocolActions { amountOne_ = uint128(bound(amountOne_, 2e6, 2e10)); amountTwo_ = uint128(bound(amountTwo_, 2e6, 2e10)); amountThree_ = uint128(bound(amountThree_, 2e6, 2e10)); - AMOUNTS[ARBI][0] = [amountOne_, amountTwo_, amountThree_, amountOne_]; + AMOUNTS[ARBI][0] = [amountOne_, amountTwo_, amountThree_, amountOne_]; AMOUNTS[POLY][0] = [amountOne_, amountOne_, amountTwo_, amountThree_]; for (uint256 act = 0; act < actions.length; ++act) { @@ -131,9 +131,9 @@ contract MDMVW00001200TokenInputSlippageAMB12 is ProtocolActions { /// @dev superPostions[0] = superPositions[1] = superPositions[2] for ARBI (as it's the same /// superform) - amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 1e6, (superPositions[0] / 3) + 1)); - amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 1e6, (superPositions[1] / 3) + 1)); - amountThreeWithdraw_ = uint128(bound(amountThreeWithdraw_, 1e6, (superPositions[2] / 3) + 1)); + amountOneWithdraw_ = uint128(bound(amountOneWithdraw_, 0.1e6, (superPositions[0] / 3) + 1)); + amountTwoWithdraw_ = uint128(bound(amountTwoWithdraw_, 0.1e6, (superPositions[1] / 3) + 1)); + amountThreeWithdraw_ = uint128(bound(amountThreeWithdraw_, 0.1e6, (superPositions[2] / 3) + 1)); if (PARTIAL[DST_CHAINS[i]][1].length > 0) { AMOUNTS[DST_CHAINS[i]][1] = diff --git a/test/unit/crosschain-liquidity/DstSwapper.t.sol b/test/unit/crosschain-liquidity/DstSwapper.t.sol index 08bc0bc7a..ea75bc4b0 100644 --- a/test/unit/crosschain-liquidity/DstSwapper.t.sol +++ b/test/unit/crosschain-liquidity/DstSwapper.t.sol @@ -735,7 +735,9 @@ contract DstSwapperTest is ProtocolActions { abi.encode( new uint8[](0), abi.encode( - InitSingleVaultData(1, superformId, amount, amount, 0, liq, true, false, receiverAddress, bytes("")) + InitSingleVaultData( + 1, superformId, amount, amount, 0, liq, true, false, receiverAddress, bytes("") + ) ) ) ) @@ -772,7 +774,9 @@ contract DstSwapperTest is ProtocolActions { ), abi.encode( new uint8[](0), - abi.encode(InitSingleVaultData(1, superformId, 1e18, 1e18, 1000, liq, true, false, users[0], bytes(""))) + abi.encode( + InitSingleVaultData(1, superformId, 1e18, 1e18, 1000, liq, true, false, users[0], bytes("")) + ) ) ) ); @@ -822,27 +826,16 @@ contract DstSwapperTest is ProtocolActions { liq[1] = LiqRequest("", getContract(OP, "DAI"), interimToken_, 1, OP, 0); InitMultiVaultData memory initMultiVaultData = InitMultiVaultData( - 1, - superformIds, - amounts, - outputAmounts, - maxSlippages, - liq, - hasDstSwaps, - new bool[](2), - users[0], - bytes("") + 1, superformIds, amounts, outputAmounts, maxSlippages, liq, hasDstSwaps, new bool[](2), users[0], bytes("") ); + uint8[] memory ambIds = new uint8[](1); + ambIds[0] = 1; + bytes memory encodedData = abi.encode( - AMBMessage( - DataLib.packTxInfo( - uint8(TransactionType.DEPOSIT), uint8(CallbackType.INIT), uint8(1), 1, users[0], ETH - ), - abi.encode( - new uint8[](1), - abi.encode(initMultiVaultData) - ) + AMBMessage( + DataLib.packTxInfo(uint8(TransactionType.DEPOSIT), uint8(CallbackType.INIT), uint8(1), 1, users[0], ETH), + abi.encode(ambIds, abi.encode(initMultiVaultData)) ) ); @@ -960,7 +953,7 @@ contract DstSwapperTest is ProtocolActions { new uint256[](2), liq, hasDstSwaps, - new bool[](2), + new bool[](2), receiverAddress, bytes("") ); @@ -968,10 +961,7 @@ contract DstSwapperTest is ProtocolActions { bytes memory encodedData = abi.encode( AMBMessage( DataLib.packTxInfo(1, 0, 1, 1, address(420), uint64(137)), - abi.encode( - new uint8[](1), // ambIds_ - abi.encode(initMultiVaultData) - ) + abi.encode(ambIds_, abi.encode(initMultiVaultData)) ) ); diff --git a/test/utils/ProtocolActions.sol b/test/utils/ProtocolActions.sol index 45b377cd7..b6e3ac2bc 100644 --- a/test/utils/ProtocolActions.sol +++ b/test/utils/ProtocolActions.sol @@ -1602,7 +1602,7 @@ abstract contract ProtocolActions is CommonProtocolActions { v.totalAmount += finalAmounts[i]; finalAmounts[i] = superformData.amount; - console.log("finalAMount", finalAmounts[i]); + console.log("finalAmount", finalAmounts[i]); args.outputAmounts[i] = superformData.outputAmount; console.log("args.outputAmounts[i]", args.outputAmounts[i]); } @@ -1768,7 +1768,6 @@ abstract contract ProtocolActions is CommonProtocolActions { if (liqRequestToken != NATIVE_TOKEN) { /// @dev - APPROVE transfer to SuperformRouter (because of Socket) - if (action == Actions.DepositPermit2) { vm.prank(users[args.user]); MockERC20(liqRequestToken).approve(getContract(args.srcChainId, "CanonicalPermit2"), type(uint256).max); From 1add84fe7205b3927297fbeb89725cb1a66777f2 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 12:09:54 +0530 Subject: [PATCH 196/210] chore: remove console logs --- src/BaseRouterImplementation.sol | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 01004d42e..a79399c2f 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -21,8 +21,6 @@ import { IPermit2 } from "./vendor/dragonfly-xyz/IPermit2.sol"; import "./crosschain-liquidity/LiquidityHandler.sol"; import "./types/DataTypes.sol"; -import "forge-std/console.sol"; - /// @title BaseRouterImplementation /// @author Zeropoint Labs /// @dev Extends BaseRouter with standard internal execution functions @@ -852,10 +850,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev 10000 = 100% slippage if (maxSlippage_ > 10_000) return false; - console.log(1); /// @dev amounts can't be 0 if (amount_ == 0 || outputAmount_ == 0) return false; - console.log(2); /// @dev only validate this for non multi case (multi case is validated in _validateSuperformsData) /// @dev ensure that receiver address is set always @@ -904,13 +900,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (len == 0 || liqRequestsLen == 0) return false; if (len != liqRequestsLen) return false; - console.log("A"); - console.log(len); - console.log(lenSuperforms); - console.log(superformsData_.outputAmounts.length); - console.log(superformsData_.maxSlippages.length); - console.log(superformsData_.hasDstSwaps.length); - console.log(superformsData_.retain4626s.length); /// @dev all other length checks if ( lenSuperforms != len || lenSuperforms != superformsData_.outputAmounts.length @@ -920,13 +909,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ) { return false; } - console.log("B"); /// @dev deposits beyond multi vault limit for a given destination chain blocked if (lenSuperforms > superRegistry.getVaultLimitPerDestination(dstChainId_)) { return false; } - console.log("C"); /// @dev since this is a multi case, validate receiverAddress here once if (superformsData_.receiverAddress == address(0)) { @@ -945,7 +932,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); bool valid; - console.log("D"); /// @dev slippage, amount, paused status validation for (uint256 i; i < len; ++i) { @@ -978,7 +964,6 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } } } - console.log("E"); return true; } From 7dc6c0adf9bc8bd3e121f6e0393b8c67a7ecef9f Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 12:52:06 +0530 Subject: [PATCH 197/210] chore: bring csr size < 24.5 KB --- src/crosschain-data/extensions/CoreStateRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 32015e9f8..4ed708ed9 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -50,7 +50,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { ////////////////////////////////////////////////////////////// modifier onlySender() override { - if (msg.sender != superRegistry.getAddress(keccak256("SUPERFORM_ROUTER"))) revert Error.NOT_SUPERFORM_ROUTER(); + if (msg.sender != _getAddress(keccak256("SUPERFORM_ROUTER"))) revert Error.NOT_SUPERFORM_ROUTER(); _; } From 5b831b71aae8fdcb317cb478acca09bfdebae827 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 13:05:37 +0530 Subject: [PATCH 198/210] chore: bring router size < 24.5 KB --- src/BaseRouterImplementation.sol | 64 ++++++++++++++++---------------- src/SuperformRouter.sol | 10 ++--- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index a79399c2f..b1d16ef6b 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -125,6 +125,11 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou return superRegistry.PERMIT2(); } + /// @dev returns the address from super registry + function _getAddress(bytes32 id_) internal view returns (address) { + return superRegistry.getAddress(id_); + } + /// @dev handles same-chain single vault deposit function _singleDirectSingleVaultDeposit(SingleDirectSingleVaultStateReq memory req_) internal virtual { /// @dev validate superformData @@ -138,7 +143,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.receiverAddressSP, CHAIN_ID, true, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))), false ) ) { @@ -185,7 +190,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.receiverAddressSP, req_.dstChainId, true, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))), false ) ) { @@ -368,14 +373,14 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.receiverAddressSP, CHAIN_ID, false, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))), false ) ) { revert Error.INVALID_SUPERFORMS_DATA(); } - ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).burnSingle( + ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).burnSingle( msg.sender, req_.superformData.superformId, req_.superformData.amount ); @@ -418,14 +423,14 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou req_.superformData.receiverAddressSP, req_.dstChainId, false, - ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))), + ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))), false ) ) { revert Error.INVALID_SUPERFORMS_DATA(); } - ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).burnSingle( + ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).burnSingle( msg.sender, req_.superformData.superformId, req_.superformData.amount ); @@ -479,7 +484,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } /// @dev SuperPositions are burnt optimistically here - ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).burnBatch( + ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).burnBatch( msg.sender, req_.superformData.superformIds, req_.superformData.amounts ); @@ -515,7 +520,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou revert Error.INVALID_SUPERFORMS_DATA(); } - ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).burnBatch( + ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).burnBatch( msg.sender, req_.superformsData.superformIds, req_.superformsData.amounts ); @@ -587,28 +592,27 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } function _dispatchAmbMessage(DispatchAMBMessageVars memory vars_, address receiverAddressSP_) internal virtual { - AMBMessage memory ambMessage = AMBMessage( - DataLib.packTxInfo( - uint8(vars_.txType), - uint8(CallbackType.INIT), - vars_.multiVaults, - STATE_REGISTRY_TYPE, - vars_.srcSender, - vars_.srcChainId - ), - vars_.ambData + uint256 txInfo = DataLib.packTxInfo( + uint8(vars_.txType), + uint8(CallbackType.INIT), + vars_.multiVaults, + STATE_REGISTRY_TYPE, + vars_.srcSender, + vars_.srcChainId ); - (uint256 fees, bytes memory extraData) = IPaymentHelper(superRegistry.getAddress(keccak256("PAYMENT_HELPER"))) - .calculateAMBData(vars_.dstChainId, vars_.ambIds, abi.encode(ambMessage)); + bytes memory ambMessage = abi.encode(AMBMessage(txInfo, vars_.ambData)); - ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).updateTxHistory( - vars_.currentPayloadId, ambMessage.txInfo, receiverAddressSP_ + (uint256 fees, bytes memory extraData) = IPaymentHelper(_getAddress(keccak256("PAYMENT_HELPER"))) + .calculateAMBData(vars_.dstChainId, vars_.ambIds, ambMessage); + + ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).updateTxHistory( + vars_.currentPayloadId, txInfo, receiverAddressSP_ ); /// @dev this call dispatches the message to the AMB bridge through dispatchPayload - IBaseStateRegistry(superRegistry.getAddress(keccak256("CORE_STATE_REGISTRY"))).dispatchPayload{ value: fees }( - vars_.srcSender, vars_.ambIds, vars_.dstChainId, abi.encode(ambMessage), extraData + IBaseStateRegistry(_getAddress(keccak256("CORE_STATE_REGISTRY"))).dispatchPayload{ value: fees }( + vars_.srcSender, vars_.ambIds, vars_.dstChainId, ambMessage, extraData ); } @@ -667,7 +671,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (v.shares != 0 && !args_.vaultData.retain4626) { // @dev mint super positions at the end of the deposit action if user doesn't retain 4626 - ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintSingle( + ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).mintSingle( args_.receiverAddressSP, args_.vaultData.superformId, v.shares ); } @@ -713,7 +717,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } /// @dev in direct deposits, SuperPositions are minted right after depositing to vaults - ISuperPositions(superRegistry.getAddress(keccak256("SUPER_POSITIONS"))).mintBatch( + ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).mintBatch( args_.receiverAddressSP, args_.vaultData.superformIds, v.shares ); } @@ -806,7 +810,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou function _forwardDustToPaymaster(address token_) internal { if (token_ == address(0)) revert Error.ZERO_ADDRESS(); - address paymaster = superRegistry.getAddress(keccak256("PAYMASTER")); + address paymaster = _getAddress(keccak256("PAYMASTER")); IERC20 token = IERC20(token_); uint256 dust = token.balanceOf(address(this)); @@ -930,7 +934,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou } } - ISuperformFactory factory = ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))); + ISuperformFactory factory = ISuperformFactory(_getAddress(keccak256("SUPERFORM_FACTORY"))); bool valid; /// @dev slippage, amount, paused status validation @@ -978,9 +982,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou uint256 residualPayment = address(this).balance - _balanceBefore; if (residualPayment != 0) { - IPayMaster(superRegistry.getAddress(keccak256("PAYMASTER"))).makePayment{ value: residualPayment }( - msg.sender - ); + IPayMaster(_getAddress(keccak256("PAYMASTER"))).makePayment{ value: residualPayment }(msg.sender); } } diff --git a/src/SuperformRouter.sol b/src/SuperformRouter.sol index 4dfdd2d4c..c44db3855 100644 --- a/src/SuperformRouter.sol +++ b/src/SuperformRouter.sol @@ -75,12 +75,11 @@ contract SuperformRouter is BaseRouterImplementation { payable override(BaseRouter, IBaseRouter) { - uint64 srcChainId = CHAIN_ID; uint256 balanceBefore = address(this).balance - msg.value; uint256 len = req_.dstChainIds.length; for (uint256 i; i < len; ++i) { - if (srcChainId == req_.dstChainIds[i]) { + if (CHAIN_ID == req_.dstChainIds[i]) { _singleDirectSingleVaultDeposit(SingleDirectSingleVaultStateReq(req_.superformsData[i])); } else { _singleXChainSingleVaultDeposit( @@ -98,11 +97,11 @@ contract SuperformRouter is BaseRouterImplementation { payable override(BaseRouter, IBaseRouter) { - uint64 chainId = CHAIN_ID; uint256 balanceBefore = address(this).balance - msg.value; uint256 len = req_.dstChainIds.length; + for (uint256 i; i < len; ++i) { - if (chainId == req_.dstChainIds[i]) { + if (CHAIN_ID == req_.dstChainIds[i]) { _singleDirectMultiVaultDeposit(SingleDirectMultiVaultStateReq(req_.superformsData[i])); } else { _singleXChainMultiVaultDeposit( @@ -190,12 +189,11 @@ contract SuperformRouter is BaseRouterImplementation { payable override(BaseRouter, IBaseRouter) { - uint64 chainId = CHAIN_ID; uint256 balanceBefore = address(this).balance - msg.value; uint256 len = req_.dstChainIds.length; for (uint256 i; i < len; ++i) { - if (chainId == req_.dstChainIds[i]) { + if (CHAIN_ID == req_.dstChainIds[i]) { _singleDirectMultiVaultWithdraw(SingleDirectMultiVaultStateReq(req_.superformsData[i])); } else { _singleXChainMultiVaultWithdraw( From ad18fcb8845f4c0c1d79264e874522c2e21256d0 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 13:23:07 +0530 Subject: [PATCH 199/210] chore: add ouput amounts to payload helper --- src/crosschain-data/utils/PayloadHelper.sol | 29 +++++++++++++++++-- src/interfaces/IPayloadHelper.sol | 2 ++ .../utils/PayloadHelper.multiVault.t.sol | 5 ++-- .../utils/PayloadHelper.singleVault.t.sol | 5 ++-- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 54e84b3a8..097491b81 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -44,6 +44,7 @@ contract PayloadHelper is IPayloadHelper { address srcSender; uint64 srcChainId; uint256[] amounts; + uint256[] outputAmounts; uint256[] slippages; uint256[] superformIds; bool[] hasDstSwaps; @@ -94,6 +95,7 @@ contract PayloadHelper is IPayloadHelper { address srcSender, uint64 srcChainId, uint256[] memory amounts, + uint256[] memory outputAmounts, uint256[] memory slippages, uint256[] memory superformIds, bool[] memory hasDstSwaps, @@ -112,8 +114,16 @@ contract PayloadHelper is IPayloadHelper { if (v.callbackType == uint256(CallbackType.RETURN) || v.callbackType == uint256(CallbackType.FAIL)) { (v.amounts, v.srcPayloadId) = _decodeReturnData(dstPayloadId_, v.multi, coreStateRegistry); } else if (v.callbackType == uint256(CallbackType.INIT)) { - (v.amounts, v.slippages, v.superformIds, v.hasDstSwaps, v.extraFormData, v.receiverAddress, v.srcPayloadId) - = _decodeInitData(dstPayloadId_, v.multi, coreStateRegistry); + ( + v.amounts, + v.outputAmounts, + v.slippages, + v.superformIds, + v.hasDstSwaps, + v.extraFormData, + v.receiverAddress, + v.srcPayloadId + ) = _decodeInitData(dstPayloadId_, v.multi, coreStateRegistry); } else { revert Error.INVALID_PAYLOAD(); } @@ -124,6 +134,7 @@ contract PayloadHelper is IPayloadHelper { v.srcSender, v.srcChainId, v.amounts, + v.outputAmounts, v.slippages, v.superformIds, v.hasDstSwaps, @@ -307,6 +318,7 @@ contract PayloadHelper is IPayloadHelper { view returns ( uint256[] memory amounts, + uint256[] memory outputAmounts, uint256[] memory slippages, uint256[] memory superformIds, bool[] memory hasDstSwaps, @@ -321,6 +333,7 @@ contract PayloadHelper is IPayloadHelper { return ( imvd.amounts, + imvd.outputAmounts, imvd.maxSlippages, imvd.superformIds, imvd.hasDstSwaps, @@ -335,6 +348,9 @@ contract PayloadHelper is IPayloadHelper { amounts = new uint256[](1); amounts[0] = isvd.amount; + outputAmounts = new uint256[](1); + outputAmounts[0] = isvd.outputAmount; + slippages = new uint256[](1); slippages[0] = isvd.maxSlippage; @@ -345,7 +361,14 @@ contract PayloadHelper is IPayloadHelper { receiverAddress = isvd.receiverAddress; return ( - amounts, slippages, superformIds, hasDstSwaps, isvd.extraFormData, isvd.receiverAddress, isvd.payloadId + amounts, + outputAmounts, + slippages, + superformIds, + hasDstSwaps, + isvd.extraFormData, + isvd.receiverAddress, + isvd.payloadId ); } } diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index a8d198db2..a22f578ce 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -16,6 +16,7 @@ interface IPayloadHelper { /// @return srcSender is the user who initiated the transaction on the srcChain /// @return srcChainId is the unique identifier of the srcChain /// @return amounts are the amounts to deposit/withdraw + /// @return outputAmounts are the expected outputAmounts specified by user /// @return slippages are the max slippages configured by the user (only for deposits) /// @return superformIds are the unique identifiers of the superforms /// @return hasDstSwaps are the array of flags indicating if the original liqData has a dstSwaps @@ -31,6 +32,7 @@ interface IPayloadHelper { address srcSender, uint64 srcChainId, uint256[] memory amounts, + uint256[] memory outputAmounts, uint256[] memory slippages, uint256[] memory superformIds, bool[] memory hasDstSwaps, diff --git a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol index 0d1c5d2e8..cba24feaf 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol @@ -209,6 +209,7 @@ contract PayloadHelperMultiTest is ProtocolActions { v.srcSender, v.srcChainId, v.amounts, + , v.slippage, , , @@ -288,8 +289,8 @@ contract PayloadHelperMultiTest is ProtocolActions { CheckDstPayloadInternalVars memory v; - (v.txType, v.callbackType, v.srcSender, v.srcChainId, v.amounts, v.slippage,, v.hasDstSwaps,,, v.srcPayloadId) = - IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); + (v.txType, v.callbackType, v.srcSender, v.srcChainId, v.amounts,, v.slippage,, v.hasDstSwaps,,, v.srcPayloadId) + = IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); assertEq(v.txType, 0); diff --git a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol index 177e8c66a..dc2d98158 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol @@ -219,6 +219,7 @@ contract PayloadHelperSingleTest is ProtocolActions { v.srcSender, v.srcChainId, v.amounts, + , v.slippage, , , @@ -265,8 +266,8 @@ contract PayloadHelperSingleTest is ProtocolActions { CheckDstPayloadInternalVars memory v; - (v.txType, v.callbackType, v.srcSender, v.srcChainId, v.amounts, v.slippage,, v.hasDstSwaps,,, v.srcPayloadId) = - IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); + (v.txType, v.callbackType, v.srcSender, v.srcChainId, v.amounts,, v.slippage,, v.hasDstSwaps,,, v.srcPayloadId) + = IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); /// @dev 0 for deposit assertEq(v.txType, 0); From 15ef9af239dd03c08cf31bd038ea2dcccfe4a080 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 13:48:57 +0530 Subject: [PATCH 200/210] chore: return output amounts in decodeCoreStateRegistryPayload --- .../extensions/CoreStateRegistry.sol | 2 +- src/crosschain-data/utils/PayloadHelper.sol | 60 ++----------------- src/interfaces/IPayloadHelper.sol | 60 +++++++++++-------- .../utils/PayloadHelper.multiVault.t.sol | 52 ++++++---------- .../utils/PayloadHelper.singleVault.t.sol | 60 +++++-------------- 5 files changed, 73 insertions(+), 161 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 4ed708ed9..4afaa4e5f 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -709,7 +709,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { bool errors; uint256 len = multiVaultData.superformIds.length; - address superformFactory = superRegistry.getAddress(keccak256("SUPERFORM_FACTORY")); + address superformFactory = _getAddress(keccak256("SUPERFORM_FACTORY")); for (uint256 i; i < len; ++i) { // @dev validates if superformId exists on factory diff --git a/src/crosschain-data/utils/PayloadHelper.sol b/src/crosschain-data/utils/PayloadHelper.sol index 097491b81..83b71fe79 100644 --- a/src/crosschain-data/utils/PayloadHelper.sol +++ b/src/crosschain-data/utils/PayloadHelper.sol @@ -38,26 +38,6 @@ contract PayloadHelper is IPayloadHelper { // STRUCTS // ////////////////////////////////////////////////////////////// - struct DecodeDstPayloadInternalVars { - uint8 txType; - uint8 callbackType; - address srcSender; - uint64 srcChainId; - uint256[] amounts; - uint256[] outputAmounts; - uint256[] slippages; - uint256[] superformIds; - bool[] hasDstSwaps; - address receiverAddress; - uint256 srcPayloadId; - bytes extraFormData; - uint8 multi; - ReturnMultiData rd; - ReturnSingleData rsd; - InitMultiVaultData imvd; - InitSingleVaultData isvd; - } - struct DecodeDstPayloadLiqDataInternalVars { uint8 callbackType; uint8 multi; @@ -89,30 +69,15 @@ contract PayloadHelper is IPayloadHelper { external view override - returns ( - uint8 txType, - uint8 callbackType, - address srcSender, - uint64 srcChainId, - uint256[] memory amounts, - uint256[] memory outputAmounts, - uint256[] memory slippages, - uint256[] memory superformIds, - bool[] memory hasDstSwaps, - bytes memory extraFormData, - address receiverAddress, - uint256 srcPayloadId - ) + returns (DecodedDstPayload memory v) { - IBaseStateRegistry coreStateRegistry = _getCoreStateRegistry(); - _isValidPayloadId(dstPayloadId_, coreStateRegistry); + _isValidPayloadId(dstPayloadId_, _getCoreStateRegistry()); - DecodeDstPayloadInternalVars memory v; (v.txType, v.callbackType, v.multi, v.srcSender, v.srcChainId) = - _decodePayloadHeader(dstPayloadId_, coreStateRegistry); + _decodePayloadHeader(dstPayloadId_, _getCoreStateRegistry()); if (v.callbackType == uint256(CallbackType.RETURN) || v.callbackType == uint256(CallbackType.FAIL)) { - (v.amounts, v.srcPayloadId) = _decodeReturnData(dstPayloadId_, v.multi, coreStateRegistry); + (v.amounts, v.srcPayloadId) = _decodeReturnData(dstPayloadId_, v.multi, _getCoreStateRegistry()); } else if (v.callbackType == uint256(CallbackType.INIT)) { ( v.amounts, @@ -123,25 +88,10 @@ contract PayloadHelper is IPayloadHelper { v.extraFormData, v.receiverAddress, v.srcPayloadId - ) = _decodeInitData(dstPayloadId_, v.multi, coreStateRegistry); + ) = _decodeInitData(dstPayloadId_, v.multi, _getCoreStateRegistry()); } else { revert Error.INVALID_PAYLOAD(); } - - return ( - v.txType, - v.callbackType, - v.srcSender, - v.srcChainId, - v.amounts, - v.outputAmounts, - v.slippages, - v.superformIds, - v.hasDstSwaps, - v.extraFormData, - v.receiverAddress, - v.srcPayloadId - ); } /// @inheritdoc IPayloadHelper diff --git a/src/interfaces/IPayloadHelper.sol b/src/interfaces/IPayloadHelper.sol index a22f578ce..9ecde6ba9 100644 --- a/src/interfaces/IPayloadHelper.sol +++ b/src/interfaces/IPayloadHelper.sol @@ -5,41 +5,49 @@ pragma solidity ^0.8.23; /// @author ZeroPoint Labs /// @dev helps decoding the bytes payload and returns meaningful information interface IPayloadHelper { + ////////////////////////////////////////////////////////////// + // STRUCTS // + ////////////////////////////////////////////////////////////// + + /// @notice txType is the type of transaction. check {TransactionType} enum in DataTypes.sol + /// @notice callbackType is the type of payload. check {CallbackType} enum in DataTypes.sol + /// @notice srcSender is the user who initiated the transaction on the srcChain + /// @notice srcChainId is the unique identifier of the srcChain + /// @notice amounts are the amounts to deposit/withdraw + /// @notice outputAmounts are the expected outputAmounts specified by user + /// @notice slippages are the max slippages configured by the user (only for deposits) + /// @notice superformIds are the unique identifiers of the superforms + /// @notice hasDstSwaps are the array of flags indicating if the original liqData has a dstSwaps + /// @notice extraFormData is the extra form data (optional: passed for forms with special needs) + /// @notice receiverAddress is the address to be used for refunds + /// @notice srcPayloadId is the identifier of the corresponding payload on srcChain + struct DecodedDstPayload { + uint8 txType; + uint8 callbackType; + address srcSender; + uint64 srcChainId; + uint256[] amounts; + uint256[] outputAmounts; + uint256[] slippages; + uint256[] superformIds; + bool[] hasDstSwaps; + address receiverAddress; + uint256 srcPayloadId; + bytes extraFormData; + uint8 multi; + } + ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // ////////////////////////////////////////////////////////////// /// @dev reads the payload from the core state registry and decodes it in a more detailed manner. /// @param dstPayloadId_ is the unique identifier of the payload received in dst core state registry - /// @return txType is the type of transaction. check {TransactionType} enum in DataTypes.sol - /// @return callbackType is the type of payload. check {CallbackType} enum in DataTypes.sol - /// @return srcSender is the user who initiated the transaction on the srcChain - /// @return srcChainId is the unique identifier of the srcChain - /// @return amounts are the amounts to deposit/withdraw - /// @return outputAmounts are the expected outputAmounts specified by user - /// @return slippages are the max slippages configured by the user (only for deposits) - /// @return superformIds are the unique identifiers of the superforms - /// @return hasDstSwaps are the array of flags indicating if the original liqData has a dstSwaps - /// @return extraFormData is the extra form data (optional: passed for forms with special needs) - /// @return receiverAddress is the address to be used for refunds - /// @return srcPayloadId is the identifier of the corresponding payload on srcChain + /// @return decodedDstPayload is the details of the payload, refer DecodedDstPayload struct for info function decodeCoreStateRegistryPayload(uint256 dstPayloadId_) external view - returns ( - uint8 txType, - uint8 callbackType, - address srcSender, - uint64 srcChainId, - uint256[] memory amounts, - uint256[] memory outputAmounts, - uint256[] memory slippages, - uint256[] memory superformIds, - bool[] memory hasDstSwaps, - bytes memory extraFormData, - address receiverAddress, - uint256 srcPayloadId - ); + returns (DecodedDstPayload memory decodedDstPayload); /// @dev reads the payload from the core state registry and decodes liqData for it (to be used in withdraw cases) /// @param dstPayloadId_ is the unique identifier of the payload received in dst core state registry diff --git a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol index cba24feaf..ad74cd886 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.multiVault.t.sol @@ -201,26 +201,12 @@ contract PayloadHelperMultiTest is ProtocolActions { function _checkDstPayloadInit(CheckDstPayloadInitArgs memory args) internal { vm.selectFork(FORKS[DST_CHAINS[0]]); - CheckDstPayloadInternalVars memory v; - - ( - v.txType, - v.callbackType, - v.srcSender, - v.srcChainId, - v.amounts, - , - v.slippage, - , - , - , - v.receiverAddress, - v.srcPayloadId - ) = IPayloadHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); - - v.extraDataGenerated = new bytes[](2); - v.extraDataGenerated[0] = abi.encode("500000"); - v.extraDataGenerated[1] = abi.encode("0"); + IPayloadHelper.DecodedDstPayload memory v = + IPayloadHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); + + bytes[] memory extraDataGenerated = new bytes[](2); + extraDataGenerated[0] = abi.encode("500000"); + extraDataGenerated[1] = abi.encode("0"); assertEq(v.txType, 0); @@ -235,23 +221,23 @@ contract PayloadHelperMultiTest is ProtocolActions { for (uint256 i; i < v.amounts.length; ++i) { /// @dev ETH<>DAI swap on OP - v.daiAfterFirstSwap = (AMOUNTS[ARBI][0][i] * args.USDPerETHonOP_) / args.USDPerDAIonOP_; + uint256 daiAfterFirstSwap = (AMOUNTS[ARBI][0][i] * args.USDPerETHonOP_) / args.USDPerDAIonOP_; /// @dev DAI on OP <> DAI on ARBI - v.daiAfterSecondSwap = (v.daiAfterFirstSwap * args.USDPerDAIonOP_) / args.USDPerDAIonARBI_; + uint256 daiAfterSecondSwap = (daiAfterFirstSwap * args.USDPerDAIonOP_) / args.USDPerDAIonARBI_; /// @dev daiAfterSecondSwap doesn't include bridge slippage hence should be greater - assertLe(v.amounts[i], v.daiAfterSecondSwap); + assertLe(v.amounts[i], daiAfterSecondSwap); } - for (uint256 i = 0; i < v.slippage.length; ++i) { - assertEq(v.slippage[i], MAX_SLIPPAGE); + for (uint256 i = 0; i < v.slippages.length; ++i) { + assertEq(v.slippages[i], MAX_SLIPPAGE); } /// @notice: just asserting if fees are greater than 0 /// no way to write serious tests on forked testnet at this point. should come back to this later on. - (v.ambFees,) = IPaymentHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PaymentHelper"))]).estimateAMBFees( - AMBs, DST_CHAINS[0], abi.encode(1), v.extraDataGenerated + (uint256 ambFees,) = IPaymentHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PaymentHelper"))]).estimateAMBFees( + AMBs, DST_CHAINS[0], abi.encode(1), extraDataGenerated ); - assertGe(v.ambFees, 0); + assertGe(ambFees, 0); } struct CheckDstPayloadLiqDataInternalVars { @@ -287,10 +273,8 @@ contract PayloadHelperMultiTest is ProtocolActions { function _checkDstPayloadReturn() internal { vm.selectFork(FORKS[CHAIN_0]); - CheckDstPayloadInternalVars memory v; - - (v.txType, v.callbackType, v.srcSender, v.srcChainId, v.amounts,, v.slippage,, v.hasDstSwaps,,, v.srcPayloadId) - = IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); + IPayloadHelper.DecodedDstPayload memory v = + IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); assertEq(v.txType, 0); @@ -301,9 +285,9 @@ contract PayloadHelperMultiTest is ProtocolActions { /// chain id of polygon is 42161 assertEq(v.srcPayloadId, 1); - for (uint256 i = 0; i < v.slippage.length; ++i) { + for (uint256 i = 0; i < v.slippages.length; ++i) { assertLe(v.amounts[i], AMOUNTS[ARBI][0][i]); - assertEq(v.slippage[i], MAX_SLIPPAGE); + assertEq(v.slippages[i], MAX_SLIPPAGE); } } } diff --git a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol index dc2d98158..685faf244 100644 --- a/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol +++ b/test/unit/crosschain-data/utils/PayloadHelper.singleVault.t.sol @@ -168,22 +168,6 @@ contract PayloadHelperSingleTest is ProtocolActions { PayloadHelper(getContract(ETH, "PayloadHelper")).decodeCoreStateRegistryPayload(1); } - struct CheckDstPayloadInternalVars { - bytes[] extraDataGenerated; - uint256 ambFees; - uint8 txType; - uint8 callbackType; - address srcSender; - uint64 srcChainId; - uint256[] amounts; - uint256[] slippage; - uint256[] superformIds; - bool[] hasDstSwaps; - bytes extraFormData; - address receiverAddress; - uint256 srcPayloadId; - } - function _checkSrcPayload() internal { vm.selectFork(FORKS[CHAIN_0]); @@ -209,28 +193,16 @@ contract PayloadHelperSingleTest is ProtocolActions { function _checkDstPayloadInit() internal { vm.selectFork(FORKS[DST_CHAINS[0]]); - CheckDstPayloadInternalVars memory v; vm.expectRevert(Error.INVALID_PAYLOAD_ID.selector); IPayloadHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(3); - ( - v.txType, - v.callbackType, - v.srcSender, - v.srcChainId, - v.amounts, - , - v.slippage, - , - , - , - v.receiverAddress, - v.srcPayloadId - ) = IPayloadHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); + IPayloadHelper.DecodedDstPayload memory v = + IPayloadHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); IPayloadHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PayloadHelper"))]).getDstPayloadProof(1); - v.extraDataGenerated = new bytes[](2); - v.extraDataGenerated[0] = abi.encode("500000"); - v.extraDataGenerated[1] = abi.encode("0"); + + bytes[] memory extraDataGenerated = new bytes[](2); + extraDataGenerated[0] = abi.encode("500000"); + extraDataGenerated[1] = abi.encode("0"); /// @dev 0 for deposit assertEq(v.txType, 0); @@ -245,29 +217,27 @@ contract PayloadHelperSingleTest is ProtocolActions { assertEq(v.receiverAddress, users[0]); - for (uint256 i = 0; i < v.slippage.length; ++i) { + for (uint256 i = 0; i < v.slippages.length; ++i) { console.log("v.amounts[i]: %s", v.amounts[i]); console.log("AMOUNTS[POLY][0][i]: %s", AMOUNTS[POLY][0][i]); /// @dev TODO: fix this assertion considering exchange rates // assertLe(v.amounts[i], AMOUNTS[POLY][0][i]); - assertEq(v.slippage[i], MAX_SLIPPAGE); + assertEq(v.slippages[i], MAX_SLIPPAGE); } /// @notice: just asserting if fees are greater than 0 /// FIXME no way to write serious tests on forked testnet at this point. should come back to this later on. - (v.ambFees,) = IPaymentHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PaymentHelper"))]).estimateAMBFees( - AMBs, DST_CHAINS[0], abi.encode(1), v.extraDataGenerated + (uint256 ambFees,) = IPaymentHelper(contracts[DST_CHAINS[0]][bytes32(bytes("PaymentHelper"))]).estimateAMBFees( + AMBs, DST_CHAINS[0], abi.encode(1), extraDataGenerated ); - assertGe(v.ambFees, 0); + assertGe(ambFees, 0); } function _checkDstPayloadReturn() internal { vm.selectFork(FORKS[CHAIN_0]); - CheckDstPayloadInternalVars memory v; - - (v.txType, v.callbackType, v.srcSender, v.srcChainId, v.amounts,, v.slippage,, v.hasDstSwaps,,, v.srcPayloadId) - = IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); + IPayloadHelper.DecodedDstPayload memory v = + IPayloadHelper(contracts[CHAIN_0][bytes32(bytes("PayloadHelper"))]).decodeCoreStateRegistryPayload(1); /// @dev 0 for deposit assertEq(v.txType, 0); @@ -279,9 +249,9 @@ contract PayloadHelperSingleTest is ProtocolActions { assertEq(v.srcChainId, 137); assertEq(v.srcPayloadId, 1); - for (uint256 i = 0; i < v.slippage.length; ++i) { + for (uint256 i = 0; i < v.slippages.length; ++i) { assertLe(v.amounts[i], AMOUNTS[POLY][0][i]); - assertEq(v.slippage[i], MAX_SLIPPAGE); + assertEq(v.slippages[i], MAX_SLIPPAGE); } } From f1c2aa1ff9514a6a3b59054efafd2ed44a499659 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 27 Dec 2023 09:30:29 +0000 Subject: [PATCH 201/210] fix: comments --- lib/ERC1155A | 2 +- .../lifi/LiFiValidator.sol | 16 ++-- src/vendor/lifi/HopFacetPacked.sol | 83 +++++++++++++++++++ src/vendor/lifi/LiFiTxDataExtractor.sol | 23 +++++ 4 files changed, 115 insertions(+), 9 deletions(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index e7d53f306..f46fa5420 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 +Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 diff --git a/src/crosschain-liquidity/lifi/LiFiValidator.sol b/src/crosschain-liquidity/lifi/LiFiValidator.sol index 666062199..c48ec4ae0 100644 --- a/src/crosschain-liquidity/lifi/LiFiValidator.sol +++ b/src/crosschain-liquidity/lifi/LiFiValidator.sol @@ -42,8 +42,6 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { /// @dev 1 - check if it is a swapTokensGeneric call (match via selector) if (selector == GenericSwapFacet.swapTokensGeneric.selector) { /// @dev GenericSwapFacet - /// @dev direct actions with deposit, cannot have bridge data - goes in here - /// @dev withdraw actions without bridge data (just swap) - goes in here (sendingAssetId,, receiver,,) = extractGenericSwapParameters(args_.txData); _validateGenericParameters(args_, receiver, sendingAssetId); @@ -58,9 +56,6 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { /// @dev 3 - proceed with normal extraction (, sendingAssetId, receiver,,, destinationChainId,, hasDestinationCall) = extractMainParameters(args_.txData); - /// @dev xchain actions can have bridgeData or bridgeData + swapData - goes in here - /// @dev withdraw actions may have bridge data after withdrawing - goes in here - hasDstSwap = _validateMainParameters(args_, hasDestinationCall, hasDstSwap, receiver, sendingAssetId, destinationChainId); @@ -80,11 +75,12 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { bytes4 selector = _extractSelector(txData_); /// @dev 1 - check if it is a swapTokensGeneric call (match via selector) - if (selector == GenericSwapFacet.swapTokensGeneric.selector && !genericSwapDisallowed_) { + if (selector == GenericSwapFacet.swapTokensGeneric.selector) { + if (genericSwapDisallowed_) { + revert Error.INVALID_ACTION(); + } (, amount_,,,) = extractGenericSwapParameters(txData_); return amount_; - } else if (selector == GenericSwapFacet.swapTokensGeneric.selector && genericSwapDisallowed_) { - revert Error.INVALID_ACTION(); } /// @dev 2 - check if it is any other blacklisted selector @@ -215,6 +211,8 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { view returns (bool) { + /// @notice xchain actions can have bridgeData or swapData + bridgeData + /// @dev 0. Destination call validation if (hasDestinationCall) revert Error.INVALID_TXDATA_NO_DESTINATIONCALL_ALLOWED(); @@ -273,6 +271,8 @@ contract LiFiValidator is BridgeValidator, LiFiTxDataExtractor { internal pure { + /// @notice direct actions with deposit, cannot have bridge data + /// @notice withdraw actions without bridge data (just swap) also fall in GenericSwap if (args_.deposit) { /// @dev 1. chainId validation if (args_.srcChainId != args_.dstChainId) revert Error.INVALID_TXDATA_CHAIN_ID(); diff --git a/src/vendor/lifi/HopFacetPacked.sol b/src/vendor/lifi/HopFacetPacked.sol index 2f1aa564a..d9ae34aed 100644 --- a/src/vendor/lifi/HopFacetPacked.sol +++ b/src/vendor/lifi/HopFacetPacked.sol @@ -33,4 +33,87 @@ contract HopFacetPacked { external payable { } + + /// @notice Bridges ERC20 tokens via Hop Protocol from L2 + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaHopL2ERC20Packed() external { } + + /// @notice Bridges ERC20 tokens via Hop Protocol from L2 + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param sendingAssetId Address of the source asset to bridge + /// @param minAmount Amount of the source asset to bridge + /// @param bonderFee Fees payed to hop bonder + /// @param amountOutMin Source swap minimal accepted amount + /// @param destinationAmountOutMin Destination swap minimal accepted amount + /// @param destinationDeadline Destination swap maximal time + /// @param hopBridge Address of the Hop L2_AmmWrapper + function startBridgeTokensViaHopL2ERC20Min( + bytes8 transactionId, + address receiver, + uint256 destinationChainId, + address sendingAssetId, + uint256 minAmount, + uint256 bonderFee, + uint256 amountOutMin, + uint256 destinationAmountOutMin, + uint256 destinationDeadline, + address hopBridge + ) + external + { } + + /// @notice Bridges Native tokens via Hop Protocol from L1 + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaHopL1NativePacked() external payable { } + + /// @notice Bridges Native tokens via Hop Protocol from L1 + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param destinationAmountOutMin Destination swap minimal accepted amount + /// @param relayer needed for gas spikes + /// @param relayerFee needed for gas spikes + /// @param hopBridge Address of the Hop Bridge + function startBridgeTokensViaHopL1NativeMin( + bytes8 transactionId, + address receiver, + uint256 destinationChainId, + uint256 destinationAmountOutMin, + address relayer, + uint256 relayerFee, + address hopBridge + ) + external + payable + { } + + /// @notice Bridges Native tokens via Hop Protocol from L1 + /// No params, all data will be extracted from manually encoded callData + function startBridgeTokensViaHopL1ERC20Packed() external payable { } + + /// @notice Bridges ERC20 tokens via Hop Protocol from L1 + /// @param transactionId Custom transaction ID for tracking + /// @param receiver Receiving wallet address + /// @param destinationChainId Receiving chain + /// @param sendingAssetId Address of the source asset to bridge + /// @param minAmount Amount of the source asset to bridge + /// @param destinationAmountOutMin Destination swap minimal accepted amount + /// @param relayer needed for gas spikes + /// @param relayerFee needed for gas spikes + /// @param hopBridge Address of the Hop Bridge + function startBridgeTokensViaHopL1ERC20Min( + bytes8 transactionId, + address receiver, + uint256 destinationChainId, + address sendingAssetId, + uint256 minAmount, + uint256 destinationAmountOutMin, + address relayer, + uint256 relayerFee, + address hopBridge + ) + external + { } } diff --git a/src/vendor/lifi/LiFiTxDataExtractor.sol b/src/vendor/lifi/LiFiTxDataExtractor.sol index b4b0bcc14..012e0d959 100644 --- a/src/vendor/lifi/LiFiTxDataExtractor.sol +++ b/src/vendor/lifi/LiFiTxDataExtractor.sol @@ -44,6 +44,29 @@ contract LiFiTxDataExtractor { if (selector == HopFacetPacked.startBridgeTokensViaHopL2NativeMin.selector) { return false; } + if (selector == HopFacetPacked.startBridgeTokensViaHopL2ERC20Packed.selector) { + return false; + } + + if (selector == HopFacetPacked.startBridgeTokensViaHopL2ERC20Min.selector) { + return false; + } + + if (selector == HopFacetPacked.startBridgeTokensViaHopL1NativePacked.selector) { + return false; + } + + if (selector == HopFacetPacked.startBridgeTokensViaHopL1NativeMin.selector) { + return false; + } + + if (selector == HopFacetPacked.startBridgeTokensViaHopL1ERC20Packed.selector) { + return false; + } + + if (selector == HopFacetPacked.startBridgeTokensViaHopL1ERC20Min.selector) { + return false; + } return true; } From cabaafd817526f71fa023d507d090063cb1db85a Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 27 Dec 2023 09:41:27 +0000 Subject: [PATCH 202/210] fix: nits --- lib/ERC1155A | 2 +- src/BaseRouterImplementation.sol | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index e7d53f306..f46fa5420 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 +Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index b1d16ef6b..7bd6a0718 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -34,6 +34,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev tracks the total payloads uint256 public payloadIds; + uint256 internal constant ENTIRE_SLIPPAGE = 10_000; ////////////////////////////////////////////////////////////// // STRUCTS // @@ -852,7 +853,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou if (dstChainId_ != sfDstChainId) return false; /// @dev 10000 = 100% slippage - if (maxSlippage_ > 10_000) return false; + if (maxSlippage_ > ENTIRE_SLIPPAGE) return false; /// @dev amounts can't be 0 if (amount_ == 0 || outputAmount_ == 0) return false; @@ -978,6 +979,8 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev forwards the residual payment to Paymaster function _forwardPayment(uint256 _balanceBefore) internal virtual { + if (address(this).balance < _balanceBefore) revert Error.INSUFFICIENT_BALANCE(); + /// @dev deducts what's already available sends what's left in msg.value to Paymaster uint256 residualPayment = address(this).balance - _balanceBefore; From 9f6b051a17a0b6f1ca02ae0b5f6bcea6674756f3 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:27:39 +0000 Subject: [PATCH 203/210] chore: add check --- src/vendor/lifi/LiFiTxDataExtractor.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vendor/lifi/LiFiTxDataExtractor.sol b/src/vendor/lifi/LiFiTxDataExtractor.sol index 012e0d959..6d632d56e 100644 --- a/src/vendor/lifi/LiFiTxDataExtractor.sol +++ b/src/vendor/lifi/LiFiTxDataExtractor.sol @@ -67,6 +67,10 @@ contract LiFiTxDataExtractor { if (selector == HopFacetPacked.startBridgeTokensViaHopL1ERC20Min.selector) { return false; } + /// @dev prevent recursive calls + if (selector == StandardizedCallFacet.standardizedCall.selector) { + return false; + } return true; } From 1279d447ee61de08c249e0569be978d7eab20821 Mon Sep 17 00:00:00 2001 From: vikramarun <33469661+vikramarun@users.noreply.github.com> Date: Wed, 27 Dec 2023 04:53:09 -0600 Subject: [PATCH 204/210] chore: add param to test --- lib/ERC1155A | 2 +- test/unit/superform-forms/superform-form.ERC4626Form.t.sol | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index f46fa5420..e7d53f306 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 +Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index 6e0e96921..e672947e3 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -951,6 +951,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, daiAmount, + daiAmount, 100, LiqRequest(blacklistedTxData, getContract(ETH, "DAI"), address(0), 5, ETH, 0), "", From ba22c68bec0ab6ac0c58d517bf4bcdd8b3965723 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:09:33 +0000 Subject: [PATCH 205/210] test: hotfix --- .../superform-form.ERC4626Form.t.sol | 1 + test/utils/InvariantProtocolActions.sol | 73 ++++++++----------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol index 6e0e96921..e672947e3 100644 --- a/test/unit/superform-forms/superform-form.ERC4626Form.t.sol +++ b/test/unit/superform-forms/superform-form.ERC4626Form.t.sol @@ -951,6 +951,7 @@ contract SuperformERC4626FormTest is ProtocolActions { SingleVaultSFData memory data = SingleVaultSFData( superformId, daiAmount, + daiAmount, 100, LiqRequest(blacklistedTxData, getContract(ETH, "DAI"), address(0), 5, ETH, 0), "", diff --git a/test/utils/InvariantProtocolActions.sol b/test/utils/InvariantProtocolActions.sol index 95b5a6cac..b5ed44936 100644 --- a/test/utils/InvariantProtocolActions.sol +++ b/test/utils/InvariantProtocolActions.sol @@ -707,46 +707,14 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { ); if (action.testType == TestType.Pass) { - if (action.dstSwap) { - /// @dev calling state variables again to obtain fresh memory values corresponding to - /// DST - (,, vars.underlyingDstToken,) = _targetVaults( - vars.CHAIN_0, - vars.DST_CHAINS[i], - vars.targetVaults[i], - vars.targetFormKinds[i], - vars.targetUnderlyings[i] - ); - vars.liqBridges = vars.targetLiqBridges[i]; - - /// @dev dst swap is performed to ensure tokens reach CoreStateRegistry on deposits - if (action.multiVaults) { - _batchProcessDstSwap( - vars.liqBridges, - vars.CHAIN_0, - aV[i].toChainId, - vars.underlyingDstToken, - vars.multiVaultsPayloadArg.amounts, - action.slippage - ); - } else { - _processDstSwap( - vars.liqBridges[0], - vars.CHAIN_0, - aV[i].toChainId, - vars.underlyingDstToken[0], - vars.singleVaultsPayloadArg.amount, - action.slippage - ); - } - } - /// @dev this is the step where the amounts are updated taking into account the final /// slippage if (action.multiVaults) { - _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg, vars.targetUnderlyings[i]); } else if (singleSuperformsData.length > 0) { - _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, vars.targetUnderlyings[i][0] + ); } vm.recordLogs(); @@ -763,9 +731,11 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { } else if (action.testType == TestType.RevertProcessPayload) { /// @dev this logic is essentially repeated from above if (action.multiVaults) { - _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg, vars.targetUnderlyings[i]); } else if (singleSuperformsData.length > 0) { - _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, vars.targetUnderlyings[i][0] + ); } /// @dev process payload will revert in here success = _processPayload( @@ -780,9 +750,13 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { ) { /// @dev branch used just for reverts of updatePayload (process payload is not even called) if (action.multiVaults) { - success = _updateMultiVaultDepositPayload(vars.multiVaultsPayloadArg); + success = _updateMultiVaultDepositPayload( + vars.multiVaultsPayloadArg, vars.targetUnderlyings[i] + ); } else { - success = _updateSingleVaultDepositPayload(vars.singleVaultsPayloadArg); + success = _updateSingleVaultDepositPayload( + vars.singleVaultsPayloadArg, vars.targetUnderlyings[i][0] + ); } if (!success) { @@ -1359,7 +1333,13 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { return superformIds_; } - function _updateMultiVaultDepositPayload(updateMultiVaultDepositPayloadArgs memory args) internal returns (bool) { + function _updateMultiVaultDepositPayload( + updateMultiVaultDepositPayloadArgs memory args, + uint256[] memory targetUnderlyings + ) + internal + returns (bool) + { uint256 initialFork = vm.activeFork(); vm.selectFork(FORKS[args.targetChainId]); @@ -1369,6 +1349,10 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { int256 dstSwapSlippage; + for (uint256 i; i < len; ++i) { + bridgedTokens[i] = getContract(args.targetChainId, UNDERLYING_TOKENS[targetUnderlyings[i]]); + } + /// @dev slippage calculation for (uint256 i = 0; i < len; ++i) { finalAmounts[i] = args.amounts[i]; @@ -1419,7 +1403,10 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { return true; } - function _updateSingleVaultDepositPayload(updateSingleVaultDepositPayloadArgs memory args) + function _updateSingleVaultDepositPayload( + updateSingleVaultDepositPayloadArgs memory args, + uint256 targetUnderlying + ) internal returns (bool) { @@ -1427,7 +1414,7 @@ abstract contract InvariantProtocolActions is CommonProtocolActions { vm.selectFork(FORKS[args.targetChainId]); uint256 finalAmount; - address bridgedToken; + address bridgedToken = getContract(args.targetChainId, UNDERLYING_TOKENS[targetUnderlying]); finalAmount = args.amount; From c83b3126adb4412972014b3abfce327408e83bad Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:33:23 +0000 Subject: [PATCH 206/210] fix: nits --- lib/ERC1155A | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index e7d53f306..f46fa5420 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 +Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 From aee035d63daefaab4686f65fc46c9bb4d355da73 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:33:31 +0000 Subject: [PATCH 207/210] fix: nits2 --- src/BaseRouter.sol | 12 +++-- src/BaseRouterImplementation.sol | 46 +++++++++++++------ src/EmergencyQueue.sol | 5 +- src/SuperformRouter.sol | 10 +++- .../extensions/TimelockStateRegistry.sol | 16 +++++-- src/crosschain-liquidity/DstSwapper.sol | 2 +- src/interfaces/IBaseRouterImplementation.sol | 3 +- src/interfaces/IBaseStateRegistry.sol | 3 +- src/payments/PaymentHelper.sol | 19 +++++++- 9 files changed, 82 insertions(+), 34 deletions(-) diff --git a/src/BaseRouter.sol b/src/BaseRouter.sol index d65137006..7000011c5 100644 --- a/src/BaseRouter.sol +++ b/src/BaseRouter.sol @@ -4,7 +4,14 @@ pragma solidity ^0.8.23; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { Error } from "src/libraries/Error.sol"; -import "src/types/DataTypes.sol"; +import { + SingleDirectSingleVaultStateReq, + SingleXChainSingleVaultStateReq, + SingleDirectMultiVaultStateReq, + SingleXChainMultiVaultStateReq, + MultiDstSingleVaultStateReq, + MultiDstMultiVaultStateReq +} from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -12,7 +19,6 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa /// @dev Abstract implementation that allows Routers to implement the logic /// @author Zeropoint Labs abstract contract BaseRouter is IBaseRouter { - using SafeERC20 for IERC20; ////////////////////////////////////////////////////////////// @@ -32,7 +38,7 @@ abstract contract BaseRouter is IBaseRouter { if (superRegistry_ == address(0)) { revert Error.ZERO_ADDRESS(); } - + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } diff --git a/src/BaseRouterImplementation.sol b/src/BaseRouterImplementation.sol index 8ff2af0e1..03cf94ca5 100644 --- a/src/BaseRouterImplementation.sol +++ b/src/BaseRouterImplementation.sol @@ -14,7 +14,22 @@ import { DataLib } from "src/libraries/DataLib.sol"; import { Error } from "src/libraries/Error.sol"; import { IPermit2 } from "src/vendor/dragonfly-xyz/IPermit2.sol"; import { LiquidityHandler } from "src/crosschain-liquidity/LiquidityHandler.sol"; -import "src/types/DataTypes.sol"; +import { + SingleDirectSingleVaultStateReq, + SingleXChainSingleVaultStateReq, + SingleDirectMultiVaultStateReq, + SingleXChainMultiVaultStateReq, + MultiDstSingleVaultStateReq, + MultiDstMultiVaultStateReq, + LiqRequest, + InitSingleVaultData, + InitMultiVaultData, + MultiVaultSFData, + SingleVaultSFData, + AMBMessage, + CallbackType, + TransactionType +} from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; @@ -25,7 +40,6 @@ import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draf /// @dev Extends BaseRouter with standard internal execution functions /// @author Zeropoint Labs abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRouter, LiquidityHandler { - using SafeERC20 for IERC20; using DataLib for uint256; @@ -938,18 +952,20 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou /// @dev slippage, amount, paused status validation for (uint256 i; i < len; ++i) { - if(!_validateSuperformData( - superformsData_.superformIds[i], - superformsData_.amounts[i], - superformsData_.outputAmounts[i], - superformsData_.maxSlippages[i], - superformsData_.receiverAddress, - superformsData_.receiverAddressSP, - dstChainId_, - deposit_, - factory, - true - )) { + if ( + !_validateSuperformData( + superformsData_.superformIds[i], + superformsData_.amounts[i], + superformsData_.outputAmounts[i], + superformsData_.maxSlippages[i], + superformsData_.receiverAddress, + superformsData_.receiverAddressSP, + dstChainId_, + deposit_, + factory, + true + ) + ) { return false; } @@ -1120,7 +1136,7 @@ abstract contract BaseRouterImplementation is IBaseRouterImplementation, BaseRou abi.decode(permit2data_, (uint256, uint256, bytes)); v.permit2 = _getPermit2(); - + /// @dev moves the tokens from the user to the router IPermit2(v.permit2).permitTransferFrom( // The permit message. diff --git a/src/EmergencyQueue.sol b/src/EmergencyQueue.sol index 87ea05a28..76d272d18 100644 --- a/src/EmergencyQueue.sol +++ b/src/EmergencyQueue.sol @@ -8,13 +8,12 @@ import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperformFactory } from "src/interfaces/ISuperformFactory.sol"; import { DataLib } from "src/libraries/DataLib.sol"; import { Error } from "src/libraries/Error.sol"; -import "src/types/DataTypes.sol"; +import { InitSingleVaultData, QueuedWithdrawal } from "src/types/DataTypes.sol"; /// @title EmergencyQueue /// @dev Stores withdrawal requests when forms are paused /// @author Zeropoint Labs contract EmergencyQueue is IEmergencyQueue { - using DataLib for uint256; ////////////////////////////////////////////////////////////// @@ -64,7 +63,7 @@ contract EmergencyQueue is IEmergencyQueue { if (superRegistry_ == address(0)) { revert Error.ZERO_ADDRESS(); } - + if (block.chainid > type(uint64).max) { revert Error.BLOCK_CHAIN_ID_OUT_OF_BOUNDS(); } diff --git a/src/SuperformRouter.sol b/src/SuperformRouter.sol index ada715a5d..7f72d6d45 100644 --- a/src/SuperformRouter.sol +++ b/src/SuperformRouter.sol @@ -4,13 +4,19 @@ pragma solidity ^0.8.23; import { BaseRouterImplementation } from "src/BaseRouterImplementation.sol"; import { BaseRouter } from "src/BaseRouter.sol"; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; -import "src/types/DataTypes.sol"; +import { + SingleDirectSingleVaultStateReq, + SingleXChainSingleVaultStateReq, + SingleDirectMultiVaultStateReq, + SingleXChainMultiVaultStateReq, + MultiDstSingleVaultStateReq, + MultiDstMultiVaultStateReq +} from "src/types/DataTypes.sol"; /// @title SuperformRouter /// @dev Routes funds and action information to a remote execution chain /// @author Zeropoint Labs contract SuperformRouter is BaseRouterImplementation { - ////////////////////////////////////////////////////////////// // CONSTRUCTOR // ////////////////////////////////////////////////////////////// diff --git a/src/crosschain-data/extensions/TimelockStateRegistry.sol b/src/crosschain-data/extensions/TimelockStateRegistry.sol index c39fa639c..7bdafea9a 100644 --- a/src/crosschain-data/extensions/TimelockStateRegistry.sol +++ b/src/crosschain-data/extensions/TimelockStateRegistry.sol @@ -17,14 +17,22 @@ import { Error } from "src/libraries/Error.sol"; import { ProofLib } from "src/libraries/ProofLib.sol"; import { DataLib } from "src/libraries/DataLib.sol"; import { PayloadUpdaterLib } from "src/libraries/PayloadUpdaterLib.sol"; -import "src/types/DataTypes.sol"; +import { + InitSingleVaultData, + AMBMessage, + TimelockPayload, + CallbackType, + TransactionType, + PayloadState, + TimelockStatus, + ReturnSingleData +} from "src/types/DataTypes.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; /// @title TimelockStateRegistry /// @dev Handles communication in timelocked forms /// @author Zeropoint Labs contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, ReentrancyGuard { - using DataLib for uint256; using ProofLib for AMBMessage; @@ -57,7 +65,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree } /// @dev ensures only the timelock form can write to a timelock superform - /// @param superformId_ is the superformId of the superform to check + /// @param superformId_ is the superformId of the superform to check modifier onlyTimelockSuperform(uint256 superformId_) { if (!ISuperformFactory(superRegistry.getAddress(keccak256("SUPERFORM_FACTORY"))).isSuperform(superformId_)) { revert Error.SUPERFORM_ID_NONEXISTENT(); @@ -85,7 +93,7 @@ contract TimelockStateRegistry is BaseStateRegistry, ITimelockStateRegistry, Ree // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(ISuperRegistry superRegistry_) BaseStateRegistry(superRegistry_) {} + constructor(ISuperRegistry superRegistry_) BaseStateRegistry(superRegistry_) { } ////////////////////////////////////////////////////////////// // EXTERNAL VIEW FUNCTIONS // diff --git a/src/crosschain-liquidity/DstSwapper.sol b/src/crosschain-liquidity/DstSwapper.sol index f1d006899..2fdf94fb0 100644 --- a/src/crosschain-liquidity/DstSwapper.sol +++ b/src/crosschain-liquidity/DstSwapper.sol @@ -10,7 +10,7 @@ import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { IERC4626Form } from "src/forms/interfaces/IERC4626Form.sol"; import { Error } from "src/libraries/Error.sol"; import { DataLib } from "src/libraries/DataLib.sol"; -import "src/types/DataTypes.sol"; +import { InitSingleVaultData, InitMultiVaultData, PayloadState } from "src/types/DataTypes.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import { ReentrancyGuard } from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; diff --git a/src/interfaces/IBaseRouterImplementation.sol b/src/interfaces/IBaseRouterImplementation.sol index 91c097203..e0ca9fadd 100644 --- a/src/interfaces/IBaseRouterImplementation.sol +++ b/src/interfaces/IBaseRouterImplementation.sol @@ -2,13 +2,12 @@ pragma solidity ^0.8.23; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; -import "src/types/DataTypes.sol"; +import { AMBMessage, LiqRequest, TransactionType } from "src/types/DataTypes.sol"; /// @title IBaseRouterImplementation /// @dev Interface for BaseRouterImplementation /// @author Zeropoint Labs interface IBaseRouterImplementation is IBaseRouter { - ////////////////////////////////////////////////////////////// // STRUCTS // ////////////////////////////////////////////////////////////// diff --git a/src/interfaces/IBaseStateRegistry.sol b/src/interfaces/IBaseStateRegistry.sol index 52c75fa9b..4b43277ed 100644 --- a/src/interfaces/IBaseStateRegistry.sol +++ b/src/interfaces/IBaseStateRegistry.sol @@ -1,13 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.23; -import "src/types/DataTypes.sol"; +import { PayloadState } from "src/types/DataTypes.sol"; /// @title IBaseStateRegistry /// @dev Interface for BaseStateRegistry /// @author ZeroPoint Labs interface IBaseStateRegistry { - ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/payments/PaymentHelper.sol b/src/payments/PaymentHelper.sol index 280367a1e..86dc43a77 100644 --- a/src/payments/PaymentHelper.sol +++ b/src/payments/PaymentHelper.sol @@ -11,7 +11,23 @@ import { Error } from "src/libraries/Error.sol"; import { DataLib } from "src/libraries/DataLib.sol"; import { ProofLib } from "src/libraries/ProofLib.sol"; import { ArrayCastLib } from "src/libraries/ArrayCastLib.sol"; -import "src/types/DataTypes.sol"; +import { + SingleDirectSingleVaultStateReq, + SingleXChainSingleVaultStateReq, + SingleDirectMultiVaultStateReq, + SingleXChainMultiVaultStateReq, + MultiDstSingleVaultStateReq, + MultiDstMultiVaultStateReq, + LiqRequest, + AMBMessage, + MultiVaultSFData, + SingleVaultSFData, + AMBExtraData, + InitMultiVaultData, + InitSingleVaultData, + ReturnMultiData, + ReturnSingleData +} from "src/types/DataTypes.sol"; import { AggregatorV3Interface } from "src/vendor/chainlink/AggregatorV3Interface.sol"; /// @dev interface to read public variable from state registry @@ -23,7 +39,6 @@ interface ReadOnlyBaseRegistry is IBaseStateRegistry { /// @dev Helps estimate the cost for the entire transaction lifecycle /// @author ZeroPoint Labs contract PaymentHelper is IPaymentHelper { - using DataLib for uint256; using ArrayCastLib for LiqRequest; using ArrayCastLib for bool; From 183baeddfd1e94cbbe6f8de4a8bc7ce7ffad5002 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 17:47:53 +0530 Subject: [PATCH 208/210] chore: bring csr under size --- .../extensions/CoreStateRegistry.sol | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/crosschain-data/extensions/CoreStateRegistry.sol b/src/crosschain-data/extensions/CoreStateRegistry.sol index 6be03f106..04761fcb9 100644 --- a/src/crosschain-data/extensions/CoreStateRegistry.sol +++ b/src/crosschain-data/extensions/CoreStateRegistry.sol @@ -34,7 +34,6 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa /// @dev Enables communication between Superform core contracts deployed on all supported networks /// @author Zeropoint Labs contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { - using SafeERC20 for IERC20; using DataLib for uint256; using ProofLib for AMBMessage; @@ -87,7 +86,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { return PayloadUpdaterLib.validateSlippage(finalAmount_, amount_, maxSlippage_); } - + ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // ////////////////////////////////////////////////////////////// @@ -198,9 +197,8 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev mint superPositions for successful deposits or remint for failed withdraws if (callbackType == uint256(CallbackType.RETURN) || callbackType == uint256(CallbackType.FAIL)) { - isMulti == 1 - ? ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).stateMultiSync(message_) - : ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))).stateSync(message_); + ISuperPositions superPositions = ISuperPositions(_getAddress(keccak256("SUPER_POSITIONS"))); + isMulti == 1 ? superPositions.stateMultiSync(message_) : superPositions.stateSync(message_); } else if (callbackType == uint8(CallbackType.INIT)) { /// @dev for initial payload processing bytes memory returnMessage; @@ -313,13 +311,12 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev set to zero to prevent re-entrancy failedDeposits_.lastProposedTimestamp = 0; - IDstSwapper dstSwapper = IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))); uint256 len = failedDeposits_.amounts.length; for (uint256 i; i < len; ++i) { /// @dev refunds the amount to user specified refund address if (failedDeposits_.settleFromDstSwapper[i]) { - dstSwapper.processFailedTx( + IDstSwapper(_getAddress(keccak256("DST_SWAPPER"))).processFailedTx( failedDeposits_.receiverAddress, failedDeposits_.settlementToken[i], failedDeposits_.amounts[i] ); } else { @@ -692,7 +689,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { false, address(superform), multiVaultData_.receiverAddress, - superform.getVaultAsset(), + _getVaultAsset(address(superform)), address(0) ) ); @@ -842,7 +839,7 @@ contract CoreStateRegistry is BaseStateRegistry, ICoreStateRegistry { /// @dev clearing multiVaultData.amounts so that in case that fulfillment is true these amounts /// are not minted multiVaultData.amounts[i] = 0; - failedDeposits[payloadId_].settlementToken.push(IBaseForm(superforms[i]).getVaultAsset()); + failedDeposits[payloadId_].settlementToken.push(_getVaultAsset(superforms[i])); failedDeposits[payloadId_].settleFromDstSwapper.push(false); } } else { From f2d8c9538d92186c55ff51d7ef51adb3e9b68cdb Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 20:50:57 +0530 Subject: [PATCH 209/210] chore: merge from remote remediations repo --- lib/ERC1155A | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index f46fa5420..e7d53f306 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57 +Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 From 749f6f96f99bb2ae13d75eccaed798186abff0d7 Mon Sep 17 00:00:00 2001 From: sujithsomraaj Date: Wed, 27 Dec 2023 20:57:32 +0530 Subject: [PATCH 210/210] chore: update ERC1155A --- lib/ERC1155A | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ERC1155A b/lib/ERC1155A index e7d53f306..f46fa5420 160000 --- a/lib/ERC1155A +++ b/lib/ERC1155A @@ -1 +1 @@ -Subproject commit e7d53f306989ba205c779973d1b5e86755a1b9c0 +Subproject commit f46fa542026b860717d48bd1c09acbb8b68a0b57