@coti-io/coti-contracts 1.2.0 → 1.3.0
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/.github/workflows/npm-publish.yml +1 -1
- package/contracts/messaging/PrivateMessaging.sol +456 -0
- package/contracts/mocks/messaging/PrivateMessagingHarness.sol +54 -0
- package/contracts/mocks/oracle/CotiPriceConsumerMock.sol +31 -0
- package/contracts/mocks/token/ERC20DecimalsMock.sol +21 -0
- package/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.sol +8 -3
- package/contracts/node/SoulboundNodeNFT.sol +22 -22
- package/contracts/oracle/CotiPriceConsumer.sol +103 -0
- package/contracts/oracle/ICotiPriceConsumer.sol +15 -0
- package/contracts/oracle/IStdReference.sol +26 -0
- package/contracts/privacyBridge/PrivacyBridge.sol +373 -91
- package/contracts/privacyBridge/PrivacyBridgeCotiNative.sol +209 -161
- package/contracts/privacyBridge/PrivacyBridgeERC20.sol +241 -159
- package/contracts/privacyBridge/PrivacyBridgeUSDCe.sol +7 -1
- package/contracts/privacyBridge/PrivacyBridgeUSDT.sol +7 -1
- package/contracts/privacyBridge/PrivacyBridgeWADA.sol +7 -1
- package/contracts/privacyBridge/PrivacyBridgeWBTC.sol +7 -1
- package/contracts/privacyBridge/PrivacyBridgeWETH.sol +7 -1
- package/contracts/privacyBridge/PrivacyBridgegCoti.sol +7 -1
- package/hardhat.config.ts +5 -2
- package/package.json +2 -2
- package/scripts/add-bridge-operators.cjs +87 -0
- package/scripts/deploy-coti-price-consumer-mainnet.cjs +49 -0
- package/scripts/deployCotiNodeRewards.ts +51 -0
- package/scripts/redeploy-private-and-bridges.cjs +201 -0
- package/scripts/set-bridge-limits-mainnet.cjs +177 -0
- package/scripts/verify-mainnet-private-bridges.cjs +289 -0
- package/sonar-project.properties +11 -0
- package/test/messaging/PrivateMessaging.test.ts +158 -0
- package/test/privacyBridge/UnifiedPrivacyBridges.test.cjs +1663 -0
- package/test/token/PrivateERC20/PrivacyBridge.fees.test.ts +162 -239
- package/typechain-types/@openzeppelin/contracts/access/AccessControl.ts +324 -0
- package/typechain-types/@openzeppelin/contracts/access/AccessControlEnumerable.ts +361 -0
- package/typechain-types/@openzeppelin/contracts/access/IAccessControl.ts +292 -0
- package/typechain-types/@openzeppelin/contracts/access/IAccessControlEnumerable.ts +329 -0
- package/typechain-types/@openzeppelin/contracts/access/index.ts +4 -0
- package/typechain-types/@openzeppelin/contracts/index.ts +2 -0
- package/typechain-types/@openzeppelin/contracts/security/Pausable.ts +150 -0
- package/typechain-types/@openzeppelin/contracts/security/index.ts +4 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/ERC20.ts +330 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.ts +286 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/index.ts +1 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/index.ts +1 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/ERC721.ts +420 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.ts +420 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/index.ts +4 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC721/index.ts +3 -0
- package/typechain-types/contracts/disperse/coinByRatio/FixedRatioCoinDisperserLeftoverS1.ts +735 -0
- package/typechain-types/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow.ts +734 -0
- package/typechain-types/contracts/disperse/coinByRatio/index.ts +2 -0
- package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/IOwnable.ts +95 -0
- package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser.ts +22 -0
- package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +1 -0
- package/typechain-types/contracts/index.ts +8 -0
- package/typechain-types/contracts/messaging/PrivateMessaging.ts +871 -0
- package/typechain-types/contracts/messaging/index.ts +4 -0
- package/typechain-types/contracts/mocks/index.ts +4 -0
- package/typechain-types/contracts/mocks/messaging/PrivateMessagingHarness.ts +951 -0
- package/typechain-types/contracts/mocks/messaging/index.ts +4 -0
- package/typechain-types/contracts/mocks/oracle/CotiPriceConsumerMock.ts +163 -0
- package/typechain-types/contracts/mocks/oracle/index.ts +4 -0
- package/typechain-types/contracts/mocks/token/ERC20DecimalsMock.ts +349 -0
- package/typechain-types/contracts/mocks/token/ERC20Mock.ts +368 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock.ts +108 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.ts +1892 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock.ts +1296 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock.ts +1270 -0
- package/typechain-types/contracts/mocks/{utils/mpc/Bitwise128BitTestsContract.ts → token/PrivateERC20/PrivateERC20GtCallerMock.ts} +47 -67
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.ts +757 -25
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/IPrivateERC20TransferAndCallEncrypted.ts +102 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/PrivateERC20ReentrantReceiverMock.ts +154 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/index.ts +5 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock.ts +155 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock.ts +107 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock.ts +100 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/index.ts +10 -0
- package/typechain-types/contracts/mocks/token/index.ts +2 -0
- package/typechain-types/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.ts +6 -6
- package/typechain-types/contracts/node/CotiNodeRewards.ts +566 -0
- package/typechain-types/contracts/node/SoulboundNodeNFT.sol/IERC5192.ts +123 -0
- package/typechain-types/contracts/node/SoulboundNodeNFT.sol/SoulboundNodeNFT.ts +975 -0
- package/typechain-types/contracts/node/SoulboundNodeNFT.sol/index.ts +5 -0
- package/typechain-types/contracts/node/index.ts +6 -0
- package/typechain-types/contracts/oracle/CotiPriceConsumer.ts +256 -0
- package/typechain-types/contracts/oracle/ICotiPriceConsumer.ts +119 -0
- package/typechain-types/contracts/oracle/IStdReference.ts +136 -0
- package/typechain-types/contracts/oracle/index.ts +6 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridge.ts +1628 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeCotiNative.ts +1870 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeERC20.sol/IHasDecimals.ts +84 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeERC20.sol/PrivacyBridgeERC20.ts +1892 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeERC20.sol/index.ts +5 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeUSDCe.ts +1892 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeUSDT.ts +1892 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeWADA.ts +1892 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeWBTC.ts +1892 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgeWETH.ts +1892 -0
- package/typechain-types/contracts/privacyBridge/PrivacyBridgegCoti.ts +1892 -0
- package/typechain-types/contracts/privacyBridge/index.ts +13 -0
- package/typechain-types/contracts/token/PrivateERC20/IPrivateERC20.ts +439 -19
- package/typechain-types/contracts/token/PrivateERC20/ITokenReceiver.ts +100 -0
- package/typechain-types/contracts/token/PrivateERC20/ITokenReceiverEncrypted.ts +99 -0
- package/typechain-types/contracts/token/PrivateERC20/PrivateERC20.ts +763 -15
- package/typechain-types/contracts/token/PrivateERC20/index.ts +4 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC.ts +1270 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateCOTI.ts +1270 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken.ts +1270 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateTetherUSD.ts +1270 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedADA.ts +1270 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC.ts +1270 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedEther.ts +1270 -0
- package/typechain-types/contracts/token/PrivateERC20/tokens/index.ts +10 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/AccessControlEnumerable__factory.ts +276 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/AccessControl__factory.ts +229 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/IAccessControlEnumerable__factory.ts +244 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/IAccessControl__factory.ts +197 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/index.ts +1 -0
- package/typechain-types/factories/@openzeppelin/contracts/security/Pausable__factory.ts +61 -0
- package/typechain-types/factories/@openzeppelin/contracts/security/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/ERC20__factory.ts +356 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata__factory.ts +247 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/index.ts +1 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/index.ts +1 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/ERC721__factory.ts +416 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata__factory.ts +355 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/index.ts +4 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/index.ts +2 -0
- package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperserLeftoverS1__factory.ts +791 -0
- package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow__factory.ts +711 -0
- package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperser__factory.ts +1 -1
- package/typechain-types/factories/contracts/disperse/coinByRatio/index.ts +2 -0
- package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/IOwnable__factory.ts +35 -0
- package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser__factory.ts +19 -1
- package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +1 -0
- package/typechain-types/factories/contracts/disperse/disperseToken/TokenDisperser__factory.ts +1 -1
- package/typechain-types/factories/contracts/index.ts +4 -0
- package/typechain-types/factories/contracts/messaging/PrivateMessaging__factory.ts +1035 -0
- package/typechain-types/factories/contracts/messaging/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/access/DataPrivacyFramework/DataPrivacyFrameworkMock__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/index.ts +2 -0
- package/typechain-types/factories/contracts/mocks/messaging/PrivateMessagingHarness__factory.ts +1161 -0
- package/typechain-types/factories/contracts/mocks/messaging/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/oracle/CotiPriceConsumerMock__factory.ts +159 -0
- package/typechain-types/factories/contracts/mocks/oracle/index.ts +4 -0
- package/typechain-types/factories/contracts/mocks/token/ERC20DecimalsMock__factory.ts +394 -0
- package/typechain-types/factories/contracts/mocks/token/ERC20Mock__factory.ts +392 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock__factory.ts +125 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock__factory.ts +1797 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock__factory.ts +1514 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock__factory.ts +1466 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock__factory.ts +165 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20Mock__factory.ts +771 -55
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/IPrivateERC20TransferAndCallEncrypted__factory.ts +54 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/PrivateERC20ReentrantReceiverMock__factory.ts +159 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/index.ts +5 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock__factory.ts +164 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock__factory.ts +130 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock__factory.ts +102 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC20/index.ts +9 -0
- package/typechain-types/factories/contracts/mocks/token/PrivateERC721/PrivateERC721URIStorageMock__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/token/index.ts +2 -0
- 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/MinimalProxy__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/PrivacyProxy__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 +4 -22
- package/typechain-types/factories/contracts/node/CotiNodeRewards__factory.ts +549 -0
- package/typechain-types/factories/contracts/node/SoulboundNodeNFT.sol/IERC5192__factory.ts +54 -0
- package/typechain-types/factories/contracts/node/SoulboundNodeNFT.sol/SoulboundNodeNFT__factory.ts +947 -0
- package/typechain-types/factories/contracts/node/SoulboundNodeNFT.sol/index.ts +5 -0
- package/typechain-types/factories/contracts/node/index.ts +5 -0
- package/typechain-types/factories/contracts/onboard/AccountOnboard__factory.ts +1 -1
- package/typechain-types/factories/contracts/oracle/CotiPriceConsumer__factory.ts +295 -0
- package/typechain-types/factories/contracts/oracle/ICotiPriceConsumer__factory.ts +73 -0
- package/typechain-types/factories/contracts/oracle/IStdReference__factory.ts +107 -0
- package/typechain-types/factories/contracts/oracle/index.ts +6 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeCotiNative__factory.ts +1676 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeERC20.sol/IHasDecimals__factory.ts +38 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeERC20.sol/PrivacyBridgeERC20__factory.ts +1678 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeERC20.sol/index.ts +5 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeUSDCe__factory.ts +1782 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeUSDT__factory.ts +1782 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWADA__factory.ts +1782 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWBTC__factory.ts +1782 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWETH__factory.ts +1782 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridge__factory.ts +1367 -0
- package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgegCoti__factory.ts +1782 -0
- package/typechain-types/factories/contracts/privacyBridge/index.ts +12 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/IPrivateERC20__factory.ts +481 -35
- package/typechain-types/factories/contracts/token/PrivateERC20/ITokenReceiverEncrypted__factory.ts +53 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/ITokenReceiver__factory.ts +54 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/PrivateERC20__factory.ts +793 -59
- package/typechain-types/factories/contracts/token/PrivateERC20/index.ts +3 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC__factory.ts +1445 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken__factory.ts +1451 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateCOTI__factory.ts +1442 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateTetherUSD__factory.ts +1445 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedADA__factory.ts +1445 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC__factory.ts +1445 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedEther__factory.ts +1451 -0
- package/typechain-types/factories/contracts/token/PrivateERC20/tokens/index.ts +10 -0
- package/typechain-types/factories/contracts/utils/mpc/MpcCore__factory.ts +1 -1
- package/typechain-types/hardhat.d.ts +953 -17
- package/typechain-types/index.ts +104 -0
- package/typechain-types/contracts/mocks/utils/mpc/Arithmetic128BitTestsContract.ts +0 -341
- package/typechain-types/contracts/mocks/utils/mpc/Arithmetic256BitTestsContract.ts +0 -347
- package/typechain-types/contracts/mocks/utils/mpc/Bitwise256BitTestsContract.ts +0 -186
- package/typechain-types/contracts/mocks/utils/mpc/Comparison128BitTestsContract.ts +0 -260
- package/typechain-types/contracts/mocks/utils/mpc/Comparison256BitTestsContract.ts +0 -260
- package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract.ts +0 -302
- package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract.ts +0 -322
- package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic128BitTestsContract__factory.ts +0 -349
- package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic256BitTestsContract__factory.ts +0 -364
- package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise128BitTestsContract__factory.ts +0 -182
- package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise256BitTestsContract__factory.ts +0 -182
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison128BitTestsContract__factory.ts +0 -255
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison256BitTestsContract__factory.ts +0 -255
- package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract__factory.ts +0 -332
- package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract__factory.ts +0 -380
|
@@ -4,24 +4,60 @@ pragma solidity ^0.8.19;
|
|
|
4
4
|
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
|
|
5
5
|
import "@openzeppelin/contracts/security/Pausable.sol";
|
|
6
6
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
7
|
-
import "@openzeppelin/contracts/access/
|
|
8
|
-
import "
|
|
7
|
+
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
|
|
8
|
+
import "../oracle/ICotiPriceConsumer.sol";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @title PrivacyBridge
|
|
12
12
|
* @notice Base contract for Privacy Bridge contracts containing common logic
|
|
13
13
|
* @dev Trust assumptions: (1) MPC precompile at expected address is correct and non-malicious.
|
|
14
14
|
* (2) Private token implementation is trusted and only authorized minters can mint.
|
|
15
|
-
* (3)
|
|
16
|
-
*
|
|
15
|
+
* (3) Pause and rescue (governance-critical): The owner can {pause}. While paused, derived bridges expose
|
|
16
|
+
* owner-only rescue entry points ({PrivacyBridgeCotiNative.rescueNative}, {PrivacyBridgeERC20.rescueERC20})
|
|
17
|
+
* that send value to {rescueRecipient}. Those calls can transfer the contract's entire relevant balance,
|
|
18
|
+
* including liquidity that backs user obligations (full TVL migration). That is the intended emergency
|
|
19
|
+
* response after a bug or to retire a deployment; it is not enforced user-by-user on-chain. Treat
|
|
20
|
+
* owner key compromise after pause as catastrophic TVL loss to {rescueRecipient}. Mitigations are
|
|
21
|
+
* operational: multisig or timelock on ownership, strict {rescueRecipient} policy, monitoring of
|
|
22
|
+
* {Paused} and rescue events, and separation of duties where possible.
|
|
23
|
+
* (4) Oracle prices are trusted; {maxOracleAge} bounds staleness of `lastUpdated` (owner cannot set it to zero;
|
|
24
|
+
* use a large value only if a very lenient window is intended). Does not remove oracle trust.
|
|
25
|
+
* (5) {totalUserLiability} is bridge bookkeeping for transparency: it tracks net user obligations from mint/burn
|
|
26
|
+
* paths in this contract only. It helps depositors/observers reason about exposure; it is not a
|
|
27
|
+
* cryptographic proof of MPC/private-token balances and can diverge if the token layer misbehaves.
|
|
28
|
+
* **Docs / integrators:** Compare this counter to collateral still held by *this* contract (ERC20:
|
|
29
|
+
* {PrivacyBridgeERC20.token} balance; native: {address(this).balance}) for a liquidity snapshot. After
|
|
30
|
+
* {rescueERC20}/{rescueNative}, collateral may sit at {rescueRecipient} while this counter is unchanged—
|
|
31
|
+
* economic claims on outstanding private supply are not extinguished by rescue; do not treat the counter
|
|
32
|
+
* as “assets on hand” post-migration. Forced native (e.g. `selfdestruct`) increases balance but **never**
|
|
33
|
+
* mints private tokens and does **not** increase {totalUserLiability} (no user deposit path).
|
|
34
|
+
* (6) For COTI-operated deployments, residual trust in MPC/private-token behavior beyond (2) and (5), and in oracle
|
|
35
|
+
* *market* correctness beyond (4), is an accepted operational assumption; the on-chain mitigations above
|
|
36
|
+
* are the intended scope for those concerns in this module.
|
|
37
|
+
* (7) **Centralized control:** A single `Ownable` owner and any `OPERATOR_ROLE` grantees can configure pause,
|
|
38
|
+
* oracle rotation, deposit/withdraw limits, blacklist, and fee *parameters* (floors/caps/percentages) exposed
|
|
39
|
+
* in this module. **Fee and rescue destinations are fixed at deployment**—there are no setters for
|
|
40
|
+
* {feeRecipient} or {rescueRecipient}, so a compromised owner **cannot** redirect rescue or fee sweep
|
|
41
|
+
* addresses to an attacker (trade-off: a wrong address at deploy or a reverting recipient must be handled
|
|
42
|
+
* operationally / via migration). {transferOwnership} enumerates and revokes all role members, which can
|
|
43
|
+
* become gas-heavy with many operators; that cost is accepted. The contracts are not upgradeable via
|
|
44
|
+
* delegatecall within this package. Operational mitigations are off-chain: multisig or timelock on
|
|
45
|
+
* ownership, least-privilege operators, and monitoring.
|
|
46
|
+
* (8) **Oracle binding:** {_validateOracleTimestamps} requires exact equality to the user-supplied Band row
|
|
47
|
+
* timestamps so the fee quote cannot change between estimate and execution without a revert. With a
|
|
48
|
+
* typical ~30 minute feed cadence (plus {maxOracleAge} buffer), users have ample time to sign and submit
|
|
49
|
+
* the same row; relaxing this binding is intentionally rejected to avoid showing one price and settling
|
|
50
|
+
* at another.
|
|
17
51
|
*/
|
|
18
|
-
abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable,
|
|
52
|
+
abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessControlEnumerable {
|
|
19
53
|
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
|
|
20
54
|
|
|
21
55
|
event OperatorAdded(address indexed account, address indexed by);
|
|
22
56
|
event OperatorRemoved(address indexed account, address indexed by);
|
|
23
57
|
event DepositEnabledUpdated(bool enabled, address indexed by);
|
|
24
|
-
event
|
|
58
|
+
event DynamicFeeUpdated(string feeType, uint256 fixedFee, uint256 percentageBps, uint256 maxFee);
|
|
59
|
+
event PriceOracleUpdated(address indexed oldOracle, address indexed newOracle);
|
|
60
|
+
event MaxOracleAgeUpdated(uint256 maxOracleAge, address indexed by);
|
|
25
61
|
|
|
26
62
|
/// @notice Maximum amount that can be deposited in a single transaction
|
|
27
63
|
uint256 public maxDepositAmount;
|
|
@@ -35,19 +71,29 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
35
71
|
/// @notice Minimum amount required for a withdrawal
|
|
36
72
|
uint256 public minWithdrawAmount;
|
|
37
73
|
|
|
38
|
-
/// @notice
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
/// @notice Withdrawal fee in basis points (1 bp = 0.0001%, 1,000,000 = 100%)
|
|
42
|
-
uint256 public withdrawFeeBasisPoints;
|
|
43
|
-
|
|
44
|
-
/// @notice Accumulated fees collected by the bridge (in bridged asset units)
|
|
45
|
-
uint256 public accumulatedFees;
|
|
46
|
-
|
|
47
|
-
/// @notice Accumulated native COTI fees (used only by ERC20 bridges for per-operation native fee; not used by native bridge)
|
|
74
|
+
/// @notice Booked native COTI fees not yet swept: both {PrivacyBridgeCotiNative} (deposit/withdraw fees)
|
|
75
|
+
/// and ERC20 bridges (per-operation dynamic native fee via {_collectDynamicNativeFee}) credit this counter.
|
|
76
|
+
/// Native bridge: {PrivacyBridgeCotiNative.withdrawFees}; ERC20 deployments: {withdrawCotiFees}.
|
|
48
77
|
uint256 public accumulatedCotiFees;
|
|
49
78
|
|
|
50
|
-
/// @notice
|
|
79
|
+
/// @notice On-chain aggregate of bridge-issued user obligations from deposit/withdraw mint and burn paths
|
|
80
|
+
/// (native: net private minted; native withdraw: private burned; ERC20: public received in / amount out).
|
|
81
|
+
/// Intended for transparency so depositors and tooling can read how much liability the bridge tracks
|
|
82
|
+
/// in its own accounting. This does not attest to MPC correctness or encrypted token balances.
|
|
83
|
+
/// @dev Same scope as contract-level @dev (5): updates only follow explicit mint/burn paths; unsolicited native
|
|
84
|
+
/// (e.g. `selfdestruct`) does **not** increase this value and does not mint private tokens. If the private
|
|
85
|
+
/// token or MPC layer misreports or mis-mints, this counter can diverge from economic reality. Do not
|
|
86
|
+
/// treat it as a solvency proof or substitute for off-chain audits of the private ledger. Emergency
|
|
87
|
+
/// {rescueERC20}/{rescueNative} moves collateral out but does **not** change this counter—obligations
|
|
88
|
+
/// implied by outstanding private supply may then exceed assets held here until migration elsewhere.
|
|
89
|
+
/// **Integrators:** compare to on-contract collateral (see contract @dev (5)).
|
|
90
|
+
uint256 public totalUserLiability;
|
|
91
|
+
|
|
92
|
+
/// @notice Fee divisor (1,000,000). Fee math uses {Math.mulDiv} (OpenZeppelin): integer division **rounds down**
|
|
93
|
+
/// (toward zero) at each step, so on-chain fees are at most a few wei **lower** than an idealized
|
|
94
|
+
/// floating-point quote—bias slightly favors users, not the fee recipient.
|
|
95
|
+
/// @dev Pathological `amount` × oracle rate products can still overflow `uint256` and revert—operators should
|
|
96
|
+
/// set deposit/withdraw limits accordingly.
|
|
51
97
|
uint256 public constant FEE_DIVISOR = 1000000;
|
|
52
98
|
|
|
53
99
|
/// @notice Maximum fee allowed (10% = 100,000 units)
|
|
@@ -56,8 +102,46 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
56
102
|
/// @notice Flag to enable/disable deposits
|
|
57
103
|
bool public isDepositEnabled = true;
|
|
58
104
|
|
|
59
|
-
|
|
60
|
-
|
|
105
|
+
// Privacy Bridge defines default Fees
|
|
106
|
+
// those fees can be overwritten using
|
|
107
|
+
// setDepositDynamicFee available for OPERATORS and ADMIN
|
|
108
|
+
|
|
109
|
+
/// @notice Deposit fee floor in COTI wei
|
|
110
|
+
uint256 public depositFixedFee = 10 ether;
|
|
111
|
+
|
|
112
|
+
/// @notice Deposit percentage (500/1,000,000 = 0.05%)
|
|
113
|
+
uint256 public depositPercentageBps = 500;
|
|
114
|
+
|
|
115
|
+
/// @notice Deposit fee cap in COTI wei
|
|
116
|
+
uint256 public depositMaxFee = 3000 ether;
|
|
117
|
+
|
|
118
|
+
/// @notice Withdraw fee floor in COTI wei
|
|
119
|
+
uint256 public withdrawFixedFee = 3 ether;
|
|
120
|
+
|
|
121
|
+
/// @notice Withdraw percentage (250/1,000,000 = 0.025%)
|
|
122
|
+
uint256 public withdrawPercentageBps = 250;
|
|
123
|
+
|
|
124
|
+
/// @notice Withdraw fee cap in COTI wei
|
|
125
|
+
uint256 public withdrawMaxFee = 1500 ether;
|
|
126
|
+
|
|
127
|
+
// --- END OF DEFAULT FEES
|
|
128
|
+
|
|
129
|
+
/// @notice CotiPriceConsumer contract address (non-zero at construction; owner may {setPriceOracle} to rotate)
|
|
130
|
+
address public priceOracle;
|
|
131
|
+
|
|
132
|
+
/// @notice Default max oracle age: nominal ~30 minute feed cadence plus a 5 minute buffer so slightly delayed
|
|
133
|
+
/// updates or inclusion lag do not spuriously revert with {OraclePriceStale}.
|
|
134
|
+
uint256 public constant DEFAULT_MAX_ORACLE_AGE = 30 minutes + 5 minutes;
|
|
135
|
+
|
|
136
|
+
/// @notice Maximum allowed `block.timestamp - oracle lastUpdated` (seconds). Initialized to {DEFAULT_MAX_ORACLE_AGE};
|
|
137
|
+
/// owner may increase the window (e.g. for long test runs) but {setMaxOracleAge} rejects zero.
|
|
138
|
+
uint256 public maxOracleAge;
|
|
139
|
+
|
|
140
|
+
/// @notice Address where collected fees are sent (fixed at deploy; no setter—see contract @dev (7))
|
|
141
|
+
address public feeRecipient;
|
|
142
|
+
|
|
143
|
+
/// @notice Address where rescued funds are sent (fixed at deploy; no setter—see contract @dev (7))
|
|
144
|
+
address public rescueRecipient;
|
|
61
145
|
|
|
62
146
|
error AmountZero();
|
|
63
147
|
error InsufficientEthBalance();
|
|
@@ -66,6 +150,26 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
66
150
|
error DepositDisabled();
|
|
67
151
|
error InsufficientCotiFee();
|
|
68
152
|
error BridgePaused();
|
|
153
|
+
error OracleTimestampMismatch(uint256 expected, uint256 actual);
|
|
154
|
+
error PriceOracleNotSet();
|
|
155
|
+
error InvalidOraclePrice();
|
|
156
|
+
error OraclePriceStale(uint256 oracleLastUpdated, uint256 blockTimestamp, uint256 maxOracleAge);
|
|
157
|
+
error OracleLastUpdatedInFuture(uint256 lastUpdated);
|
|
158
|
+
error OracleMaxAgeZeroDisallowed();
|
|
159
|
+
error FeeRecipientNotSet();
|
|
160
|
+
error AddressBlacklisted(address account);
|
|
161
|
+
|
|
162
|
+
/// @notice Addresses blocked from depositing or withdrawing
|
|
163
|
+
mapping(address => bool) public blacklisted;
|
|
164
|
+
|
|
165
|
+
/// @notice Per-user native COTI credited when an ERC20 bridge excess refund could not be pushed to `msg.sender` (e.g. smart contract wallets).
|
|
166
|
+
/// @dev Indexed by the same address that called `deposit`/`withdraw`. Pull via {claimRefundableNativeExcess}; listen for {NativeRefundExcessPushFailed}.
|
|
167
|
+
mapping(address => uint256) public refundableNativeExcess;
|
|
168
|
+
|
|
169
|
+
event Blacklisted(address indexed account, address indexed by);
|
|
170
|
+
event UnBlacklisted(address indexed account, address indexed by);
|
|
171
|
+
event NativeRefundExcessPushFailed(address indexed user, uint256 amount);
|
|
172
|
+
event RefundableNativeExcessClaimed(address indexed user, uint256 amount);
|
|
69
173
|
|
|
70
174
|
// Limits errors
|
|
71
175
|
error InvalidLimitConfiguration();
|
|
@@ -74,8 +178,8 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
74
178
|
error WithdrawBelowMinimum();
|
|
75
179
|
error WithdrawExceedsMaximum();
|
|
76
180
|
error InvalidFee();
|
|
181
|
+
error InvalidFeeConfiguration();
|
|
77
182
|
error InsufficientAccumulatedFees();
|
|
78
|
-
error WithdrawFeesMustBeOverridden();
|
|
79
183
|
|
|
80
184
|
/// @notice Emitted when a user deposits tokens
|
|
81
185
|
/// @param user Address of the user
|
|
@@ -97,17 +201,28 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
97
201
|
uint256 maxWithdraw
|
|
98
202
|
);
|
|
99
203
|
|
|
100
|
-
/// @notice Emitted when fees are updated
|
|
101
|
-
event FeeUpdated(string feeType, uint256 newFeeBasisPoints);
|
|
102
|
-
|
|
103
204
|
/// @notice Emitted when accumulated fees are withdrawn
|
|
104
205
|
event FeesWithdrawn(address indexed to, uint256 amount);
|
|
105
206
|
|
|
106
|
-
|
|
207
|
+
/**
|
|
208
|
+
* @param _feeRecipient Non-zero recipient for swept native fees (immutable for contract lifetime—no setter)
|
|
209
|
+
* @param _rescueRecipient Non-zero recipient for emergency rescue paths (immutable for contract lifetime—no setter)
|
|
210
|
+
* @param _priceOracle Non-zero {ICotiPriceConsumer} used for dynamic fees (owner may later {setPriceOracle})
|
|
211
|
+
*/
|
|
212
|
+
constructor(address _feeRecipient, address _rescueRecipient, address _priceOracle) Ownable() {
|
|
213
|
+
if (_feeRecipient == address(0)) revert InvalidAddress();
|
|
214
|
+
if (_rescueRecipient == address(0)) revert InvalidAddress();
|
|
215
|
+
if (_priceOracle == address(0)) revert InvalidAddress();
|
|
107
216
|
maxDepositAmount = type(uint256).max;
|
|
108
217
|
maxWithdrawAmount = type(uint256).max;
|
|
109
218
|
minDepositAmount = 1;
|
|
110
219
|
minWithdrawAmount = 1;
|
|
220
|
+
feeRecipient = _feeRecipient;
|
|
221
|
+
rescueRecipient = _rescueRecipient;
|
|
222
|
+
priceOracle = _priceOracle;
|
|
223
|
+
maxOracleAge = DEFAULT_MAX_ORACLE_AGE;
|
|
224
|
+
|
|
225
|
+
emit PriceOracleUpdated(address(0), _priceOracle);
|
|
111
226
|
|
|
112
227
|
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
|
113
228
|
_grantRole(OPERATOR_ROLE, msg.sender);
|
|
@@ -135,22 +250,86 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
135
250
|
}
|
|
136
251
|
|
|
137
252
|
/**
|
|
138
|
-
* @
|
|
253
|
+
* @notice Transfers `Ownable` ownership and resets `AccessControl` admins/operators in one step.
|
|
254
|
+
* @dev **Handover semantics:** Every address with `OPERATOR_ROLE` and every address with `DEFAULT_ADMIN_ROLE`
|
|
255
|
+
* (including the current owner) is revoked before `Ownable` transfers to `newOwner`, who then receives
|
|
256
|
+
* both `DEFAULT_ADMIN_ROLE` and `OPERATOR_ROLE`. Any prior operator-only keys lose privilege immediately;
|
|
257
|
+
* plan key ceremonies and off-chain runbooks so no service relies on a revoked operator after transfer.
|
|
258
|
+
* This prevents stale operators from coexisting with a new owner (hidden privileged actors).
|
|
139
259
|
*/
|
|
140
260
|
function transferOwnership(address newOwner) public override onlyOwner {
|
|
141
261
|
if (newOwner == address(0)) revert InvalidAddress();
|
|
142
|
-
|
|
262
|
+
|
|
263
|
+
// Revoke all existing operators before transferring
|
|
264
|
+
uint256 operatorCount = getRoleMemberCount(OPERATOR_ROLE);
|
|
265
|
+
for (uint256 i = operatorCount; i > 0; i--) {
|
|
266
|
+
address op = getRoleMember(OPERATOR_ROLE, i - 1);
|
|
267
|
+
_revokeRole(OPERATOR_ROLE, op);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Revoke all existing admins
|
|
271
|
+
uint256 adminCount = getRoleMemberCount(DEFAULT_ADMIN_ROLE);
|
|
272
|
+
for (uint256 i = adminCount; i > 0; i--) {
|
|
273
|
+
address admin = getRoleMember(DEFAULT_ADMIN_ROLE, i - 1);
|
|
274
|
+
_revokeRole(DEFAULT_ADMIN_ROLE, admin);
|
|
275
|
+
}
|
|
276
|
+
|
|
143
277
|
super.transferOwnership(newOwner);
|
|
144
278
|
_grantRole(DEFAULT_ADMIN_ROLE, newOwner);
|
|
145
279
|
_grantRole(OPERATOR_ROLE, newOwner);
|
|
146
|
-
|
|
147
|
-
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @dev **Intentionally disabled** (reverts with a fixed message). `renounceOwnership` would leave `AccessControl`
|
|
284
|
+
* roles and admins in place while clearing `Ownable.owner`, producing ambiguous governance (`onlyOwner`
|
|
285
|
+
* vs `onlyRole`). Use {transferOwnership} to a burn/multisig address if governance must be vacated, after
|
|
286
|
+
* revoking roles through the normal owner-controlled flows this contract expects.
|
|
287
|
+
*/
|
|
288
|
+
function renounceOwnership() public override onlyOwner {
|
|
289
|
+
revert("renounceOwnership disabled");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* @notice Add an address to the blacklist, preventing deposits and withdrawals.
|
|
294
|
+
* @param account The address to blacklist
|
|
295
|
+
* @dev Only the owner can call this function.
|
|
296
|
+
*/
|
|
297
|
+
function addToBlacklist(address account) external onlyOwner {
|
|
298
|
+
if (account == address(0)) revert InvalidAddress();
|
|
299
|
+
blacklisted[account] = true;
|
|
300
|
+
emit Blacklisted(account, msg.sender);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* @notice Remove an address from the blacklist.
|
|
305
|
+
* @param account The address to remove
|
|
306
|
+
* @dev Only the owner can call this function.
|
|
307
|
+
*/
|
|
308
|
+
function removeFromBlacklist(address account) external onlyOwner {
|
|
309
|
+
if (account == address(0)) revert InvalidAddress();
|
|
310
|
+
blacklisted[account] = false;
|
|
311
|
+
emit UnBlacklisted(account, msg.sender);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* @dev Reverts if the caller is blacklisted. Applies to deposit, withdraw, and {claimRefundableNativeExcess}.
|
|
316
|
+
* Blacklisted addresses are intentionally **not** exempted on claim: policy treats them as abusive;
|
|
317
|
+
* credited {refundableNativeExcess} for that address remains until the owner removes the listing or
|
|
318
|
+
* another agreed process applies.
|
|
319
|
+
*/
|
|
320
|
+
modifier notBlacklisted() {
|
|
321
|
+
if (blacklisted[msg.sender]) revert AddressBlacklisted(msg.sender);
|
|
322
|
+
_;
|
|
148
323
|
}
|
|
149
324
|
|
|
150
325
|
/**
|
|
151
326
|
* @notice Update deposit and withdrawal limits
|
|
152
327
|
* @dev Ensures min values are less than or equal to max values.
|
|
153
328
|
* Setting _maxDeposit or _maxWithdraw to 0 effectively disables deposits or withdrawals.
|
|
329
|
+
* Note: cross-parameter coherence (e.g. minDeposit after fee >= minWithdraw) cannot be
|
|
330
|
+
* validated on-chain because fees are dynamic and depend on the oracle price at transaction
|
|
331
|
+
* time, not at the time limits are set. The operator is responsible for ensuring that the
|
|
332
|
+
* smallest valid deposit mints at least the smallest valid withdrawal amount.
|
|
154
333
|
* @param _minDeposit New minimum deposit amount
|
|
155
334
|
* @param _maxDeposit New maximum deposit amount
|
|
156
335
|
* @param _minWithdraw New minimum withdrawal amount
|
|
@@ -178,8 +357,10 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
178
357
|
}
|
|
179
358
|
|
|
180
359
|
/**
|
|
181
|
-
* @notice
|
|
182
|
-
* @dev Only the owner can call this function
|
|
360
|
+
* @notice Emergency stop — pause the bridge, preventing all deposits and withdrawals.
|
|
361
|
+
* @dev Only the owner can call this function. Pausing also gates rescue paths on derived contracts: once
|
|
362
|
+
* paused, the owner can move TVL via rescue (see contract @dev (3)). Use pause only with operational
|
|
363
|
+
* awareness of that combined authority.
|
|
183
364
|
*/
|
|
184
365
|
function pause() external onlyOwner {
|
|
185
366
|
_pause();
|
|
@@ -214,105 +395,206 @@ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessCon
|
|
|
214
395
|
}
|
|
215
396
|
|
|
216
397
|
/**
|
|
217
|
-
* @notice
|
|
218
|
-
* @param
|
|
398
|
+
* @notice Toggle deposit functionality
|
|
399
|
+
* @param _enabled True to enable, false to disable
|
|
219
400
|
* @dev Only the operator can call this function
|
|
220
401
|
*/
|
|
221
|
-
function
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
402
|
+
function setIsDepositEnabled(bool _enabled) external onlyOperator {
|
|
403
|
+
isDepositEnabled = _enabled;
|
|
404
|
+
emit DepositEnabledUpdated(_enabled, msg.sender);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function _requirePriceOracle() internal view {
|
|
408
|
+
if (priceOracle == address(0)) revert PriceOracleNotSet();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function _requirePositiveOracleRate(uint256 rate) internal pure {
|
|
412
|
+
if (rate == 0) revert InvalidOraclePrice();
|
|
225
413
|
}
|
|
226
414
|
|
|
227
415
|
/**
|
|
228
|
-
* @
|
|
229
|
-
*
|
|
230
|
-
*
|
|
416
|
+
* @dev Credits `user` when the ERC20 bridge’s push-refund of native excess after fee collection returns false
|
|
417
|
+
* (common with smart contract accounts / AA wallets that reject unsolicited ETH, or `receive`/`fallback`
|
|
418
|
+
* reverts). Funds remain on the bridge until {claimRefundableNativeExcess}. UIs should watch
|
|
419
|
+
* {NativeRefundExcessPushFailed} and prompt the same `user` to claim; the amount is not in
|
|
420
|
+
* {accumulatedCotiFees} and cannot be swept as protocol fees.
|
|
231
421
|
*/
|
|
232
|
-
function
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
emit FeeUpdated("withdraw", _feeBasisPoints);
|
|
422
|
+
function _creditRefundableNativeExcess(address user, uint256 amount) internal {
|
|
423
|
+
refundableNativeExcess[user] += amount;
|
|
424
|
+
emit NativeRefundExcessPushFailed(user, amount);
|
|
236
425
|
}
|
|
237
426
|
|
|
238
427
|
/**
|
|
239
|
-
* @notice
|
|
240
|
-
* @
|
|
241
|
-
*
|
|
428
|
+
* @notice Pull native COTI previously credited when the ERC20 bridge could not push the fee excess to you.
|
|
429
|
+
* @dev Same push pattern as the original refund: `msg.sender.call{value: amount}`. If your wallet still
|
|
430
|
+
* rejects ETH, the call reverts with {EthTransferFailed} and your credit is restored so you can try
|
|
431
|
+
* again from an address that accepts native transfers (the protocol does not support forwarding to a
|
|
432
|
+
* third-party payout address). Not gated by {whenPaused}; {notBlacklisted} applies ({AddressBlacklisted})—
|
|
433
|
+
* blacklisted callers cannot pull credits by design (see {notBlacklisted}).
|
|
242
434
|
*/
|
|
243
|
-
function
|
|
244
|
-
|
|
245
|
-
|
|
435
|
+
function claimRefundableNativeExcess() external nonReentrant notBlacklisted {
|
|
436
|
+
uint256 amount = refundableNativeExcess[msg.sender];
|
|
437
|
+
if (amount == 0) revert AmountZero();
|
|
438
|
+
refundableNativeExcess[msg.sender] = 0;
|
|
439
|
+
if (address(this).balance < amount) revert InsufficientEthBalance();
|
|
440
|
+
(bool success, ) = msg.sender.call{value: amount}("");
|
|
441
|
+
if (!success) {
|
|
442
|
+
refundableNativeExcess[msg.sender] = amount;
|
|
443
|
+
revert EthTransferFailed();
|
|
444
|
+
}
|
|
445
|
+
emit RefundableNativeExcessClaimed(msg.sender, amount);
|
|
246
446
|
}
|
|
247
447
|
|
|
248
448
|
/**
|
|
249
|
-
* @notice
|
|
250
|
-
* @
|
|
251
|
-
* @dev Used by ERC20 bridges: they require msg.value >= this value and refund excess to the caller (best-effort). Only the operator can call this function.
|
|
449
|
+
* @notice Reject oracle rows that are too old vs `block.timestamp` per {maxOracleAge}.
|
|
450
|
+
* @dev {maxOracleAge} is always non-zero in normal configuration ({setMaxOracleAge} forbids zero).
|
|
252
451
|
*/
|
|
253
|
-
function
|
|
254
|
-
|
|
255
|
-
|
|
452
|
+
function _requireOracleFreshness(uint256 lastUpdated) internal view {
|
|
453
|
+
uint256 maxAge = maxOracleAge;
|
|
454
|
+
if (lastUpdated > block.timestamp) revert OracleLastUpdatedInFuture(lastUpdated);
|
|
455
|
+
uint256 nowTs = block.timestamp;
|
|
456
|
+
if (nowTs - lastUpdated > maxAge) revert OraclePriceStale(lastUpdated, nowTs, maxAge);
|
|
256
457
|
}
|
|
257
458
|
|
|
258
459
|
/**
|
|
259
|
-
* @notice
|
|
260
|
-
* @dev
|
|
460
|
+
* @notice Validate oracle timestamps for both COTI and a bridged token.
|
|
461
|
+
* @dev Strict equality: on-chain `lastUpdated` for COTI and for `tokenSymbol` must exactly equal the
|
|
462
|
+
* `expected*` values supplied by the client. That binds execution to the same Band row the user
|
|
463
|
+
* saw when calling the estimate view; if the feed publishes a newer row before inclusion, the check
|
|
464
|
+
* reverts with {OracleTimestampMismatch} so price cannot change under the user without a visible revert.
|
|
465
|
+
* This strict binding is **intentional** (no relaxation): with a typical ~30 minute oracle cadence and
|
|
466
|
+
* {maxOracleAge} buffer, users have a long window to sign and broadcast the same row; we avoid any path
|
|
467
|
+
* where the UI shows one Band row and execution silently uses a newer price.
|
|
468
|
+
* Failures are timing/race issues (mempool delay vs oracle refresh cadence), not third-party griefing.
|
|
469
|
+
* Integrators: call estimate immediately before building the tx; pass returned timestamps unchanged into
|
|
470
|
+
* deposit/withdraw; on mismatch, re-estimate and resubmit; avoid submit across a refresh boundary (COTI UI
|
|
471
|
+
* blocks ~10s before a scheduled tick—mirror that); simulate right before broadcast. {_requireOracleFreshness}
|
|
472
|
+
* still enforces {maxOracleAge} on the matched row.
|
|
473
|
+
* @param expectedCotiTimestamp COTI `lastUpdated` from the user's latest estimate (must equal on-chain).
|
|
474
|
+
* @param expectedTokenTimestamp Token `lastUpdated` from the user's latest estimate (must equal on-chain).
|
|
475
|
+
* @param tokenSymbol The Band oracle symbol for the bridged token (native bridge uses `"COTI"` for both).
|
|
261
476
|
*/
|
|
262
|
-
function
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
477
|
+
function _validateOracleTimestamps(
|
|
478
|
+
uint256 expectedCotiTimestamp,
|
|
479
|
+
uint256 expectedTokenTimestamp,
|
|
480
|
+
string memory tokenSymbol
|
|
481
|
+
) internal view {
|
|
482
|
+
_requirePriceOracle();
|
|
483
|
+
(, uint256 cotiLastUpdated,) = ICotiPriceConsumer(priceOracle).getPriceWithMeta("COTI");
|
|
484
|
+
if (cotiLastUpdated != expectedCotiTimestamp) revert OracleTimestampMismatch(expectedCotiTimestamp, cotiLastUpdated);
|
|
485
|
+
_requireOracleFreshness(cotiLastUpdated);
|
|
486
|
+
(, uint256 tokenLastUpdated,) = ICotiPriceConsumer(priceOracle).getPriceWithMeta(tokenSymbol);
|
|
487
|
+
if (tokenLastUpdated != expectedTokenTimestamp) revert OracleTimestampMismatch(expectedTokenTimestamp, tokenLastUpdated);
|
|
488
|
+
_requireOracleFreshness(tokenLastUpdated);
|
|
266
489
|
}
|
|
267
490
|
|
|
268
|
-
|
|
269
491
|
/**
|
|
270
|
-
* @notice Calculate
|
|
271
|
-
* @param
|
|
272
|
-
* @param
|
|
273
|
-
* @
|
|
492
|
+
* @notice Calculate the dynamic fee using the floor/cap formula
|
|
493
|
+
* @param percentageFeeCoti The percentage-based fee component in COTI
|
|
494
|
+
* @param fixedFee The minimum fee floor in COTI
|
|
495
|
+
* @param maxFee The maximum fee cap in COTI
|
|
496
|
+
* @return The computed fee: min(max(fixedFee, percentageFeeCoti), maxFee)
|
|
274
497
|
*/
|
|
275
|
-
function
|
|
276
|
-
uint256
|
|
277
|
-
uint256
|
|
498
|
+
function _calculateDynamicFee(
|
|
499
|
+
uint256 percentageFeeCoti,
|
|
500
|
+
uint256 fixedFee,
|
|
501
|
+
uint256 maxFee
|
|
278
502
|
) internal pure returns (uint256) {
|
|
279
|
-
|
|
280
|
-
return
|
|
503
|
+
uint256 fee = percentageFeeCoti > fixedFee ? percentageFeeCoti : fixedFee;
|
|
504
|
+
return fee > maxFee ? maxFee : fee;
|
|
281
505
|
}
|
|
282
506
|
|
|
283
507
|
/**
|
|
284
|
-
* @notice
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
* to perform the actual token/native transfer; base implementation reverts.
|
|
508
|
+
* @notice Estimate functions are declared in derived contracts (Native and ERC20 bridges)
|
|
509
|
+
* with different return signatures:
|
|
510
|
+
* - Native: returns (fee, lastUpdated, blockTimestamp)
|
|
511
|
+
* - ERC20: returns (fee, cotiLastUpdated, tokenLastUpdated, blockTimestamp)
|
|
289
512
|
*/
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* @notice Set the deposit dynamic fee parameters
|
|
516
|
+
* @param _fixedFee New deposit fee floor in COTI wei
|
|
517
|
+
* @param _percentageBps New deposit percentage (max MAX_FEE_UNITS = 10%)
|
|
518
|
+
* @param _maxFee New deposit fee cap in COTI wei
|
|
519
|
+
* @dev Only the operator can call this function
|
|
520
|
+
*/
|
|
521
|
+
function setDepositDynamicFee(
|
|
522
|
+
uint256 _fixedFee,
|
|
523
|
+
uint256 _percentageBps,
|
|
524
|
+
uint256 _maxFee
|
|
525
|
+
) external onlyOperator {
|
|
526
|
+
if (_maxFee == 0) revert InvalidFeeConfiguration();
|
|
527
|
+
if (_fixedFee > _maxFee) revert InvalidFeeConfiguration();
|
|
528
|
+
if (_percentageBps > MAX_FEE_UNITS) revert InvalidFee();
|
|
529
|
+
depositFixedFee = _fixedFee;
|
|
530
|
+
depositPercentageBps = _percentageBps;
|
|
531
|
+
depositMaxFee = _maxFee;
|
|
532
|
+
emit DynamicFeeUpdated("deposit", _fixedFee, _percentageBps, _maxFee);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* @notice Set the withdraw dynamic fee parameters
|
|
537
|
+
* @param _fixedFee New withdraw fee floor in COTI wei
|
|
538
|
+
* @param _percentageBps New withdraw percentage (max MAX_FEE_UNITS = 10%)
|
|
539
|
+
* @param _maxFee New withdraw fee cap in COTI wei
|
|
540
|
+
* @dev Only the operator can call this function
|
|
541
|
+
*/
|
|
542
|
+
function setWithdrawDynamicFee(
|
|
543
|
+
uint256 _fixedFee,
|
|
544
|
+
uint256 _percentageBps,
|
|
545
|
+
uint256 _maxFee
|
|
546
|
+
) external onlyOperator {
|
|
547
|
+
if (_maxFee == 0) revert InvalidFeeConfiguration();
|
|
548
|
+
if (_fixedFee > _maxFee) revert InvalidFeeConfiguration();
|
|
549
|
+
if (_percentageBps > MAX_FEE_UNITS) revert InvalidFee();
|
|
550
|
+
withdrawFixedFee = _fixedFee;
|
|
551
|
+
withdrawPercentageBps = _percentageBps;
|
|
552
|
+
withdrawMaxFee = _maxFee;
|
|
553
|
+
emit DynamicFeeUpdated("withdraw", _fixedFee, _percentageBps, _maxFee);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* @notice Set the price oracle address
|
|
558
|
+
* @param _oracle Address of the CotiPriceConsumer contract
|
|
559
|
+
* @dev Only the owner can call this function
|
|
560
|
+
*/
|
|
561
|
+
function setPriceOracle(address _oracle) external onlyOwner {
|
|
562
|
+
if (_oracle == address(0)) revert InvalidAddress();
|
|
563
|
+
address oldOracle = priceOracle;
|
|
564
|
+
priceOracle = _oracle;
|
|
565
|
+
emit PriceOracleUpdated(oldOracle, _oracle);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* @notice Set the maximum allowed age of oracle `lastUpdated` (seconds) relative to `block.timestamp`.
|
|
570
|
+
* @param _maxOracleAge Must be non-zero. Default after deploy is {DEFAULT_MAX_ORACLE_AGE} (30 min cadence + 5 min buffer).
|
|
571
|
+
* @dev Zero is rejected so production cannot accidentally turn off staleness bounds; for very lenient test
|
|
572
|
+
* environments use a large finite value instead.
|
|
573
|
+
*/
|
|
574
|
+
function setMaxOracleAge(uint256 _maxOracleAge) external onlyOwner {
|
|
575
|
+
if (_maxOracleAge == 0) revert OracleMaxAgeZeroDisallowed();
|
|
576
|
+
maxOracleAge = _maxOracleAge;
|
|
577
|
+
emit MaxOracleAgeUpdated(_maxOracleAge, msg.sender);
|
|
298
578
|
}
|
|
299
579
|
|
|
580
|
+
event CotiFeesWithdrawn(address indexed feeRecipient, uint256 amount);
|
|
581
|
+
|
|
300
582
|
/**
|
|
301
|
-
* @notice Withdraw accumulated native COTI fees
|
|
302
|
-
* @param to Address to send the native COTI fees to
|
|
583
|
+
* @notice Withdraw accumulated native COTI fees to the predefined feeRecipient
|
|
303
584
|
* @param amount Amount of native COTI fees to withdraw
|
|
304
|
-
* @dev Only the
|
|
305
|
-
* accumulated native COTI fees; native bridge does not use this (accumulatedCotiFees remains 0).
|
|
585
|
+
* @dev Only the owner can call this function.
|
|
306
586
|
*/
|
|
307
|
-
function withdrawCotiFees(
|
|
308
|
-
if (
|
|
587
|
+
function withdrawCotiFees(uint256 amount) external onlyOwner nonReentrant {
|
|
588
|
+
if (feeRecipient == address(0)) revert FeeRecipientNotSet();
|
|
309
589
|
if (amount == 0) revert AmountZero();
|
|
310
590
|
if (amount > accumulatedCotiFees) revert InsufficientAccumulatedFees();
|
|
311
591
|
if (amount > address(this).balance) revert InsufficientEthBalance();
|
|
312
592
|
|
|
313
593
|
accumulatedCotiFees -= amount;
|
|
314
594
|
|
|
315
|
-
(bool success, ) =
|
|
595
|
+
(bool success, ) = feeRecipient.call{value: amount}("");
|
|
316
596
|
if (!success) revert EthTransferFailed();
|
|
597
|
+
|
|
598
|
+
emit CotiFeesWithdrawn(feeRecipient, amount);
|
|
317
599
|
}
|
|
318
600
|
}
|