@coti-io/coti-contracts 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/access/DataPrivacyFramework/DataPrivacyFramework.sol +1 -1
- package/contracts/access/DataPrivacyFramework/extensions/DataPrivacyFrameworkMpc.sol +1 -1
- package/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow.sol +2 -4
- package/contracts/disperse/disperseToken/MintDisperser.sol +1 -3
- package/contracts/disperse/disperseToken/TokenDisperser.sol +1 -1
- package/contracts/messaging/PrivateMessaging.sol +1 -1
- package/contracts/mocks/access/DataPrivacyFramework/DataPrivacyFrameworkMock.sol +1 -1
- package/contracts/mocks/messaging/PrivateMessagingHarness.sol +1 -1
- package/contracts/mocks/oracle/CotiPriceConsumerMock.sol +1 -1
- package/contracts/mocks/token/ERC20DecimalsMock.sol +1 -1
- package/contracts/mocks/token/ERC20Mock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock.sol +1 -1
- package/contracts/mocks/token/PrivateERC721/PrivateERC721URIStorageMock.sol +1 -1
- package/contracts/mocks/utils/mpc/Arithmetic128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Arithmetic256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/ArithmeticAddTestsContract.sol +196 -0
- package/contracts/mocks/utils/mpc/ArithmeticMulTestsContract.sol +194 -0
- package/contracts/mocks/utils/mpc/ArithmeticSigned128TestsContract.sol +63 -0
- package/contracts/mocks/utils/mpc/ArithmeticSigned256TestsContract.sol +107 -0
- package/contracts/mocks/utils/mpc/ArithmeticSignedNarrowTestsContract.sol +123 -0
- package/contracts/mocks/utils/mpc/ArithmeticSubTestsContract.sol +196 -0
- package/contracts/mocks/utils/mpc/Bitwise128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Bitwise256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/BitwiseTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/CheckedArithmeticWIthOverflowBitTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Comparison128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Comparison1TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Comparison256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Comparison2TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/MinMax128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/MinMax256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/MinMaxTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/MinimalImplementation.sol +1 -1
- package/contracts/mocks/utils/mpc/MinimalProxy.sol +1 -1
- package/contracts/mocks/utils/mpc/Miscellaneous1TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/MiscellaneousTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/MpcOperations128TestContract.sol +1 -1
- package/contracts/mocks/utils/mpc/MpcOperationsTestContract.sol +4 -4
- package/contracts/mocks/utils/mpc/Mux128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Mux256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/OffboardToUserKeyTestContract.sol +1 -1
- package/contracts/mocks/utils/mpc/OnBoard128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/OnBoard256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/PrivacyImplementationV1.sol +1 -1
- package/contracts/mocks/utils/mpc/PrivacyImplementationV2.sol +1 -1
- package/contracts/mocks/utils/mpc/PrivacyProxy.sol +1 -1
- package/contracts/mocks/utils/mpc/Random128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Random256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Shift128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Shift256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/ShiftTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/StringTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Transfer128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/Transfer256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferScalarTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowance64_16TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowance64_32TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowance64_64TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowance64_8TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowanceScalarTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/TransferWithAllowanceTestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract.sol +1 -1
- package/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract.sol +2 -2
- package/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract.sol +1 -1
- package/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.sol +1 -1
- package/contracts/node/CotiNodeRewards.sol +3 -3
- package/contracts/node/SoulboundNodeNFT.sol +1 -2
- package/contracts/onboard/AccountOnboard.sol +1 -1
- package/contracts/oracle/ICotiPriceConsumer.sol +1 -1
- package/contracts/pod/IInbox.sol +231 -0
- package/contracts/pod/IInboxMiner.sol +53 -0
- package/contracts/pod/InboxUser.sol +29 -0
- package/contracts/pod/InboxUserCotiTestnet.sol +13 -0
- package/contracts/pod/PodNetworkConstants.sol +30 -0
- package/contracts/pod/examples/MpcAdder.sol +57 -0
- package/contracts/pod/examples/MpcAdderPausable.sol +25 -0
- package/contracts/pod/examples/MpcAdderPausable.sol.bak +25 -0
- package/contracts/pod/examples/it128/PodAdder128.sol +48 -0
- package/contracts/pod/examples/it256/PodAdder256.sol +48 -0
- package/contracts/pod/fee/IInboxFeeManager.sol +40 -0
- package/contracts/pod/manifest.json +52 -0
- package/contracts/pod/mpc/PodLib.sol +10 -0
- package/contracts/pod/mpc/PodLib128.sol +361 -0
- package/contracts/pod/mpc/PodLib256.sol +361 -0
- package/contracts/pod/mpc/PodLib64.sol +385 -0
- package/contracts/pod/mpc/PodLibBase.sol +72 -0
- package/contracts/pod/mpc/PodUser.sol +58 -0
- package/contracts/pod/mpc/PodUserFuji.sol +14 -0
- package/contracts/pod/mpc/PodUserSepolia.sol +13 -0
- package/contracts/pod/mpc/coti-side/IPodExecutorOps.sol +99 -0
- package/contracts/pod/mpccodec/MpcAbiCodec.sol +482 -0
- package/contracts/pod/privacy/IPodPriceOracle.sol +20 -0
- package/contracts/pod/privacy/IPrivacyPortal.sol +248 -0
- package/contracts/pod/privacy/IPrivacyPortalFactory.sol +88 -0
- package/contracts/pod/privacy/PortalFeeOracle.sol +51 -0
- package/contracts/pod/privacy/PrivacyPortal.sol +871 -0
- package/contracts/pod/privacy/PrivacyPortalFactory.sol +492 -0
- package/contracts/pod/privacy/PrivacyPortalFeeLib.sol +98 -0
- package/contracts/pod/privacy/mocks/CloneHelper.sol +14 -0
- package/contracts/pod/privacy/mocks/MockERC20.sol +26 -0
- package/contracts/pod/privacy/mocks/MockPodERC20ForPortal.sol +160 -0
- package/contracts/pod/privacy/mocks/MockPrivacyPortalFactory.sol +125 -0
- package/contracts/pod/privacy/mocks/MockWrappedNative.sol +24 -0
- package/contracts/pod/token/erc7984/Erc7984Constants.sol +9 -0
- package/contracts/pod/token/erc7984/Erc7984Pointers.sol +29 -0
- package/contracts/pod/token/erc7984/IERC7984.sol +69 -0
- package/contracts/pod/token/erc7984/IERC7984PortalWrapper.sol +31 -0
- package/contracts/pod/token/erc7984/PodErc7984Mixin.sol +125 -0
- package/contracts/pod/token/erc7984/README.md +60 -0
- package/contracts/pod/token/perc20/IPodERC20.sol +298 -0
- package/contracts/pod/token/perc20/PodERC20.sol +1021 -0
- package/contracts/pod/token/perc20/PodErc20Mintable.sol +88 -0
- package/contracts/pod/token/perc20/PodErc20MintableInitializable.sol +42 -0
- package/contracts/pod/token/perc20/cotiside/IPodErc20CotiSide.sol +88 -0
- package/contracts/pod/token/perc20/cotiside/PodErc20CotiMother.sol +529 -0
- package/contracts/pod/utils/IWrappedNative.sol +11 -0
- package/contracts/privacyBridge/PrivacyBridge.sol +5 -5
- package/contracts/privacyBridge/PrivacyBridgeCotiNative.sol +1 -1
- package/contracts/privacyBridge/PrivacyBridgeERC20.sol +1 -1
- package/contracts/privacyBridge/PrivacyBridgeUSDCe.sol +1 -1
- package/contracts/privacyBridge/PrivacyBridgeUSDT.sol +1 -1
- package/contracts/privacyBridge/PrivacyBridgeWADA.sol +1 -1
- package/contracts/privacyBridge/PrivacyBridgeWBTC.sol +1 -1
- package/contracts/privacyBridge/PrivacyBridgeWETH.sol +1 -1
- package/contracts/privacyBridge/PrivacyBridgegCoti.sol +1 -1
- package/contracts/token/PrivateERC20/IPrivateERC20.sol +1 -1
- package/contracts/token/PrivateERC20/ITokenReceiver.sol +1 -1
- package/contracts/token/PrivateERC20/ITokenReceiverEncrypted.sol +1 -1
- package/contracts/token/PrivateERC20/PrivateERC20.sol +5 -5
- package/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC.sol +1 -1
- package/contracts/token/PrivateERC20/tokens/PrivateCOTI.sol +1 -1
- package/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken.sol +1 -1
- package/contracts/token/PrivateERC20/tokens/PrivateTetherUSD.sol +1 -1
- package/contracts/token/PrivateERC20/tokens/PrivateWrappedADA.sol +1 -1
- package/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC.sol +1 -1
- package/contracts/token/PrivateERC20/tokens/PrivateWrappedEther.sol +1 -1
- package/contracts/token/PrivateERC721/IERC721Errors.sol +1 -1
- package/contracts/token/PrivateERC721/PrivateERC721.sol +1 -1
- package/contracts/token/PrivateERC721/extensions/IPrivateERC721URIStorage.sol +1 -1
- package/contracts/token/PrivateERC721/extensions/PrivateERC721URIStorage.sol +1 -1
- package/contracts/token/points/CotiTokenPoints004.sol +43 -0
- package/contracts/utils/mpc/MpcCore.sol +610 -1
- package/contracts/utils/mpc/MpcInterface.sol +1 -1
- package/hardhat.config.ts +5 -14
- package/package.json +4 -4
- package/scripts/deployCotiTokenPoints004.ts +61 -0
- package/scripts/deployFixedRatioCoinDisperserUnlimitedWindow.ts +68 -0
- package/scripts/verifyCotiTokenPoints004.ts +123 -0
- package/scripts/verifyFixedRatioCoinDisperserUnlimitedWindow.ts +112 -0
- package/test/messaging/PrivateMessaging.test.ts +5 -5
- package/test/pod/privacy/PrivacyPortal.access.test.ts +756 -0
- package/test/pod/privacy/PrivacyPortal.recovery.test.ts +263 -0
- package/test/privacyBridge/UnifiedPrivacyBridges.test.cjs +5 -3
- package/test/utils/mpc/CheckedSignedArithmetic256.test.ts +163 -0
- package/test/utils/mpc/NegativeCases.test.ts +3 -3
- package/test/utils/mpc/Precompile.test.ts +6 -6
- package/typechain-types/@openzeppelin/contracts/access/AccessControl.ts +2 -2
- package/typechain-types/@openzeppelin/contracts/access/IAccessControl.ts +2 -2
- package/typechain-types/@openzeppelin/contracts/access/extensions/AccessControlEnumerable.ts +375 -0
- package/typechain-types/@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.ts +329 -0
- package/typechain-types/@openzeppelin/contracts/access/extensions/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/access/index.ts +2 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/IERC1363.ts +412 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/IERC5267.ts +151 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
- package/typechain-types/@openzeppelin/contracts/interfaces/index.ts +4 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/ERC20.ts +6 -50
- package/typechain-types/@openzeppelin/contracts/token/ERC20/IERC20.ts +6 -6
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.ts +313 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.ts +356 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.ts +423 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.ts +6 -6
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/index.ts +3 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/index.ts +2 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/utils/index.ts +4 -0
- package/typechain-types/@openzeppelin/contracts/utils/Nonces.ts +85 -0
- package/typechain-types/@openzeppelin/contracts/utils/Pausable.ts +150 -0
- package/typechain-types/@openzeppelin/contracts/utils/ReentrancyGuard.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/utils/ShortStrings.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/utils/Strings.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/utils/cryptography/ECDSA.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/utils/cryptography/EIP712.ts +151 -0
- package/typechain-types/@openzeppelin/contracts/utils/cryptography/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/utils/index.ts +9 -0
- package/typechain-types/@openzeppelin/contracts/utils/math/SafeCast.ts +69 -0
- package/typechain-types/@openzeppelin/contracts/utils/math/index.ts +4 -0
- package/typechain-types/contracts/mocks/token/ERC20DecimalsMock.ts +6 -50
- package/typechain-types/contracts/mocks/token/ERC20Mock.ts +6 -50
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.ts +16 -2
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock.ts +2 -2
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock.ts +2 -2
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.ts +2 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridge.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeCotiNative.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeERC20.sol/PrivacyBridgeERC20.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeUSDCe.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeUSDT.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeWADA.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeWBTC.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeWETH.ts +16 -2
- package/typechain-types/contracts/privacyBridge/PrivacyBridgegCoti.ts +16 -2
- package/typechain-types/contracts/token/PrivateERC20/PrivateERC20.ts +2 -2
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC.ts +2 -2
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateCOTI.ts +2 -2
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken.ts +2 -2
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateTetherUSD.ts +2 -2
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedADA.ts +2 -2
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC.ts +2 -2
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedEther.ts +2 -2
- package/typechain-types/contracts/token/index.ts +2 -0
- package/typechain-types/contracts/token/points/CotiTokenPoints004.sol/COTITokenPoints004.ts +826 -0
- package/typechain-types/contracts/token/points/CotiTokenPoints004.ts +826 -0
- package/typechain-types/contracts/token/points/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/AccessControl__factory.ts +22 -1
- package/typechain-types/factories/@openzeppelin/contracts/access/IAccessControl__factory.ts +22 -1
- package/typechain-types/factories/@openzeppelin/contracts/access/Ownable__factory.ts +22 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/extensions/AccessControlEnumerable__factory.ts +316 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/extensions/IAccessControlEnumerable__factory.ts +265 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/extensions/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +1 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC1363__factory.ts +393 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC5267__factory.ts +71 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors__factory.ts +127 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors__factory.ts +111 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors__factory.ts +128 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
- package/typechain-types/factories/@openzeppelin/contracts/interfaces/index.ts +3 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/ERC20__factory.ts +84 -110
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/IERC20__factory.ts +3 -3
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable__factory.ts +364 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable__factory.ts +382 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit__factory.ts +540 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata__factory.ts +3 -3
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/index.ts +3 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/index.ts +1 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/utils/SafeERC20__factory.ts +96 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/utils/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/ERC721__factory.ts +98 -59
- package/typechain-types/factories/@openzeppelin/contracts/utils/Nonces__factory.ts +57 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/Pausable__factory.ts +71 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/ReentrancyGuard__factory.ts +30 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/ShortStrings__factory.ts +83 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/Strings__factory.ts +90 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/cryptography/ECDSA__factory.ts +91 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/cryptography/EIP712__factory.ts +87 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/cryptography/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/index.ts +7 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/math/SafeCast__factory.ts +118 -0
- package/typechain-types/factories/@openzeppelin/contracts/utils/math/index.ts +4 -0
- package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperserLeftoverS1__factory.ts +12 -1
- package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow__factory.ts +39 -1
- package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperser__factory.ts +12 -1
- package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser__factory.ts +23 -1
- package/typechain-types/factories/contracts/disperse/disperseToken/TokenDisperser__factory.ts +12 -1
- package/typechain-types/factories/contracts/messaging/PrivateMessaging__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/messaging/PrivateMessagingHarness__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/token/ERC20DecimalsMock__factory.ts +90 -52
- package/typechain-types/factories/contracts/mocks/token/ERC20Mock__factory.ts +90 -52
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock__factory.ts +90 -2
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock__factory.ts +28 -2
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock__factory.ts +28 -2
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20Mock__factory.ts +28 -2
- package/typechain-types/factories/contracts/mocks/token/PrivateERC721/PrivateERC721URIStorageMock__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/ArithmeticTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/BitwiseTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmeticWIthOverflowBitTestsContract.sol/CheckedArithmeticWithOverflowBitTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison1TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison2TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinMaxTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinimalImplementation__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous1TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MiscellaneousTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MpcOperations128TestContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MpcOperationsTestContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Mux128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Mux256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/OffboardToUserKeyTestContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV1__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV2__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Random128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Random256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Shift128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Shift256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/ShiftTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/StringTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Transfer128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Transfer256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferScalarTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_16TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_32TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_64TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_8TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowanceScalarTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowanceTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock__factory.ts +1 -1
- package/typechain-types/factories/contracts/node/CotiNodeRewards__factory.ts +28 -1
- package/typechain-types/factories/contracts/node/SoulboundNodeNFT.sol/SoulboundNodeNFT__factory.ts +126 -1
- package/typechain-types/factories/contracts/onboard/AccountOnboard__factory.ts +1 -1
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeCotiNative__factory.ts +79 -2
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeERC20.sol/PrivacyBridgeERC20__factory.ts +89 -1
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeUSDCe__factory.ts +90 -2
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeUSDT__factory.ts +90 -2
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWADA__factory.ts +90 -2
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWBTC__factory.ts +90 -2
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWETH__factory.ts +90 -2
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridge__factory.ts +78 -1
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgegCoti__factory.ts +90 -2
- package/typechain-types/factories/contracts/token/PrivateERC20/PrivateERC20__factory.ts +27 -1
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC__factory.ts +28 -2
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken__factory.ts +28 -2
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateCOTI__factory.ts +28 -2
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateTetherUSD__factory.ts +28 -2
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedADA__factory.ts +28 -2
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC__factory.ts +28 -2
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedEther__factory.ts +28 -2
- package/typechain-types/factories/contracts/token/index.ts +1 -0
- package/typechain-types/factories/contracts/token/points/CotiTokenPoints004.sol/COTITokenPoints004__factory.ts +992 -0
- package/typechain-types/factories/contracts/token/points/CotiTokenPoints004__factory.ts +992 -0
- package/typechain-types/factories/contracts/token/points/index.ts +4 -0
- package/typechain-types/factories/contracts/utils/mpc/MpcCore__factory.ts +1 -1
- package/typechain-types/hardhat.d.ts +360 -0
- package/typechain-types/index.ts +36 -4
- package/contracts/mocks/utils/mpc/ArithmeticTestsContract.sol +0 -408
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
5
|
+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
6
|
+
import "@openzeppelin/contracts/utils/Pausable.sol";
|
|
7
|
+
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
|
8
|
+
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
|
|
9
|
+
|
|
10
|
+
import "../token/perc20/IPodERC20.sol";
|
|
11
|
+
import "../token/erc7984/IERC7984PortalWrapper.sol";
|
|
12
|
+
import "../utils/IWrappedNative.sol";
|
|
13
|
+
import "./IPrivacyPortal.sol";
|
|
14
|
+
import "./IPrivacyPortalFactory.sol";
|
|
15
|
+
import "./IPodPriceOracle.sol";
|
|
16
|
+
import "./PrivacyPortalFeeLib.sol";
|
|
17
|
+
|
|
18
|
+
/// @title PrivacyPortal
|
|
19
|
+
/// @notice Locks a public ERC20 and mints/burns its PoD private pToken counterpart.
|
|
20
|
+
/// @dev The portal never reads private balances. It only reacts to successful pToken callbacks and records public bridge obligations.
|
|
21
|
+
/// Split deploy-then-initialize is unsafe on clones; use {PrivacyPortalFactory.createPortal} or an equivalent atomic path.
|
|
22
|
+
/// Admin and operator privileges live on {factory} only — portals have no local Ownable.
|
|
23
|
+
contract PrivacyPortal is IPrivacyPortal, IERC7984PortalWrapper, Pausable, ReentrancyGuard, Initializable {
|
|
24
|
+
using SafeERC20 for IERC20;
|
|
25
|
+
using PrivacyPortalFeeLib for bytes32;
|
|
26
|
+
|
|
27
|
+
/// @notice Public ERC20 collateral locked by this portal.
|
|
28
|
+
IERC20 public underlyingToken;
|
|
29
|
+
/// @notice Private pToken minted and burned against the underlying collateral.
|
|
30
|
+
IPodERC20 public pToken;
|
|
31
|
+
/// @notice Factory that created this portal (fees, pause, blacklist, rescue, operators).
|
|
32
|
+
address public factory;
|
|
33
|
+
/// @notice Token decimals mirrored from the underlying/pToken pair.
|
|
34
|
+
uint8 public decimals;
|
|
35
|
+
/// @notice When true, {depositNative} wraps native coin; withdrawals release wrapped underlying ERC20.
|
|
36
|
+
bool public nativeWrappedUnderlying;
|
|
37
|
+
|
|
38
|
+
/// @notice Soft deposit switch (factory operator); independent of pause / factory pause.
|
|
39
|
+
bool public isDepositEnabled = true;
|
|
40
|
+
/// @notice Per-portal blacklist (ORs with factory blacklist).
|
|
41
|
+
mapping(address => bool) public blacklisted;
|
|
42
|
+
|
|
43
|
+
/// @notice Optional per-portal deposit fee override; bytes32(0) inherits factory default.
|
|
44
|
+
bytes32 internal depositFeeOverridePacked;
|
|
45
|
+
/// @notice Optional per-portal withdraw fee override; bytes32(0) inherits factory default.
|
|
46
|
+
bytes32 internal withdrawFeeOverridePacked;
|
|
47
|
+
/// @notice Accumulated portal protocol fees awaiting sweep.
|
|
48
|
+
uint256 public accumulatedPortalFees;
|
|
49
|
+
/// @notice pToken amount held in portal custody pending owner batch burn.
|
|
50
|
+
uint256 public pendingBurnAmount;
|
|
51
|
+
/// @notice Monotonic nonce used to derive withdrawal ids.
|
|
52
|
+
uint256 public withdrawalNonce;
|
|
53
|
+
|
|
54
|
+
/// @notice Maximum amount that can be deposited in a single transaction.
|
|
55
|
+
uint256 public maxDepositAmount;
|
|
56
|
+
/// @notice Maximum amount that can be withdrawn in a single transaction.
|
|
57
|
+
uint256 public maxWithdrawAmount;
|
|
58
|
+
/// @notice Minimum amount required for a deposit.
|
|
59
|
+
uint256 public minDepositAmount;
|
|
60
|
+
/// @notice Minimum amount required for a withdrawal.
|
|
61
|
+
uint256 public minWithdrawAmount;
|
|
62
|
+
|
|
63
|
+
/// @notice Withdrawal state by withdrawal id.
|
|
64
|
+
mapping(bytes32 => Withdrawal) public withdrawals;
|
|
65
|
+
/// @notice Deposit escrow by mint request id.
|
|
66
|
+
mapping(bytes32 => DepositEscrow) public depositEscrows;
|
|
67
|
+
|
|
68
|
+
/// @notice Public ERC20 was locked and an async private pToken mint was requested.
|
|
69
|
+
event DepositRequested(
|
|
70
|
+
address indexed user,
|
|
71
|
+
address indexed recipient,
|
|
72
|
+
uint256 amount,
|
|
73
|
+
bytes32 indexed mintRequestId
|
|
74
|
+
);
|
|
75
|
+
/// @notice Failed mint collateral was returned to the depositor.
|
|
76
|
+
event DepositRefunded(address indexed user, bytes32 indexed mintRequestId, uint256 amount);
|
|
77
|
+
/// @notice Public withdrawal was requested and a pToken transfer-to-portal request was submitted.
|
|
78
|
+
event WithdrawalRequested(
|
|
79
|
+
bytes32 indexed withdrawalId,
|
|
80
|
+
address indexed user,
|
|
81
|
+
address indexed recipient,
|
|
82
|
+
uint256 amount,
|
|
83
|
+
bytes32 transferRequestId
|
|
84
|
+
);
|
|
85
|
+
/// @notice Pending withdrawal was cancelled after a failed pToken transfer.
|
|
86
|
+
event WithdrawalFailed(bytes32 indexed withdrawalId, bytes32 indexed transferRequestId);
|
|
87
|
+
/// @notice Underlying collateral was released to the withdrawal recipient.
|
|
88
|
+
event WithdrawalReleased(bytes32 indexed withdrawalId, address indexed recipient, uint256 amount);
|
|
89
|
+
/// @notice Portal protocol fee collected on a user-facing entry point.
|
|
90
|
+
/// @dev Prefer {OperationFeesPaid} for offline indexing of portal vs PoD fee legs.
|
|
91
|
+
event PortalFeeCollected(address indexed payer, uint256 amount, bool isDeposit);
|
|
92
|
+
/// @notice Full native-fee breakdown for a deposit or withdraw (offline fee accounting).
|
|
93
|
+
/// @param payer User who paid `msg.value`.
|
|
94
|
+
/// @param correlationId Mint `requestId` (deposit/wrap) or `withdrawalId` (withdraw).
|
|
95
|
+
/// @param isDeposit True for deposit/wrap; false for withdraw.
|
|
96
|
+
/// @param isNativeWrap True when the deposit wrapped native coin into the underlying.
|
|
97
|
+
/// @param portalFee Protocol fee retained by this portal (native wei).
|
|
98
|
+
/// @param podFee Native wei forwarded to the pToken/inbox for the async PoD leg.
|
|
99
|
+
/// @param podCallbackFee Native wei reserved for the PoD callback slice within `podFee`.
|
|
100
|
+
/// @param amount Principal amount in underlying token units (not a fee).
|
|
101
|
+
event OperationFeesPaid(
|
|
102
|
+
address indexed payer,
|
|
103
|
+
bytes32 indexed correlationId,
|
|
104
|
+
bool indexed isDeposit,
|
|
105
|
+
bool isNativeWrap,
|
|
106
|
+
uint256 portalFee,
|
|
107
|
+
uint256 podFee,
|
|
108
|
+
uint256 podCallbackFee,
|
|
109
|
+
uint256 amount
|
|
110
|
+
);
|
|
111
|
+
/// @notice pTokens from a release were queued for batch burn.
|
|
112
|
+
event PendingBurnIncreased(bytes32 indexed withdrawalId, uint256 amount, uint256 pendingBurnAmount);
|
|
113
|
+
/// @notice Owner submitted a batch burn for accumulated pTokens.
|
|
114
|
+
event BatchBurnSubmitted(address indexed caller, uint256 amount, bytes32 indexed burnRequestId);
|
|
115
|
+
/// @notice Portal protocol fees swept to the factory fee recipient.
|
|
116
|
+
event PortalFeesWithdrawn(address indexed recipient, uint256 amount);
|
|
117
|
+
/// @notice Per-portal fee override updated.
|
|
118
|
+
event PortalFeeOverrideUpdated(bool indexed isDeposit, bytes32 packedConfig);
|
|
119
|
+
/// @notice Per-portal fee override cleared.
|
|
120
|
+
event PortalFeeOverrideCleared(bool indexed isDeposit);
|
|
121
|
+
/// @notice Factory binding set at initialize (immutable thereafter).
|
|
122
|
+
event FactorySet(address indexed factory);
|
|
123
|
+
/// @notice Per-portal deposit/withdraw limits changed.
|
|
124
|
+
event LimitsUpdated(
|
|
125
|
+
uint256 minDeposit,
|
|
126
|
+
uint256 maxDeposit,
|
|
127
|
+
uint256 minWithdraw,
|
|
128
|
+
uint256 maxWithdraw
|
|
129
|
+
);
|
|
130
|
+
/// @notice Native token was rescued to the factory rescue recipient while paused.
|
|
131
|
+
event NativeRescued(address indexed rescueRecipient, uint256 amount);
|
|
132
|
+
/// @notice ERC20 was rescued to the factory rescue recipient while paused.
|
|
133
|
+
event ERC20Rescued(address indexed token, address indexed rescueRecipient, uint256 amount);
|
|
134
|
+
/// @notice Soft deposit-enabled flag changed.
|
|
135
|
+
event DepositEnabledUpdated(bool enabled);
|
|
136
|
+
/// @notice Address added to the portal blacklist.
|
|
137
|
+
event Blacklisted(address indexed account, address indexed by);
|
|
138
|
+
/// @notice Address removed from the portal blacklist.
|
|
139
|
+
event UnBlacklisted(address indexed account, address indexed by);
|
|
140
|
+
|
|
141
|
+
/// @notice A required address was zero.
|
|
142
|
+
error InvalidAddress();
|
|
143
|
+
/// @notice Amount argument was zero.
|
|
144
|
+
error InvalidAmount();
|
|
145
|
+
/// @notice `msg.value` did not match the expected fee.
|
|
146
|
+
error IncorrectFee(uint256 expected, uint256 actual);
|
|
147
|
+
/// @notice Caller was not the configured pToken.
|
|
148
|
+
error OnlyPToken(address caller);
|
|
149
|
+
/// @notice Withdrawal id is not known.
|
|
150
|
+
error UnknownWithdrawal(bytes32 withdrawalId);
|
|
151
|
+
/// @notice Withdrawal is not in the pending-transfer state.
|
|
152
|
+
error WithdrawalNotPending(bytes32 withdrawalId, WithdrawalStatus status);
|
|
153
|
+
/// @notice Requested batch burn exceeds pending burn amount.
|
|
154
|
+
error PendingBurnTooLow(uint256 pending, uint256 requested);
|
|
155
|
+
/// @notice Portal fee below configured floor.
|
|
156
|
+
error InsufficientPortalFee(uint256 expectedFloor, uint256 actual);
|
|
157
|
+
/// @notice Portal fee above configured max.
|
|
158
|
+
error ExcessivePortalFee(uint256 maxFee, uint256 actual);
|
|
159
|
+
/// @notice Insufficient accumulated portal fees to sweep.
|
|
160
|
+
error InsufficientAccumulatedFees(uint256 accumulated, uint256 requested);
|
|
161
|
+
/// @notice Pause controller reports withdrawals are paused.
|
|
162
|
+
error WithdrawalsPaused();
|
|
163
|
+
/// @notice Pause controller reports deposits are paused.
|
|
164
|
+
error DepositsPaused();
|
|
165
|
+
/// @notice pToken transfer request has not succeeded yet.
|
|
166
|
+
error PTokenTransferNotSuccessful(bytes32 requestId, IPodERC20.RequestStatus status);
|
|
167
|
+
/// @notice Deposit escrow is missing or not eligible for the requested action.
|
|
168
|
+
error DepositEscrowInvalid(bytes32 requestId, DepositEscrowStatus status);
|
|
169
|
+
/// @notice Mint request is not {IPodERC20.RequestStatus.SystemFailed}, so escrow cannot be refunded.
|
|
170
|
+
error DepositMintNotFailed(bytes32 requestId, IPodERC20.RequestStatus status);
|
|
171
|
+
/// @notice Transfer request is not Failed/SystemFailed, so withdrawal cannot be cancelled.
|
|
172
|
+
error WithdrawTransferNotFailed(bytes32 requestId, IPodERC20.RequestStatus status);
|
|
173
|
+
/// @notice Portal underlying is not configured for native wrap deposits.
|
|
174
|
+
error NativeWrapDisabled();
|
|
175
|
+
/// @notice Factory pause controller is not configured.
|
|
176
|
+
error FactoryNotConfigured();
|
|
177
|
+
/// @notice Caller is on the factory blacklist.
|
|
178
|
+
error AddressBlacklisted(address account);
|
|
179
|
+
/// @notice Deposit amount is below the configured minimum.
|
|
180
|
+
error DepositBelowMinimum();
|
|
181
|
+
/// @notice Deposit amount exceeds the configured maximum.
|
|
182
|
+
error DepositExceedsMaximum();
|
|
183
|
+
/// @notice Withdraw amount is below the configured minimum.
|
|
184
|
+
error WithdrawBelowMinimum();
|
|
185
|
+
/// @notice Withdraw amount exceeds the configured maximum.
|
|
186
|
+
error WithdrawExceedsMaximum();
|
|
187
|
+
/// @notice Invalid min/max limit configuration.
|
|
188
|
+
error InvalidLimitConfiguration();
|
|
189
|
+
/// @notice Soft deposit switch is off.
|
|
190
|
+
error DepositDisabled();
|
|
191
|
+
/// @notice Caller is not a factory {OPERATOR_ROLE} holder.
|
|
192
|
+
error OnlyFactoryOperator(address caller);
|
|
193
|
+
/// @notice Caller is not a factory {DEFAULT_ADMIN_ROLE} holder.
|
|
194
|
+
error OnlyFactoryAdmin(address caller);
|
|
195
|
+
/// @notice Cannot rescue the paired pToken.
|
|
196
|
+
error CannotRescuePToken();
|
|
197
|
+
/// @notice Native transfer failed.
|
|
198
|
+
error EthTransferFailed();
|
|
199
|
+
|
|
200
|
+
/// @notice Lock implementation so it cannot be initialized.
|
|
201
|
+
constructor() {
|
|
202
|
+
_disableInitializers();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/// @notice Accept native funds for portal fees or accidental recovery.
|
|
206
|
+
receive() external payable {}
|
|
207
|
+
|
|
208
|
+
function initialize(
|
|
209
|
+
address underlyingToken_,
|
|
210
|
+
address pToken_,
|
|
211
|
+
uint8 decimals_,
|
|
212
|
+
bool nativeWrappedUnderlying_,
|
|
213
|
+
address factory_
|
|
214
|
+
) external initializer override {
|
|
215
|
+
if (underlyingToken_ == address(0) || pToken_ == address(0) || factory_ == address(0)) {
|
|
216
|
+
revert InvalidAddress();
|
|
217
|
+
}
|
|
218
|
+
underlyingToken = IERC20(underlyingToken_);
|
|
219
|
+
pToken = IPodERC20(pToken_);
|
|
220
|
+
decimals = decimals_;
|
|
221
|
+
nativeWrappedUnderlying = nativeWrappedUnderlying_;
|
|
222
|
+
isDepositEnabled = true;
|
|
223
|
+
maxDepositAmount = type(uint256).max;
|
|
224
|
+
maxWithdrawAmount = type(uint256).max;
|
|
225
|
+
minDepositAmount = 1;
|
|
226
|
+
minWithdrawAmount = 1;
|
|
227
|
+
factory = factory_;
|
|
228
|
+
emit FactorySet(factory_);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/// @notice Factory-admin hard-pause for this portal instance (enables rescue). Checked before factory pause.
|
|
232
|
+
function pause() external onlyFactoryAdmin {
|
|
233
|
+
_pause();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/// @notice Factory-admin unpause for this portal instance.
|
|
237
|
+
function unpause() external onlyFactoryAdmin {
|
|
238
|
+
_unpause();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/// @notice Soft deposit enable/disable (factory operator); does not enable rescue.
|
|
242
|
+
function setIsDepositEnabled(bool enabled) external onlyFactoryOperator {
|
|
243
|
+
isDepositEnabled = enabled;
|
|
244
|
+
emit DepositEnabledUpdated(enabled);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/// @notice Add an address to this portal's blacklist.
|
|
248
|
+
function addToBlacklist(address account) external onlyFactoryAdmin {
|
|
249
|
+
if (account == address(0)) {
|
|
250
|
+
revert InvalidAddress();
|
|
251
|
+
}
|
|
252
|
+
blacklisted[account] = true;
|
|
253
|
+
emit Blacklisted(account, msg.sender);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/// @notice Remove an address from this portal's blacklist.
|
|
257
|
+
function removeFromBlacklist(address account) external onlyFactoryAdmin {
|
|
258
|
+
if (account == address(0)) {
|
|
259
|
+
revert InvalidAddress();
|
|
260
|
+
}
|
|
261
|
+
blacklisted[account] = false;
|
|
262
|
+
emit UnBlacklisted(account, msg.sender);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/// @notice Update per-portal deposit and withdrawal amount limits.
|
|
266
|
+
/// @dev Setting `maxDeposit` or `maxWithdraw` to zero disables that operation.
|
|
267
|
+
function setLimits(
|
|
268
|
+
uint256 minDeposit,
|
|
269
|
+
uint256 maxDeposit,
|
|
270
|
+
uint256 minWithdraw,
|
|
271
|
+
uint256 maxWithdraw
|
|
272
|
+
) external onlyFactoryAdmin {
|
|
273
|
+
if (minDeposit > maxDeposit) {
|
|
274
|
+
revert InvalidLimitConfiguration();
|
|
275
|
+
}
|
|
276
|
+
if (minWithdraw > maxWithdraw) {
|
|
277
|
+
revert InvalidLimitConfiguration();
|
|
278
|
+
}
|
|
279
|
+
minDepositAmount = minDeposit;
|
|
280
|
+
maxDepositAmount = maxDeposit;
|
|
281
|
+
minWithdrawAmount = minWithdraw;
|
|
282
|
+
maxWithdrawAmount = maxWithdraw;
|
|
283
|
+
emit LimitsUpdated(minDeposit, maxDeposit, minWithdraw, maxWithdraw);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/// @inheritdoc IPrivacyPortal
|
|
287
|
+
function setDepositFee(uint256 fixedFee, uint256 percentageBps, uint256 maxFee) external onlyFactoryOperator {
|
|
288
|
+
bytes32 packed = PrivacyPortalFeeLib.packFeeConfig(fixedFee, percentageBps, maxFee);
|
|
289
|
+
depositFeeOverridePacked = packed;
|
|
290
|
+
emit PortalFeeOverrideUpdated(true, packed);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/// @inheritdoc IPrivacyPortal
|
|
294
|
+
function setWithdrawFee(uint256 fixedFee, uint256 percentageBps, uint256 maxFee) external onlyFactoryOperator {
|
|
295
|
+
bytes32 packed = PrivacyPortalFeeLib.packFeeConfig(fixedFee, percentageBps, maxFee);
|
|
296
|
+
withdrawFeeOverridePacked = packed;
|
|
297
|
+
emit PortalFeeOverrideUpdated(false, packed);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/// @inheritdoc IPrivacyPortal
|
|
301
|
+
function clearDepositFeeOverride() external onlyFactoryOperator {
|
|
302
|
+
depositFeeOverridePacked = bytes32(0);
|
|
303
|
+
emit PortalFeeOverrideCleared(true);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/// @inheritdoc IPrivacyPortal
|
|
307
|
+
function clearWithdrawFeeOverride() external onlyFactoryOperator {
|
|
308
|
+
withdrawFeeOverridePacked = bytes32(0);
|
|
309
|
+
emit PortalFeeOverrideCleared(false);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/// @inheritdoc IPrivacyPortal
|
|
313
|
+
function deposit(
|
|
314
|
+
address recipient,
|
|
315
|
+
uint256 amount,
|
|
316
|
+
uint256 portalFee,
|
|
317
|
+
uint256 mintCallbackFee
|
|
318
|
+
) external payable override nonReentrant returns (bytes32 requestId) {
|
|
319
|
+
return _deposit(recipient, amount, portalFee, mintCallbackFee);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function _deposit(address recipient, uint256 amount, uint256 portalFee, uint256 mintCallbackFee)
|
|
323
|
+
private
|
|
324
|
+
returns (bytes32 requestId)
|
|
325
|
+
{
|
|
326
|
+
_checkDepositsNotPaused();
|
|
327
|
+
_checkNotBlacklisted();
|
|
328
|
+
if (recipient == address(0)) {
|
|
329
|
+
revert InvalidAddress();
|
|
330
|
+
}
|
|
331
|
+
if (amount == 0) {
|
|
332
|
+
revert InvalidAmount();
|
|
333
|
+
}
|
|
334
|
+
_checkDepositLimits(amount);
|
|
335
|
+
|
|
336
|
+
_validateAndCollectPortalFee(portalFee, amount, true);
|
|
337
|
+
if (msg.value <= portalFee) {
|
|
338
|
+
revert IncorrectFee(portalFee + 1, msg.value);
|
|
339
|
+
}
|
|
340
|
+
uint256 mintFee = msg.value - portalFee;
|
|
341
|
+
|
|
342
|
+
underlyingToken.safeTransferFrom(msg.sender, address(this), amount);
|
|
343
|
+
requestId = pToken.mint{value: mintFee}(recipient, amount, mintCallbackFee);
|
|
344
|
+
depositEscrows[requestId] = DepositEscrow({
|
|
345
|
+
user: msg.sender,
|
|
346
|
+
recipient: recipient,
|
|
347
|
+
amount: amount,
|
|
348
|
+
status: DepositEscrowStatus.Pending
|
|
349
|
+
});
|
|
350
|
+
emit DepositRequested(msg.sender, recipient, amount, requestId);
|
|
351
|
+
emit WrapRequested(msg.sender, recipient, amount, requestId);
|
|
352
|
+
emit OperationFeesPaid(
|
|
353
|
+
msg.sender, requestId, true, false, portalFee, mintFee, mintCallbackFee, amount
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// @inheritdoc IPrivacyPortal
|
|
358
|
+
function depositNative(
|
|
359
|
+
address recipient,
|
|
360
|
+
uint256 amount,
|
|
361
|
+
uint256 portalFee,
|
|
362
|
+
uint256 mintCallbackFee
|
|
363
|
+
) external payable override nonReentrant returns (bytes32 requestId) {
|
|
364
|
+
if (!nativeWrappedUnderlying) {
|
|
365
|
+
revert NativeWrapDisabled();
|
|
366
|
+
}
|
|
367
|
+
_checkDepositsNotPaused();
|
|
368
|
+
_checkNotBlacklisted();
|
|
369
|
+
if (recipient == address(0)) {
|
|
370
|
+
revert InvalidAddress();
|
|
371
|
+
}
|
|
372
|
+
if (amount == 0) {
|
|
373
|
+
revert InvalidAmount();
|
|
374
|
+
}
|
|
375
|
+
_checkDepositLimits(amount);
|
|
376
|
+
|
|
377
|
+
_validateAndCollectPortalFee(portalFee, amount, true);
|
|
378
|
+
if (msg.value <= amount + portalFee) {
|
|
379
|
+
revert IncorrectFee(amount + portalFee + 1, msg.value);
|
|
380
|
+
}
|
|
381
|
+
uint256 mintFee = msg.value - amount - portalFee;
|
|
382
|
+
|
|
383
|
+
IWrappedNative(address(underlyingToken)).deposit{value: amount}();
|
|
384
|
+
requestId = pToken.mint{value: mintFee}(recipient, amount, mintCallbackFee);
|
|
385
|
+
depositEscrows[requestId] = DepositEscrow({
|
|
386
|
+
user: msg.sender,
|
|
387
|
+
recipient: recipient,
|
|
388
|
+
amount: amount,
|
|
389
|
+
status: DepositEscrowStatus.Pending
|
|
390
|
+
});
|
|
391
|
+
emit DepositRequested(msg.sender, recipient, amount, requestId);
|
|
392
|
+
emit WrapRequested(msg.sender, recipient, amount, requestId);
|
|
393
|
+
emit OperationFeesPaid(
|
|
394
|
+
msg.sender, requestId, true, true, portalFee, mintFee, mintCallbackFee, amount
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/// @inheritdoc IERC7984PortalWrapper
|
|
399
|
+
function underlying() external view returns (address) {
|
|
400
|
+
return address(underlyingToken);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/// @inheritdoc IERC7984PortalWrapper
|
|
404
|
+
function rate() external pure returns (uint256) {
|
|
405
|
+
return 1;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/// @inheritdoc IERC7984PortalWrapper
|
|
409
|
+
function wrap(address to, uint256 amount, uint256 mintCallbackFee)
|
|
410
|
+
external
|
|
411
|
+
payable
|
|
412
|
+
nonReentrant
|
|
413
|
+
returns (bytes32 requestId)
|
|
414
|
+
{
|
|
415
|
+
(uint256 portalFloor,) = _portalFeeFloor(amount, true);
|
|
416
|
+
return _deposit(to, amount, portalFloor, mintCallbackFee);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/// @inheritdoc IPrivacyPortal
|
|
420
|
+
function requestWithdrawWithPermit(
|
|
421
|
+
address recipient,
|
|
422
|
+
uint256 amount,
|
|
423
|
+
uint256 portalFee,
|
|
424
|
+
uint256 transferFee,
|
|
425
|
+
uint256 transferCallbackFee,
|
|
426
|
+
uint256 permitDeadline,
|
|
427
|
+
uint8 v,
|
|
428
|
+
bytes32 r,
|
|
429
|
+
bytes32 s
|
|
430
|
+
) external payable override nonReentrant returns (bytes32 withdrawalId, bytes32 transferRequestId) {
|
|
431
|
+
_checkWithdrawalsNotPaused();
|
|
432
|
+
_checkNotBlacklisted();
|
|
433
|
+
if (recipient == address(0)) {
|
|
434
|
+
revert InvalidAddress();
|
|
435
|
+
}
|
|
436
|
+
if (amount == 0) {
|
|
437
|
+
revert InvalidAmount();
|
|
438
|
+
}
|
|
439
|
+
_checkWithdrawLimits(amount);
|
|
440
|
+
|
|
441
|
+
_validateAndCollectPortalFee(portalFee, amount, false);
|
|
442
|
+
if (msg.value < portalFee) {
|
|
443
|
+
revert IncorrectFee(portalFee, msg.value);
|
|
444
|
+
}
|
|
445
|
+
uint256 transferTotalFee = msg.value - portalFee;
|
|
446
|
+
if (transferFee != transferTotalFee) {
|
|
447
|
+
revert IncorrectFee(transferTotalFee, transferFee);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
withdrawalId = keccak256(abi.encodePacked(address(this), msg.sender, recipient, amount, withdrawalNonce++));
|
|
451
|
+
bytes memory callbackData = abi.encodeWithSelector(this.onPTokenTransferred.selector, withdrawalId);
|
|
452
|
+
|
|
453
|
+
IPodERC20.PublicPermit memory permit =
|
|
454
|
+
IPodERC20.PublicPermit({deadline: permitDeadline, v: v, r: r, s: s});
|
|
455
|
+
transferRequestId = pToken.transferFromAndCallWithPermit{value: transferTotalFee}(
|
|
456
|
+
msg.sender,
|
|
457
|
+
address(this),
|
|
458
|
+
amount,
|
|
459
|
+
permit,
|
|
460
|
+
callbackData,
|
|
461
|
+
transferCallbackFee
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
withdrawals[withdrawalId] = Withdrawal({
|
|
465
|
+
user: msg.sender,
|
|
466
|
+
recipient: recipient,
|
|
467
|
+
amount: amount,
|
|
468
|
+
transferRequestId: transferRequestId,
|
|
469
|
+
status: WithdrawalStatus.TransferPending
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
emit WithdrawalRequested(withdrawalId, msg.sender, recipient, amount, transferRequestId);
|
|
473
|
+
emit UnwrapRequested(
|
|
474
|
+
recipient,
|
|
475
|
+
withdrawalId,
|
|
476
|
+
keccak256(abi.encode(withdrawalId, transferRequestId))
|
|
477
|
+
);
|
|
478
|
+
emit OperationFeesPaid(
|
|
479
|
+
msg.sender,
|
|
480
|
+
withdrawalId,
|
|
481
|
+
false,
|
|
482
|
+
false,
|
|
483
|
+
portalFee,
|
|
484
|
+
transferTotalFee,
|
|
485
|
+
transferCallbackFee,
|
|
486
|
+
amount
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/// @inheritdoc IPrivacyPortal
|
|
491
|
+
function onPTokenTransferred(bytes32 withdrawalId) external override nonReentrant {
|
|
492
|
+
if (msg.sender != address(pToken)) {
|
|
493
|
+
revert OnlyPToken(msg.sender);
|
|
494
|
+
}
|
|
495
|
+
_releaseWithdrawal(withdrawalId);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/// @inheritdoc IPrivacyPortal
|
|
499
|
+
function refundFailedDeposit(bytes32 requestId) external override nonReentrant {
|
|
500
|
+
DepositEscrow storage escrow = depositEscrows[requestId];
|
|
501
|
+
DepositEscrowStatus status = escrow.status;
|
|
502
|
+
if (status != DepositEscrowStatus.Pending && status != DepositEscrowStatus.Failed) {
|
|
503
|
+
revert DepositEscrowInvalid(requestId, status);
|
|
504
|
+
}
|
|
505
|
+
IPodERC20.RequestStatus mintStatus = pToken.requests(requestId).status;
|
|
506
|
+
// Mint should not `raise`; only Inbox system errors are refundable.
|
|
507
|
+
// Permissionless: anyone may trigger; underlying always returns to {escrow.user}.
|
|
508
|
+
if (mintStatus != IPodERC20.RequestStatus.SystemFailed) {
|
|
509
|
+
revert DepositMintNotFailed(requestId, mintStatus);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
uint256 amount = escrow.amount;
|
|
513
|
+
escrow.status = DepositEscrowStatus.Refunded;
|
|
514
|
+
escrow.amount = 0;
|
|
515
|
+
underlyingToken.safeTransfer(escrow.user, amount);
|
|
516
|
+
emit DepositRefunded(escrow.user, requestId, amount);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/// @inheritdoc IPrivacyPortal
|
|
520
|
+
function cancelFailedWithdrawal(bytes32 withdrawalId) external override nonReentrant {
|
|
521
|
+
Withdrawal storage withdrawal = withdrawals[withdrawalId];
|
|
522
|
+
if (withdrawal.user == address(0)) {
|
|
523
|
+
revert UnknownWithdrawal(withdrawalId);
|
|
524
|
+
}
|
|
525
|
+
if (withdrawal.status != WithdrawalStatus.TransferPending) {
|
|
526
|
+
revert WithdrawalNotPending(withdrawalId, withdrawal.status);
|
|
527
|
+
}
|
|
528
|
+
IPodERC20.RequestStatus requestStatus = pToken.requests(withdrawal.transferRequestId).status;
|
|
529
|
+
if (
|
|
530
|
+
requestStatus != IPodERC20.RequestStatus.Failed
|
|
531
|
+
&& requestStatus != IPodERC20.RequestStatus.SystemFailed
|
|
532
|
+
) {
|
|
533
|
+
revert WithdrawTransferNotFailed(withdrawal.transferRequestId, requestStatus);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
withdrawal.status = WithdrawalStatus.Failed;
|
|
537
|
+
emit WithdrawalFailed(withdrawalId, withdrawal.transferRequestId);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/// @inheritdoc IPrivacyPortal
|
|
541
|
+
function triggerWithdrawalRelease(bytes32 withdrawalId) external override nonReentrant {
|
|
542
|
+
_releaseWithdrawal(withdrawalId);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/// @inheritdoc IPrivacyPortal
|
|
546
|
+
function burnAccumulatedPTokens(uint256 amount, uint256 burnCallbackFee)
|
|
547
|
+
external
|
|
548
|
+
payable
|
|
549
|
+
onlyFactoryAdmin
|
|
550
|
+
nonReentrant
|
|
551
|
+
returns (bytes32 burnRequestId)
|
|
552
|
+
{
|
|
553
|
+
if (amount == 0) {
|
|
554
|
+
revert InvalidAmount();
|
|
555
|
+
}
|
|
556
|
+
if (amount > pendingBurnAmount) {
|
|
557
|
+
revert PendingBurnTooLow(pendingBurnAmount, amount);
|
|
558
|
+
}
|
|
559
|
+
if (msg.value == 0) {
|
|
560
|
+
revert InvalidAmount();
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
pendingBurnAmount -= amount;
|
|
564
|
+
burnRequestId = pToken.burn{value: msg.value}(amount, burnCallbackFee);
|
|
565
|
+
emit BatchBurnSubmitted(msg.sender, amount, burnRequestId);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/// @inheritdoc IPrivacyPortal
|
|
569
|
+
function withdrawPortalFees(uint256 amount) external onlyFactoryAdmin nonReentrant {
|
|
570
|
+
if (amount == 0) {
|
|
571
|
+
revert InvalidAmount();
|
|
572
|
+
}
|
|
573
|
+
if (amount > accumulatedPortalFees) {
|
|
574
|
+
revert InsufficientAccumulatedFees(accumulatedPortalFees, amount);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
IPrivacyPortalFactory portalFactory = _factory();
|
|
578
|
+
address recipient = portalFactory.feeRecipient();
|
|
579
|
+
if (recipient == address(0)) {
|
|
580
|
+
revert InvalidAddress();
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
accumulatedPortalFees -= amount;
|
|
584
|
+
(bool ok,) = payable(recipient).call{value: amount}("");
|
|
585
|
+
require(ok, "PrivacyPortal: fee sweep failed");
|
|
586
|
+
emit PortalFeesWithdrawn(recipient, amount);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/// @notice Rescue native balance to the factory rescue recipient while paused (catastrophe path).
|
|
590
|
+
function rescueNative(uint256 amount) external onlyFactoryAdmin nonReentrant whenPaused {
|
|
591
|
+
if (amount == 0) {
|
|
592
|
+
revert InvalidAmount();
|
|
593
|
+
}
|
|
594
|
+
address recipient = _factory().rescueRecipient();
|
|
595
|
+
if (recipient == address(0)) {
|
|
596
|
+
revert InvalidAddress();
|
|
597
|
+
}
|
|
598
|
+
(bool ok,) = payable(recipient).call{value: amount}("");
|
|
599
|
+
if (!ok) {
|
|
600
|
+
revert EthTransferFailed();
|
|
601
|
+
}
|
|
602
|
+
// Keep fee accounting consistent if rescue dips into fee balance.
|
|
603
|
+
uint256 bal = address(this).balance;
|
|
604
|
+
if (accumulatedPortalFees > bal) {
|
|
605
|
+
accumulatedPortalFees = bal;
|
|
606
|
+
}
|
|
607
|
+
emit NativeRescued(recipient, amount);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/// @notice Rescue ERC20 balance to the factory rescue recipient while paused. Cannot rescue the paired pToken.
|
|
611
|
+
function rescueERC20(address token, uint256 amount) external onlyFactoryAdmin nonReentrant whenPaused {
|
|
612
|
+
if (token == address(0) || amount == 0) {
|
|
613
|
+
revert InvalidAmount();
|
|
614
|
+
}
|
|
615
|
+
if (token == address(pToken)) {
|
|
616
|
+
revert CannotRescuePToken();
|
|
617
|
+
}
|
|
618
|
+
address recipient = _factory().rescueRecipient();
|
|
619
|
+
if (recipient == address(0)) {
|
|
620
|
+
revert InvalidAddress();
|
|
621
|
+
}
|
|
622
|
+
IERC20(token).safeTransfer(recipient, amount);
|
|
623
|
+
emit ERC20Rescued(token, recipient, amount);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/// @inheritdoc IPrivacyPortal
|
|
627
|
+
function estimateDepositFees(uint256 amount)
|
|
628
|
+
external
|
|
629
|
+
view
|
|
630
|
+
returns (
|
|
631
|
+
uint256 portalFee,
|
|
632
|
+
bool usedDynamicPricing,
|
|
633
|
+
uint256 mintTotalFee,
|
|
634
|
+
uint256 mintCallbackFee
|
|
635
|
+
)
|
|
636
|
+
{
|
|
637
|
+
(portalFee, usedDynamicPricing) = _estimatePortalFee(amount, true);
|
|
638
|
+
(mintTotalFee, , mintCallbackFee) = pToken.estimateFee();
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/// @inheritdoc IPrivacyPortal
|
|
642
|
+
function estimateWithdrawFees(uint256 amount)
|
|
643
|
+
external
|
|
644
|
+
view
|
|
645
|
+
returns (
|
|
646
|
+
uint256 portalFee,
|
|
647
|
+
bool usedDynamicPricing,
|
|
648
|
+
uint256 transferTotalFee,
|
|
649
|
+
uint256 transferCallbackFee
|
|
650
|
+
)
|
|
651
|
+
{
|
|
652
|
+
(portalFee, usedDynamicPricing) = _estimatePortalFee(amount, false);
|
|
653
|
+
(transferTotalFee, , transferCallbackFee) = pToken.estimateFee();
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/// @inheritdoc IPrivacyPortal
|
|
657
|
+
function estimateBatchBurnFees(uint256)
|
|
658
|
+
external
|
|
659
|
+
view
|
|
660
|
+
returns (uint256 burnTotalFee, uint256 burnCallbackFee)
|
|
661
|
+
{
|
|
662
|
+
(burnTotalFee, , burnCallbackFee) = pToken.estimateFee();
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/// @notice Effective packed deposit fee config (override or factory default).
|
|
666
|
+
function getEffectiveDepositFeeConfig() external view returns (bytes32) {
|
|
667
|
+
return _effectiveFeePacked(true);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/// @notice Effective packed withdraw fee config (override or factory default).
|
|
671
|
+
function getEffectiveWithdrawFeeConfig() external view returns (bytes32) {
|
|
672
|
+
return _effectiveFeePacked(false);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/// @inheritdoc IPrivacyPortal
|
|
676
|
+
function getFeeConfig(bool isDeposit) external view returns (PortalFeeConfig memory config) {
|
|
677
|
+
return PrivacyPortalFeeLib.decodeFeeConfig(_effectiveFeePacked(isDeposit));
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/// @inheritdoc IPrivacyPortal
|
|
681
|
+
function getFeeConfigOverride(bool isDeposit)
|
|
682
|
+
external
|
|
683
|
+
view
|
|
684
|
+
returns (PortalFeeConfig memory config, bool isSet)
|
|
685
|
+
{
|
|
686
|
+
bytes32 packed = isDeposit ? depositFeeOverridePacked : withdrawFeeOverridePacked;
|
|
687
|
+
isSet = PrivacyPortalFeeLib.isOverrideSet(packed);
|
|
688
|
+
if (!isSet) {
|
|
689
|
+
return (config, false);
|
|
690
|
+
}
|
|
691
|
+
return (PrivacyPortalFeeLib.decodeFeeConfig(packed), true);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/// @notice Release an eligible withdrawal exactly once; pTokens remain in custody for batch burn.
|
|
695
|
+
function _releaseWithdrawal(bytes32 withdrawalId) private {
|
|
696
|
+
Withdrawal storage withdrawal = withdrawals[withdrawalId];
|
|
697
|
+
if (withdrawal.user == address(0)) {
|
|
698
|
+
revert UnknownWithdrawal(withdrawalId);
|
|
699
|
+
}
|
|
700
|
+
if (withdrawal.status != WithdrawalStatus.TransferPending) {
|
|
701
|
+
revert WithdrawalNotPending(withdrawalId, withdrawal.status);
|
|
702
|
+
}
|
|
703
|
+
IPodERC20.RequestStatus requestStatus = pToken.requests(withdrawal.transferRequestId).status;
|
|
704
|
+
if (requestStatus != IPodERC20.RequestStatus.Success) {
|
|
705
|
+
revert PTokenTransferNotSuccessful(withdrawal.transferRequestId, requestStatus);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
withdrawal.status = WithdrawalStatus.Released;
|
|
709
|
+
underlyingToken.safeTransfer(withdrawal.recipient, withdrawal.amount);
|
|
710
|
+
pendingBurnAmount += withdrawal.amount;
|
|
711
|
+
|
|
712
|
+
emit WithdrawalReleased(withdrawalId, withdrawal.recipient, withdrawal.amount);
|
|
713
|
+
emit PendingBurnIncreased(withdrawalId, withdrawal.amount, pendingBurnAmount);
|
|
714
|
+
emit UnwrapFinalized(
|
|
715
|
+
withdrawal.recipient,
|
|
716
|
+
withdrawalId,
|
|
717
|
+
withdrawalId,
|
|
718
|
+
uint64(withdrawal.amount)
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
function _validateAndCollectPortalFee(uint256 portalFee, uint256 amount, bool isDeposit) private {
|
|
723
|
+
(uint256 floor, uint128 maxFee) = _portalFeeFloor(amount, isDeposit);
|
|
724
|
+
if (portalFee < floor) {
|
|
725
|
+
revert InsufficientPortalFee(floor, portalFee);
|
|
726
|
+
}
|
|
727
|
+
if (portalFee > maxFee) {
|
|
728
|
+
revert ExcessivePortalFee(maxFee, portalFee);
|
|
729
|
+
}
|
|
730
|
+
accumulatedPortalFees += portalFee;
|
|
731
|
+
emit PortalFeeCollected(msg.sender, portalFee, isDeposit);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
function _portalFeeFloor(uint256 amount, bool isDeposit)
|
|
735
|
+
private
|
|
736
|
+
view
|
|
737
|
+
returns (uint256 floor, uint128 maxFee)
|
|
738
|
+
{
|
|
739
|
+
bytes32 packed = _effectiveFeePacked(isDeposit);
|
|
740
|
+
IPrivacyPortalFactory portalFactory = _factory();
|
|
741
|
+
(uint96 fixedFee, uint32 bps, uint128 max) = PrivacyPortalFeeLib.unpackFeeConfig(packed);
|
|
742
|
+
maxFee = max;
|
|
743
|
+
if (address(portalFactory.priceOracle()) == address(0) || bps == 0) {
|
|
744
|
+
return (fixedFee, maxFee);
|
|
745
|
+
}
|
|
746
|
+
IPodPriceOracle oracle = portalFactory.priceOracle();
|
|
747
|
+
(uint256 nativeUsd, uint256 collateralUsd) = oracle.getLivePrices(
|
|
748
|
+
portalFactory.nativeToken(),
|
|
749
|
+
address(underlyingToken)
|
|
750
|
+
);
|
|
751
|
+
(floor,) = PrivacyPortalFeeLib.resolvePortalFee(
|
|
752
|
+
packed,
|
|
753
|
+
amount,
|
|
754
|
+
decimals,
|
|
755
|
+
collateralUsd,
|
|
756
|
+
nativeUsd
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
function _estimatePortalFee(uint256 amount, bool isDeposit)
|
|
761
|
+
private
|
|
762
|
+
view
|
|
763
|
+
returns (uint256 fee, bool usedDynamicPricing)
|
|
764
|
+
{
|
|
765
|
+
IPrivacyPortalFactory portalFactory = _factory();
|
|
766
|
+
if (isDeposit) {
|
|
767
|
+
if (PrivacyPortalFeeLib.isOverrideSet(depositFeeOverridePacked)) {
|
|
768
|
+
return _estimateWithOverride(depositFeeOverridePacked, amount, portalFactory);
|
|
769
|
+
}
|
|
770
|
+
return portalFactory.estimateDepositPortalFee(address(underlyingToken), amount, decimals);
|
|
771
|
+
}
|
|
772
|
+
if (PrivacyPortalFeeLib.isOverrideSet(withdrawFeeOverridePacked)) {
|
|
773
|
+
return _estimateWithOverride(withdrawFeeOverridePacked, amount, portalFactory);
|
|
774
|
+
}
|
|
775
|
+
return portalFactory.estimateWithdrawPortalFee(address(underlyingToken), amount, decimals);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
function _estimateWithOverride(bytes32 packed, uint256 amount, IPrivacyPortalFactory portalFactory)
|
|
779
|
+
private
|
|
780
|
+
view
|
|
781
|
+
returns (uint256 fee, bool usedDynamicPricing)
|
|
782
|
+
{
|
|
783
|
+
if (address(portalFactory.priceOracle()) == address(0)) {
|
|
784
|
+
(uint96 fixedFee,,) = PrivacyPortalFeeLib.unpackFeeConfig(packed);
|
|
785
|
+
return (fixedFee, false);
|
|
786
|
+
}
|
|
787
|
+
IPodPriceOracle oracle = portalFactory.priceOracle();
|
|
788
|
+
(uint256 nativeUsd, uint256 collateralUsd) = oracle.getLivePrices(
|
|
789
|
+
portalFactory.nativeToken(),
|
|
790
|
+
address(underlyingToken)
|
|
791
|
+
);
|
|
792
|
+
return PrivacyPortalFeeLib.resolvePortalFee(
|
|
793
|
+
packed,
|
|
794
|
+
amount,
|
|
795
|
+
decimals,
|
|
796
|
+
collateralUsd,
|
|
797
|
+
nativeUsd
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function _effectiveFeePacked(bool isDeposit) private view returns (bytes32) {
|
|
802
|
+
bytes32 overridePacked = isDeposit ? depositFeeOverridePacked : withdrawFeeOverridePacked;
|
|
803
|
+
if (PrivacyPortalFeeLib.isOverrideSet(overridePacked)) {
|
|
804
|
+
return overridePacked;
|
|
805
|
+
}
|
|
806
|
+
IPrivacyPortalFactory portalFactory = _factory();
|
|
807
|
+
return isDeposit ? portalFactory.defaultDepositFeePacked() : portalFactory.defaultWithdrawFeePacked();
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function _factory() private view returns (IPrivacyPortalFactory) {
|
|
811
|
+
address factory_ = factory;
|
|
812
|
+
if (factory_ == address(0)) {
|
|
813
|
+
revert FactoryNotConfigured();
|
|
814
|
+
}
|
|
815
|
+
return IPrivacyPortalFactory(factory_);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
modifier onlyFactoryOperator() {
|
|
819
|
+
if (!_factory().isOperator(msg.sender)) {
|
|
820
|
+
revert OnlyFactoryOperator(msg.sender);
|
|
821
|
+
}
|
|
822
|
+
_;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
modifier onlyFactoryAdmin() {
|
|
826
|
+
if (!_factory().isAdmin(msg.sender)) {
|
|
827
|
+
revert OnlyFactoryAdmin(msg.sender);
|
|
828
|
+
}
|
|
829
|
+
_;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
function _checkWithdrawalsNotPaused() private view {
|
|
833
|
+
// Local instance pause first, then factory-wide pause.
|
|
834
|
+
if (paused() || _factory().withdrawalsPaused()) {
|
|
835
|
+
revert WithdrawalsPaused();
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function _checkDepositsNotPaused() private view {
|
|
840
|
+
if (paused() || _factory().depositsPaused()) {
|
|
841
|
+
revert DepositsPaused();
|
|
842
|
+
}
|
|
843
|
+
if (!isDepositEnabled) {
|
|
844
|
+
revert DepositDisabled();
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
function _checkNotBlacklisted() private view {
|
|
849
|
+
if (blacklisted[msg.sender] || _factory().blacklisted(msg.sender)) {
|
|
850
|
+
revert AddressBlacklisted(msg.sender);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
function _checkDepositLimits(uint256 amount) private view {
|
|
855
|
+
if (amount < minDepositAmount) {
|
|
856
|
+
revert DepositBelowMinimum();
|
|
857
|
+
}
|
|
858
|
+
if (amount > maxDepositAmount) {
|
|
859
|
+
revert DepositExceedsMaximum();
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
function _checkWithdrawLimits(uint256 amount) private view {
|
|
864
|
+
if (amount < minWithdrawAmount) {
|
|
865
|
+
revert WithdrawBelowMinimum();
|
|
866
|
+
}
|
|
867
|
+
if (amount > maxWithdrawAmount) {
|
|
868
|
+
revert WithdrawExceedsMaximum();
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|