@coti-io/coti-contracts 1.1.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 +19 -15
- package/README.md +3 -1
- package/contracts/disperse/coinByRatio/FixedRatioCoinDisperser.sol +452 -0
- package/contracts/disperse/coinByRatio/FixedRatioCoinDisperserLeftoverS1.sol +490 -0
- package/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow.sol +432 -0
- package/contracts/disperse/disperseToken/MintDisperser.sol +120 -0
- package/contracts/disperse/disperseToken/TokenDisperser.sol +139 -0
- 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/ERC20Mock.sol +19 -0
- package/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock.sol +18 -0
- package/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.sol +18 -0
- package/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock.sol +44 -0
- package/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock.sol +23 -0
- package/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock.sol +29 -0
- package/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.sol +9 -4
- package/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol +39 -0
- package/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock.sol +29 -0
- package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock.sol +18 -0
- package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock.sol +12 -0
- package/contracts/mocks/utils/mpc/Arithmetic128TestsContract.sol +123 -0
- package/contracts/mocks/utils/mpc/Arithmetic256TestsContract.sol +122 -0
- package/contracts/mocks/utils/mpc/Bitwise128TestsContract.sol +65 -0
- package/contracts/mocks/utils/mpc/Bitwise256TestsContract.sol +65 -0
- package/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract.sol +64 -0
- package/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract.sol +64 -0
- package/contracts/mocks/utils/mpc/Comparison128TestsContract.sol +98 -0
- package/contracts/mocks/utils/mpc/Comparison256TestsContract.sol +98 -0
- package/contracts/mocks/utils/mpc/MinMax128TestsContract.sol +44 -0
- package/contracts/mocks/utils/mpc/MinMax256TestsContract.sol +44 -0
- package/contracts/mocks/utils/mpc/MinimalImplementation.sol +55 -0
- package/contracts/mocks/utils/mpc/MinimalProxy.sol +27 -0
- package/contracts/mocks/utils/mpc/MpcOperations128TestContract.sol +267 -0
- package/contracts/mocks/utils/mpc/MpcOperationsTestContract.sol +334 -0
- package/contracts/mocks/utils/mpc/Mux128TestsContract.sol +24 -0
- package/contracts/mocks/utils/mpc/Mux256TestsContract.sol +24 -0
- package/contracts/mocks/utils/mpc/OnBoard128TestsContract.sol +93 -0
- package/contracts/mocks/utils/mpc/OnBoard256TestsContract.sol +116 -0
- package/contracts/mocks/utils/mpc/PrivacyImplementationV1.sol +157 -0
- package/contracts/mocks/utils/mpc/PrivacyImplementationV2.sol +133 -0
- package/contracts/mocks/utils/mpc/PrivacyProxy.sol +137 -0
- package/contracts/mocks/utils/mpc/Random128TestsContract.sol +32 -0
- package/contracts/mocks/utils/mpc/Random256TestsContract.sol +32 -0
- package/contracts/mocks/utils/mpc/Shift128TestsContract.sol +36 -0
- package/contracts/mocks/utils/mpc/Shift256TestsContract.sol +36 -0
- package/contracts/mocks/utils/mpc/Transfer128TestsContract.sol +29 -0
- package/contracts/mocks/utils/mpc/Transfer256TestsContract.sol +29 -0
- package/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract.sol +32 -0
- package/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract.sol +32 -0
- package/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract.sol +59 -0
- package/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract.sol +63 -0
- package/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract.sol +99 -0
- package/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.sol +7 -6
- package/contracts/node/CotiNodeRewards.sol +199 -0
- package/contracts/node/SoulboundNodeNFT.sol +519 -0
- 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 +600 -0
- package/contracts/privacyBridge/PrivacyBridgeCotiNative.sol +316 -0
- package/contracts/privacyBridge/PrivacyBridgeERC20.sol +333 -0
- package/contracts/privacyBridge/PrivacyBridgeUSDCe.sol +22 -0
- package/contracts/privacyBridge/PrivacyBridgeUSDT.sol +23 -0
- package/contracts/privacyBridge/PrivacyBridgeWADA.sol +23 -0
- package/contracts/privacyBridge/PrivacyBridgeWBTC.sol +23 -0
- package/contracts/privacyBridge/PrivacyBridgeWETH.sol +23 -0
- package/contracts/privacyBridge/PrivacyBridgegCoti.sol +23 -0
- package/contracts/token/PrivateERC20/IPrivateERC20.sol +273 -40
- package/contracts/token/PrivateERC20/ITokenReceiver.sol +17 -0
- package/contracts/token/PrivateERC20/ITokenReceiverEncrypted.sol +20 -0
- package/contracts/token/PrivateERC20/PrivateERC20.sol +861 -152
- package/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC.sol +17 -0
- package/contracts/token/PrivateERC20/tokens/PrivateCOTI.sol +13 -0
- package/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken.sol +17 -0
- package/contracts/token/PrivateERC20/tokens/PrivateTetherUSD.sol +17 -0
- package/contracts/token/PrivateERC20/tokens/PrivateWrappedADA.sol +17 -0
- package/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC.sol +17 -0
- package/contracts/token/PrivateERC20/tokens/PrivateWrappedEther.sol +13 -0
- package/contracts/utils/mpc/MpcCore.sol +10780 -4962
- package/contracts/utils/mpc/MpcInterface.sol +7 -2
- package/hardhat/gasPriceBump.ts +60 -0
- package/hardhat.config.ts +63 -12
- package/package.json +22 -4
- 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/deploySoulboundNodeNFT.ts +57 -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 +250 -0
- package/test/token/PrivateERC20/PrivateERC20.test.ts +1109 -268
- package/test/utils/mpc/Bitwise128.test.ts +92 -0
- package/test/utils/mpc/Bitwise256.test.ts +101 -0
- package/test/utils/mpc/BuildInputText128.test.ts +398 -0
- package/test/utils/mpc/CheckedArithmetic128.test.ts +45 -0
- package/test/utils/mpc/CheckedArithmetic256.test.ts +45 -0
- package/test/utils/mpc/Comparison128.test.ts +48 -0
- package/test/utils/mpc/Comparison256.test.ts +48 -0
- package/test/utils/mpc/InvalidCiphertext.test.ts +179 -0
- package/test/utils/mpc/InvalidCiphertext128.test.ts +179 -0
- package/test/utils/mpc/InvalidCiphertext256.test.ts +201 -0
- package/test/utils/mpc/InvalidTransfer128.test.ts +166 -0
- package/test/utils/mpc/InvalidTransfer256.test.ts +158 -0
- package/test/utils/mpc/MinMax128.test.ts +44 -0
- package/test/utils/mpc/MinMax256.test.ts +44 -0
- package/test/utils/mpc/MinimalProxyDemo.test.ts +280 -0
- package/test/utils/mpc/MpcOperations.test.ts +589 -0
- package/test/utils/mpc/MpcOperations128.test.ts +632 -0
- package/test/utils/mpc/Mux128.test.ts +41 -0
- package/test/utils/mpc/Mux256.test.ts +41 -0
- package/test/utils/mpc/NegativeCases.test.ts +478 -0
- package/test/utils/mpc/NegativeCases128.test.ts +237 -0
- package/test/utils/mpc/NegativeCases256.test.ts +236 -0
- package/test/utils/mpc/OnBoard128.test.ts +90 -0
- package/test/utils/mpc/OnBoard256.test.ts +114 -0
- package/test/utils/mpc/Precompile128.test.ts +51 -0
- package/test/utils/mpc/Precompile256.test.ts +115 -0
- package/test/utils/mpc/ProxyValidation.test.ts +199 -0
- package/test/utils/mpc/Random128.test.ts +47 -0
- package/test/utils/mpc/Random256.test.ts +47 -0
- package/test/utils/mpc/Shift128.test.ts +41 -0
- package/test/utils/mpc/Shift256.test.ts +41 -0
- package/test/utils/mpc/Transfer128.test.ts +46 -0
- package/test/utils/mpc/Transfer256.test.ts +46 -0
- package/test/utils/mpc/TransferWithAllowance128.test.ts +48 -0
- package/test/utils/mpc/TransferWithAllowance256.test.ts +48 -0
- package/test/utils/mpc/UpgradeablePrivacyProxy.test.ts +307 -0
- package/test/utils/mpc/ValidateCiphertext.test.ts +221 -0
- package/test/utils/mpc/ValidateCiphertext256.test.ts +161 -0
- package/test/utils/mpc/ValidateCiphertext256Decryption.test.ts +383 -0
- package/test/utils/mpc/WalletEncryptionFailures.test.ts +494 -0
- package/test/utils/privateErc20Helpers.ts +97 -0
- 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/Ownable.ts +153 -0
- package/typechain-types/@openzeppelin/contracts/access/index.ts +8 -0
- package/typechain-types/@openzeppelin/contracts/index.ts +4 -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/IERC20.ts +262 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.ts +286 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.ts +143 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/index.ts +5 -0
- package/typechain-types/@openzeppelin/contracts/token/ERC20/index.ts +7 -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/@openzeppelin/contracts/token/index.ts +2 -0
- package/typechain-types/contracts/disperse/coinByRatio/FixedRatioCoinDisperser.ts +679 -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 +6 -0
- package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/IMintableERC20.ts +97 -0
- package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/IOwnable.ts +95 -0
- package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser.ts +228 -0
- package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +6 -0
- package/typechain-types/contracts/disperse/disperseToken/TokenDisperser.ts +191 -0
- package/typechain-types/contracts/disperse/disperseToken/index.ts +6 -0
- package/typechain-types/contracts/disperse/index.ts +7 -0
- package/typechain-types/contracts/index.ts +10 -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/token/PrivateERC20/PrivateERC20GtCallerMock.ts +166 -0
- package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.ts +827 -78
- 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/utils/mpc/{Arithmetic128BitTestsContract.ts → Arithmetic128TestsContract.ts} +96 -126
- package/typechain-types/contracts/mocks/utils/mpc/{Arithmetic256BitTestsContract.ts → Arithmetic256TestsContract.ts} +97 -133
- package/typechain-types/contracts/mocks/utils/mpc/{Bitwise128BitTestsContract.ts → Bitwise128TestsContract.ts} +52 -59
- package/typechain-types/contracts/mocks/utils/mpc/{Bitwise256BitTestsContract.ts → Bitwise256TestsContract.ts} +52 -59
- package/typechain-types/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract.ts +206 -0
- package/typechain-types/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract.ts +206 -0
- package/typechain-types/contracts/mocks/utils/mpc/{Comparison128BitTestsContract.ts → Comparison128TestsContract.ts} +115 -97
- package/typechain-types/contracts/mocks/utils/mpc/{Comparison256BitTestsContract.ts → Comparison256TestsContract.ts} +115 -97
- package/typechain-types/contracts/mocks/utils/mpc/MinMax128TestsContract.ts +142 -0
- package/typechain-types/contracts/mocks/utils/mpc/MinMax256TestsContract.ts +142 -0
- package/typechain-types/contracts/mocks/utils/mpc/MinimalImplementation.ts +259 -0
- package/typechain-types/contracts/mocks/utils/mpc/MinimalProxy.ts +90 -0
- package/typechain-types/contracts/mocks/utils/mpc/MpcOperations128TestContract.ts +388 -0
- package/typechain-types/contracts/mocks/utils/mpc/MpcOperationsTestContract.ts +455 -0
- package/typechain-types/contracts/mocks/utils/mpc/Mux128TestsContract.ts +109 -0
- package/typechain-types/contracts/mocks/utils/mpc/Mux256TestsContract.ts +109 -0
- package/typechain-types/contracts/mocks/utils/mpc/OnBoard128TestsContract.ts +166 -0
- package/typechain-types/contracts/mocks/utils/mpc/OnBoard256TestsContract.ts +194 -0
- package/typechain-types/contracts/mocks/utils/mpc/PrivacyImplementationV1.ts +385 -0
- package/typechain-types/contracts/mocks/utils/mpc/PrivacyImplementationV2.ts +441 -0
- package/typechain-types/contracts/mocks/utils/mpc/PrivacyProxy.ts +201 -0
- package/typechain-types/contracts/mocks/utils/mpc/Random128TestsContract.ts +131 -0
- package/typechain-types/contracts/mocks/utils/mpc/Random256TestsContract.ts +131 -0
- package/typechain-types/contracts/mocks/utils/mpc/Shift128TestsContract.ts +142 -0
- package/typechain-types/contracts/mocks/utils/mpc/Shift256TestsContract.ts +142 -0
- package/typechain-types/contracts/mocks/utils/mpc/Transfer128TestsContract.ts +109 -0
- package/typechain-types/contracts/mocks/utils/mpc/Transfer256TestsContract.ts +109 -0
- package/typechain-types/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract.ts +128 -0
- package/typechain-types/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract.ts +128 -0
- package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract.ts +198 -0
- package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract.ts +182 -0
- package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract.ts +257 -0
- package/typechain-types/contracts/mocks/utils/mpc/index.ts +32 -8
- 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 +507 -70
- 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 +833 -68
- 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/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations.ts +111 -10
- 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/Ownable__factory.ts +74 -0
- package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +8 -0
- package/typechain-types/factories/@openzeppelin/contracts/index.ts +2 -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/IERC20__factory.ts +205 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata__factory.ts +247 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit__factory.ts +100 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/index.ts +5 -0
- package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/index.ts +6 -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/@openzeppelin/contracts/token/index.ts +1 -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 +759 -0
- package/typechain-types/factories/contracts/disperse/coinByRatio/index.ts +6 -0
- package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/IMintableERC20__factory.ts +43 -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 +203 -0
- package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +6 -0
- package/typechain-types/factories/contracts/disperse/disperseToken/TokenDisperser__factory.ts +198 -0
- package/typechain-types/factories/contracts/disperse/disperseToken/index.ts +5 -0
- package/typechain-types/factories/contracts/disperse/index.ts +5 -0
- package/typechain-types/factories/contracts/index.ts +5 -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 +975 -127
- 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 +330 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic256TestsContract__factory.ts +330 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/ArithmeticTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise128TestsContract__factory.ts +184 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise256TestsContract__factory.ts +184 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/BitwiseTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract__factory.ts +203 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract__factory.ts +203 -0
- 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 +295 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison1TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison256TestsContract__factory.ts +295 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison2TestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax128TestsContract__factory.ts +147 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax256TestsContract__factory.ts +147 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinMaxTestsContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinimalImplementation__factory.ts +263 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/MinimalProxy__factory.ts +104 -0
- 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 +723 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/MpcOperationsTestContract__factory.ts +1410 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Mux128TestsContract__factory.ts +115 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Mux256TestsContract__factory.ts +115 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/OffboardToUserKeyTestContract__factory.ts +1 -1
- package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard128TestsContract__factory.ts +175 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard256TestsContract__factory.ts +205 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV1__factory.ts +521 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV2__factory.ts +648 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyProxy__factory.ts +179 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Random128TestsContract__factory.ts +131 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Random256TestsContract__factory.ts +131 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Shift128TestsContract__factory.ts +147 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Shift256TestsContract__factory.ts +147 -0
- 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 +135 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/Transfer256TestsContract__factory.ts +135 -0
- 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 +154 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract__factory.ts +154 -0
- 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 +190 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract__factory.ts +210 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract__factory.ts +260 -0
- package/typechain-types/factories/contracts/mocks/utils/mpc/index.ts +32 -8
- package/typechain-types/factories/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock__factory.ts +10 -28
- 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 +639 -61
- 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 +986 -120
- 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/factories/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations__factory.ts +126 -0
- package/typechain-types/hardhat.d.ts +1772 -278
- package/typechain-types/index.ts +182 -16
- package/contracts/mocks/utils/mpc/Arithmetic128BitTestsContract.sol +0 -260
- package/contracts/mocks/utils/mpc/Arithmetic256BitTestsContract.sol +0 -264
- package/contracts/mocks/utils/mpc/Bitwise128BitTestsContract.sol +0 -91
- package/contracts/mocks/utils/mpc/Bitwise256BitTestsContract.sol +0 -91
- package/contracts/mocks/utils/mpc/Comparison128BitTestsContract.sol +0 -158
- package/contracts/mocks/utils/mpc/Comparison256BitTestsContract.sol +0 -158
- package/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract.sol +0 -185
- package/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract.sol +0 -190
- package/contracts/mocks/utils/mpc/README.md +0 -486
- package/test/utils/mpc/Unsigned128BitIntegers.test.ts +0 -945
- package/test/utils/mpc/Unsigned256BitIntegers.test.ts +0 -1124
- package/test/utils/mpc/helpers.ts +0 -77
- 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
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
|
5
|
+
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
6
|
+
import "@openzeppelin/contracts/utils/Strings.sol";
|
|
7
|
+
import "@openzeppelin/contracts/utils/Base64.sol";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @title SoulboundNodeNFT
|
|
11
|
+
* @notice ERC-721 Soulbound Node Identity NFT with ERC-5192 support
|
|
12
|
+
*
|
|
13
|
+
* @dev High-level properties:
|
|
14
|
+
* - Non-transferable (Soulbound)
|
|
15
|
+
* - ERC-5192 compliant (locked NFTs)
|
|
16
|
+
* - Only contract owner can mint
|
|
17
|
+
* - One NFT per wallet enforced
|
|
18
|
+
* - Minting can be paused by owner
|
|
19
|
+
* - Unlimited total supply
|
|
20
|
+
* - Burnable by token owner or contract owner
|
|
21
|
+
* - On-chain base64-encoded JSON metadata
|
|
22
|
+
* - Uses custom Solidity errors (gas efficient)
|
|
23
|
+
*
|
|
24
|
+
* @dev Intended use case:
|
|
25
|
+
* - Node / validator identity
|
|
26
|
+
* - Credentials
|
|
27
|
+
* - Non-transferable attestations
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/// -----------------------------------------------------------------------
|
|
31
|
+
/// ERC-5192: Minimal Soulbound NFTs
|
|
32
|
+
/// -----------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @dev ERC-5192 interface for signaling soulbound (non-transferable) NFTs.
|
|
36
|
+
* See: https://eips.ethereum.org/EIPS/eip-5192
|
|
37
|
+
*/
|
|
38
|
+
interface IERC5192 {
|
|
39
|
+
/// @notice Emitted when a token is locked (becomes soulbound)
|
|
40
|
+
event Locked(uint256 tokenId);
|
|
41
|
+
|
|
42
|
+
/// @notice Returns whether a token is locked (non-transferable)
|
|
43
|
+
function locked(uint256 tokenId) external view returns (bool);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// -----------------------------------------------------------------------
|
|
47
|
+
/// Custom errors (cheaper than revert strings)
|
|
48
|
+
/// -----------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
error InvalidRecipient();
|
|
51
|
+
error AlreadyOwnsNodeNFT();
|
|
52
|
+
error NodeNameRequired();
|
|
53
|
+
error NodeNameTooLong();
|
|
54
|
+
error SocialURLTooLong();
|
|
55
|
+
error NonexistentToken();
|
|
56
|
+
error SoulboundOperation();
|
|
57
|
+
error NotAuthorized();
|
|
58
|
+
error MintPaused();
|
|
59
|
+
|
|
60
|
+
/// -----------------------------------------------------------------------
|
|
61
|
+
/// Main contract
|
|
62
|
+
/// -----------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
contract SoulboundNodeNFT is ERC721, Ownable, IERC5192 {
|
|
65
|
+
using Strings for uint256;
|
|
66
|
+
|
|
67
|
+
/// @notice Last minted token ID (starts at 0, first mint = 1)
|
|
68
|
+
uint256 public nextTokenId;
|
|
69
|
+
|
|
70
|
+
/// @notice Maximum length (in bytes) for name and socialURL
|
|
71
|
+
uint256 public constant MAX_TEXT_BYTES = 150;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @notice If true, minting is paused.
|
|
75
|
+
* @dev Burn operations are NOT affected.
|
|
76
|
+
*/
|
|
77
|
+
bool public mintPaused;
|
|
78
|
+
|
|
79
|
+
/// @notice Node-specific metadata stored on-chain
|
|
80
|
+
struct NodeData {
|
|
81
|
+
string name; // required
|
|
82
|
+
string image; // optional (ipfs:// or https://)
|
|
83
|
+
string socialURL; // optional
|
|
84
|
+
bool isHot; // true = hot node, false = cold node
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// @dev tokenId => NodeData
|
|
88
|
+
mapping(uint256 => NodeData) private _nodeData;
|
|
89
|
+
|
|
90
|
+
/// @notice Emitted when a new node NFT is minted
|
|
91
|
+
event NodeMinted(
|
|
92
|
+
address indexed to,
|
|
93
|
+
uint256 indexed tokenId,
|
|
94
|
+
string name,
|
|
95
|
+
string image,
|
|
96
|
+
string socialURL
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
/// @notice Emitted when mint pause state is changed
|
|
100
|
+
event MintPausedSet(bool paused);
|
|
101
|
+
|
|
102
|
+
/// @notice Emitted when a token's image URI is updated
|
|
103
|
+
event ImageURIUpdated(uint256 indexed tokenId, string newImageURI);
|
|
104
|
+
|
|
105
|
+
/// @notice Emitted when a token's social URL is updated
|
|
106
|
+
event SocialURLUpdated(uint256 indexed tokenId, string newSocialURL);
|
|
107
|
+
|
|
108
|
+
/// @notice Emitted when a token's node name is updated
|
|
109
|
+
event NodeNameUpdated(uint256 indexed tokenId, string newNodeName);
|
|
110
|
+
|
|
111
|
+
/// @notice Emitted when a token's hot/cold status is updated
|
|
112
|
+
event NodeHotStatusUpdated(uint256 indexed tokenId, bool isHot);
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @notice Contract constructor
|
|
116
|
+
* @param name_ ERC-721 collection name
|
|
117
|
+
* @param symbol_ ERC-721 collection symbol
|
|
118
|
+
* @param initialOwner Address that becomes contract owner
|
|
119
|
+
*/
|
|
120
|
+
constructor(
|
|
121
|
+
string memory name_,
|
|
122
|
+
string memory symbol_,
|
|
123
|
+
address initialOwner
|
|
124
|
+
) ERC721(name_, symbol_) {
|
|
125
|
+
_transferOwnership(initialOwner);
|
|
126
|
+
mintPaused = false;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// -----------------------------------------------------------------------
|
|
130
|
+
/// Admin: pause / unpause minting
|
|
131
|
+
/// -----------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @notice Pause minting operations
|
|
135
|
+
* @dev Only the contract owner can call this function
|
|
136
|
+
* @dev Only affects minting, not burning operations
|
|
137
|
+
* @dev Emits MintPausedSet event with true
|
|
138
|
+
*/
|
|
139
|
+
function pauseMint() external onlyOwner {
|
|
140
|
+
mintPaused = true;
|
|
141
|
+
emit MintPausedSet(true);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @notice Unpause minting operations
|
|
146
|
+
* @dev Only the contract owner can call this function
|
|
147
|
+
* @dev Emits MintPausedSet event with false
|
|
148
|
+
*/
|
|
149
|
+
function unpauseMint() external onlyOwner {
|
|
150
|
+
mintPaused = false;
|
|
151
|
+
emit MintPausedSet(false);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// -----------------------------------------------------------------------
|
|
155
|
+
/// ERC-5192 (Soulbound signaling)
|
|
156
|
+
/// -----------------------------------------------------------------------
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @notice Check whether a token is locked (soulbound)
|
|
160
|
+
* @param tokenId Token ID to check
|
|
161
|
+
* @return Always true for existing tokens
|
|
162
|
+
* @dev Reverts if token does not exist
|
|
163
|
+
*/
|
|
164
|
+
function locked(uint256 tokenId) external view override returns (bool) {
|
|
165
|
+
if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @notice ERC-165 interface support
|
|
171
|
+
* @param interfaceId Interface identifier to check
|
|
172
|
+
* @return true if the contract supports the interface, false otherwise
|
|
173
|
+
* @dev Supports ERC721, ERC165, and ERC5192 interfaces
|
|
174
|
+
*/
|
|
175
|
+
function supportsInterface(
|
|
176
|
+
bytes4 interfaceId
|
|
177
|
+
) public view override(ERC721) returns (bool) {
|
|
178
|
+
return
|
|
179
|
+
interfaceId == type(IERC5192).interfaceId ||
|
|
180
|
+
super.supportsInterface(interfaceId);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// -----------------------------------------------------------------------
|
|
184
|
+
/// Minting (ONLY OWNER)
|
|
185
|
+
/// -----------------------------------------------------------------------
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @notice Mint a new soulbound Node NFT
|
|
189
|
+
* @param to Recipient address
|
|
190
|
+
* @param name Node name (required, <=150 bytes)
|
|
191
|
+
* @param image Optional image URI
|
|
192
|
+
* @param socialURL Optional social URL (<=150 bytes)
|
|
193
|
+
* @return tokenId The ID of the newly minted token
|
|
194
|
+
* @dev Restrictions:
|
|
195
|
+
* - Only contract owner can mint
|
|
196
|
+
* - Minting must not be paused
|
|
197
|
+
* - Recipient may own at most one NFT
|
|
198
|
+
* @dev Reverts if:
|
|
199
|
+
* - Minting is paused (MintPaused)
|
|
200
|
+
* - to is the zero address (InvalidRecipient)
|
|
201
|
+
* - to already owns an NFT (AlreadyOwnsNodeNFT)
|
|
202
|
+
* - name is empty (NodeNameRequired)
|
|
203
|
+
* - name exceeds MAX_TEXT_BYTES (NodeNameTooLong)
|
|
204
|
+
* - socialURL exceeds MAX_TEXT_BYTES (SocialURLTooLong)
|
|
205
|
+
* @dev Emits Locked and NodeMinted events
|
|
206
|
+
*/
|
|
207
|
+
function mintNode(
|
|
208
|
+
address to,
|
|
209
|
+
string calldata name,
|
|
210
|
+
string calldata image,
|
|
211
|
+
string calldata socialURL
|
|
212
|
+
) external onlyOwner returns (uint256 tokenId) {
|
|
213
|
+
if (mintPaused) revert MintPaused();
|
|
214
|
+
if (to == address(0)) revert InvalidRecipient();
|
|
215
|
+
if (balanceOf(to) != 0) revert AlreadyOwnsNodeNFT();
|
|
216
|
+
if (bytes(name).length == 0) revert NodeNameRequired();
|
|
217
|
+
if (bytes(name).length > MAX_TEXT_BYTES) revert NodeNameTooLong();
|
|
218
|
+
if (bytes(socialURL).length > MAX_TEXT_BYTES) revert SocialURLTooLong();
|
|
219
|
+
|
|
220
|
+
tokenId = ++nextTokenId;
|
|
221
|
+
|
|
222
|
+
_safeMint(to, tokenId);
|
|
223
|
+
|
|
224
|
+
_nodeData[tokenId] = NodeData({
|
|
225
|
+
name: name,
|
|
226
|
+
image: image,
|
|
227
|
+
socialURL: socialURL,
|
|
228
|
+
// Default new nodes to hot; can be updated later via setNodeHotStatus
|
|
229
|
+
isHot: true
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
emit Locked(tokenId);
|
|
233
|
+
emit NodeMinted(to, tokenId, name, image, socialURL);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @notice Get node metadata for a token
|
|
238
|
+
* @param tokenId Token ID to query
|
|
239
|
+
* @return NodeData struct containing name, image, and socialURL
|
|
240
|
+
* @dev Reverts if the token does not exist (NonexistentToken)
|
|
241
|
+
*/
|
|
242
|
+
function nodeData(uint256 tokenId) external view returns (NodeData memory) {
|
|
243
|
+
if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
|
|
244
|
+
return _nodeData[tokenId];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @notice Returns whether a node is marked as hot or cold
|
|
249
|
+
* @param tokenId Token ID to query
|
|
250
|
+
* @return isHot True if the node is hot, false if cold
|
|
251
|
+
* @dev Reverts if the token does not exist (NonexistentToken)
|
|
252
|
+
*/
|
|
253
|
+
function isHotNode(uint256 tokenId) external view returns (bool isHot) {
|
|
254
|
+
if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
|
|
255
|
+
return _nodeData[tokenId].isHot;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @notice Get token ID for a given owner address
|
|
260
|
+
* @param owner The address to query
|
|
261
|
+
* @return tokenId The ID of the token owned by the address, or 0 if none
|
|
262
|
+
* @dev Iterates over token IDs. Since mints are sequential and users only own 1, this is a linear scan.
|
|
263
|
+
* In a production environment with millions of NFTs an off-chain indexer is preferred,
|
|
264
|
+
* but for this scale and testnet use-case, this convenience function works.
|
|
265
|
+
*/
|
|
266
|
+
function tokenOfOwner(address owner) external view returns (uint256) {
|
|
267
|
+
if (owner == address(0)) revert InvalidRecipient();
|
|
268
|
+
if (balanceOf(owner) == 0) return 0;
|
|
269
|
+
|
|
270
|
+
// Since the user only has 1 NFT due to the mint restriction, we can find it
|
|
271
|
+
for (uint256 i = 1; i <= nextTokenId; ++i) {
|
|
272
|
+
if (_ownerOf(i) == owner) {
|
|
273
|
+
return i;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return 0; // Should never reach here if balanceOf > 0, but fallback
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* @notice Update the image URI for a token
|
|
281
|
+
* @param tokenId Token ID to update
|
|
282
|
+
* @param newImageURI New image URI (ipfs:// or https://)
|
|
283
|
+
* @dev Token owner or contract owner can call this function
|
|
284
|
+
* @dev Reverts if:
|
|
285
|
+
* - Token does not exist (NonexistentToken)
|
|
286
|
+
* - Caller is not authorized (NotAuthorized)
|
|
287
|
+
* @dev Emits ImageURIUpdated event
|
|
288
|
+
*/
|
|
289
|
+
function setImageURI(
|
|
290
|
+
uint256 tokenId,
|
|
291
|
+
string calldata newImageURI
|
|
292
|
+
) external {
|
|
293
|
+
address tokenOwner = _ownerOf(tokenId);
|
|
294
|
+
if (tokenOwner == address(0)) revert NonexistentToken();
|
|
295
|
+
if (msg.sender != tokenOwner && msg.sender != owner())
|
|
296
|
+
revert NotAuthorized();
|
|
297
|
+
|
|
298
|
+
_nodeData[tokenId].image = newImageURI;
|
|
299
|
+
emit ImageURIUpdated(tokenId, newImageURI);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* @notice Update the social URL for a token
|
|
304
|
+
* @param tokenId Token ID to update
|
|
305
|
+
* @param newSocialURL New social URL (<=150 bytes)
|
|
306
|
+
* @dev Token owner or contract owner can call this function
|
|
307
|
+
* @dev Reverts if:
|
|
308
|
+
* - Token does not exist (NonexistentToken)
|
|
309
|
+
* - newSocialURL exceeds MAX_TEXT_BYTES (SocialURLTooLong)
|
|
310
|
+
* - Caller is not authorized (NotAuthorized)
|
|
311
|
+
* @dev Emits SocialURLUpdated event
|
|
312
|
+
*/
|
|
313
|
+
function setSocialURL(
|
|
314
|
+
uint256 tokenId,
|
|
315
|
+
string calldata newSocialURL
|
|
316
|
+
) external {
|
|
317
|
+
address tokenOwner = _ownerOf(tokenId);
|
|
318
|
+
if (tokenOwner == address(0)) revert NonexistentToken();
|
|
319
|
+
if (msg.sender != tokenOwner && msg.sender != owner())
|
|
320
|
+
revert NotAuthorized();
|
|
321
|
+
if (bytes(newSocialURL).length > MAX_TEXT_BYTES)
|
|
322
|
+
revert SocialURLTooLong();
|
|
323
|
+
|
|
324
|
+
_nodeData[tokenId].socialURL = newSocialURL;
|
|
325
|
+
emit SocialURLUpdated(tokenId, newSocialURL);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* @notice Update the node name for a token
|
|
330
|
+
* @param tokenId Token ID to update
|
|
331
|
+
* @param newNodeName New node name (required, <=150 bytes)
|
|
332
|
+
* @dev Token owner or contract owner can call this function
|
|
333
|
+
* @dev Reverts if:
|
|
334
|
+
* - Token does not exist (NonexistentToken)
|
|
335
|
+
* - newNodeName is empty (NodeNameRequired)
|
|
336
|
+
* - newNodeName exceeds MAX_TEXT_BYTES (NodeNameTooLong)
|
|
337
|
+
* - Caller is not authorized (NotAuthorized)
|
|
338
|
+
* @dev Emits NodeNameUpdated event
|
|
339
|
+
*/
|
|
340
|
+
function setNodeName(
|
|
341
|
+
uint256 tokenId,
|
|
342
|
+
string calldata newNodeName
|
|
343
|
+
) external {
|
|
344
|
+
address tokenOwner = _ownerOf(tokenId);
|
|
345
|
+
if (tokenOwner == address(0)) revert NonexistentToken();
|
|
346
|
+
if (msg.sender != tokenOwner && msg.sender != owner())
|
|
347
|
+
revert NotAuthorized();
|
|
348
|
+
if (bytes(newNodeName).length == 0) revert NodeNameRequired();
|
|
349
|
+
if (bytes(newNodeName).length > MAX_TEXT_BYTES)
|
|
350
|
+
revert NodeNameTooLong();
|
|
351
|
+
|
|
352
|
+
_nodeData[tokenId].name = newNodeName;
|
|
353
|
+
emit NodeNameUpdated(tokenId, newNodeName);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* @notice Update the hot/cold status for a node
|
|
358
|
+
* @param tokenId Token ID to update
|
|
359
|
+
* @param isHot True to mark the node as hot, false to mark as cold
|
|
360
|
+
* @dev Contract owner can call this function
|
|
361
|
+
* @dev Reverts if:
|
|
362
|
+
* - Token does not exist (NonexistentToken)
|
|
363
|
+
* - Caller is not authorized (NotAuthorized)
|
|
364
|
+
* @dev Emits NodeHotStatusUpdated event
|
|
365
|
+
*/
|
|
366
|
+
function setNodeHotStatus(uint256 tokenId, bool isHot) external {
|
|
367
|
+
address tokenOwner = _ownerOf(tokenId);
|
|
368
|
+
if (tokenOwner == address(0)) revert NonexistentToken();
|
|
369
|
+
if (msg.sender != owner()) revert NotAuthorized();
|
|
370
|
+
|
|
371
|
+
_nodeData[tokenId].isHot = isHot;
|
|
372
|
+
emit NodeHotStatusUpdated(tokenId, isHot);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/// -----------------------------------------------------------------------
|
|
376
|
+
/// Soulbound restrictions (disable transfers & approvals)
|
|
377
|
+
/// -----------------------------------------------------------------------
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* @notice Approve an address to transfer a token (disabled for soulbound NFTs)
|
|
381
|
+
* @dev Always reverts with SoulboundOperation error since tokens cannot be transferred
|
|
382
|
+
* @dev Parameters match ERC721 interface but are unused
|
|
383
|
+
*/
|
|
384
|
+
function approve(
|
|
385
|
+
address /* operator */,
|
|
386
|
+
uint256 /* tokenId */
|
|
387
|
+
) public pure override {
|
|
388
|
+
revert SoulboundOperation();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* @notice Approve an operator for all tokens (disabled for soulbound NFTs)
|
|
393
|
+
* @dev Always reverts with SoulboundOperation error since tokens cannot be transferred
|
|
394
|
+
* @dev Parameters match ERC721 interface but are unused
|
|
395
|
+
*/
|
|
396
|
+
function setApprovalForAll(
|
|
397
|
+
address /* operator */,
|
|
398
|
+
bool /* approved */
|
|
399
|
+
) public pure override {
|
|
400
|
+
revert SoulboundOperation();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* @notice Transfer a token (disabled for soulbound NFTs)
|
|
405
|
+
* @dev Always reverts with SoulboundOperation error since tokens are soulbound
|
|
406
|
+
* @dev Parameters match ERC721 interface but are unused
|
|
407
|
+
*/
|
|
408
|
+
function transferFrom(
|
|
409
|
+
address /* from */,
|
|
410
|
+
address /* to */,
|
|
411
|
+
uint256 /* tokenId */
|
|
412
|
+
) public pure override {
|
|
413
|
+
revert SoulboundOperation();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/// -----------------------------------------------------------------------
|
|
417
|
+
/// Burning
|
|
418
|
+
/// -----------------------------------------------------------------------
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* @notice Burn a token, permanently removing it from circulation
|
|
422
|
+
* @param tokenId Token ID to burn
|
|
423
|
+
* @dev Callable by token owner or contract owner
|
|
424
|
+
* @dev Reverts if:
|
|
425
|
+
* - Caller is not the token owner and not the contract owner (NotAuthorized)
|
|
426
|
+
* - Token does not exist
|
|
427
|
+
* @dev Deletes the associated node data after burning
|
|
428
|
+
*/
|
|
429
|
+
function burn(uint256 tokenId) external {
|
|
430
|
+
address tokenOwner = ownerOf(tokenId);
|
|
431
|
+
if (msg.sender != tokenOwner && msg.sender != owner())
|
|
432
|
+
revert NotAuthorized();
|
|
433
|
+
|
|
434
|
+
_burn(tokenId);
|
|
435
|
+
delete _nodeData[tokenId];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/// -----------------------------------------------------------------------
|
|
439
|
+
/// Metadata (on-chain JSON)
|
|
440
|
+
/// -----------------------------------------------------------------------
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @notice Return token metadata as base64-encoded JSON
|
|
444
|
+
* @param tokenId Token ID to query
|
|
445
|
+
* @return A base64-encoded JSON data URI containing the token metadata
|
|
446
|
+
* @dev Returns on-chain JSON metadata as a data URI (data:application/json;base64,...)
|
|
447
|
+
* @dev Includes token name, description, attributes (node name, social URL), and optional image
|
|
448
|
+
* @dev Reverts if the token does not exist (NonexistentToken)
|
|
449
|
+
*/
|
|
450
|
+
function tokenURI(
|
|
451
|
+
uint256 tokenId
|
|
452
|
+
) public view override returns (string memory) {
|
|
453
|
+
if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
|
|
454
|
+
|
|
455
|
+
NodeData memory d = _nodeData[tokenId];
|
|
456
|
+
|
|
457
|
+
string memory attributes = string.concat(
|
|
458
|
+
'[{"trait_type":"Node name","value":"',
|
|
459
|
+
_escapeJSON(d.name),
|
|
460
|
+
'"}',
|
|
461
|
+
',{"trait_type":"Social URL","value":"',
|
|
462
|
+
_escapeJSON(d.socialURL),
|
|
463
|
+
'"}]'
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
string memory imagePart = bytes(d.image).length == 0
|
|
467
|
+
? ""
|
|
468
|
+
: string.concat(',"image":"', _escapeJSON(d.image), '"');
|
|
469
|
+
|
|
470
|
+
string memory json = string.concat(
|
|
471
|
+
'{"name":"Node #',
|
|
472
|
+
tokenId.toString(),
|
|
473
|
+
'","description":"Soulbound Node NFT",',
|
|
474
|
+
'"attributes":',
|
|
475
|
+
attributes,
|
|
476
|
+
imagePart,
|
|
477
|
+
"}"
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
return
|
|
481
|
+
string.concat(
|
|
482
|
+
"data:application/json;base64,",
|
|
483
|
+
Base64.encode(bytes(json))
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/// -----------------------------------------------------------------------
|
|
488
|
+
/// Internal helpers
|
|
489
|
+
/// -----------------------------------------------------------------------
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* @notice Escape special JSON characters in a string
|
|
493
|
+
* @param s The string to escape
|
|
494
|
+
* @return The escaped string with backslashes added before quotes and backslashes
|
|
495
|
+
* @dev Used internally to safely embed strings in JSON metadata
|
|
496
|
+
* @dev Escapes double quotes (") and backslashes (\) by prefixing them with a backslash
|
|
497
|
+
*/
|
|
498
|
+
function _escapeJSON(
|
|
499
|
+
string memory s
|
|
500
|
+
) internal pure returns (string memory) {
|
|
501
|
+
bytes memory b = bytes(s);
|
|
502
|
+
bytes memory out = new bytes(b.length * 2);
|
|
503
|
+
uint256 j;
|
|
504
|
+
|
|
505
|
+
for (uint256 i = 0; i < b.length; i++) {
|
|
506
|
+
bytes1 c = b[i];
|
|
507
|
+
if (c == bytes1('"') || c == bytes1("\\")) {
|
|
508
|
+
out[j++] = bytes1("\\");
|
|
509
|
+
out[j++] = c;
|
|
510
|
+
} else {
|
|
511
|
+
out[j++] = c;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
bytes memory trimmed = new bytes(j);
|
|
516
|
+
for (uint256 k = 0; k < j; k++) trimmed[k] = out[k];
|
|
517
|
+
return string(trimmed);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import "./IStdReference.sol";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @title CotiPriceConsumer
|
|
8
|
+
* @notice Retrieves token/USD prices from the Band Protocol oracle.
|
|
9
|
+
* @dev All prices returned by Band Protocol are scaled by 1e18.
|
|
10
|
+
* For example, a rate of 50000000000000000 means $0.05.
|
|
11
|
+
*/
|
|
12
|
+
contract CotiPriceConsumer {
|
|
13
|
+
/// @notice Band Protocol StdReferenceProxy on COTI .
|
|
14
|
+
IStdReference public immutable ref;
|
|
15
|
+
|
|
16
|
+
/// @notice Maximum acceptable age (in seconds) for oracle data before it is considered stale.
|
|
17
|
+
uint256 public maxStaleness;
|
|
18
|
+
|
|
19
|
+
/// @notice Emitted when the staleness threshold is updated.
|
|
20
|
+
event MaxStalenessUpdated(uint256 oldValue, uint256 newValue);
|
|
21
|
+
|
|
22
|
+
/// @notice Thrown when the oracle data is older than the allowed staleness window.
|
|
23
|
+
error StaleOracleData(uint256 lastUpdated, uint256 threshold);
|
|
24
|
+
|
|
25
|
+
address public owner;
|
|
26
|
+
|
|
27
|
+
/// @notice Minimum allowed staleness threshold (1 hour).
|
|
28
|
+
uint256 public constant MIN_STALENESS = 1 hours;
|
|
29
|
+
|
|
30
|
+
/// @notice Thrown when the staleness value is below the minimum.
|
|
31
|
+
error StalenessTooLow(uint256 provided, uint256 minimum);
|
|
32
|
+
|
|
33
|
+
modifier onlyOwner() {
|
|
34
|
+
require(msg.sender == owner, "CotiPriceConsumer: caller is not the owner");
|
|
35
|
+
_;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param _ref Address of the Band Protocol StdReferenceProxy contract.
|
|
40
|
+
* @param _maxStaleness Maximum acceptable data age in seconds (0 = no staleness check).
|
|
41
|
+
*/
|
|
42
|
+
constructor(address _ref, uint256 _maxStaleness) {
|
|
43
|
+
require(_ref != address(0), "CotiPriceConsumer: zero ref address");
|
|
44
|
+
if (_maxStaleness < MIN_STALENESS) revert StalenessTooLow(_maxStaleness, MIN_STALENESS);
|
|
45
|
+
ref = IStdReference(_ref);
|
|
46
|
+
maxStaleness = _maxStaleness;
|
|
47
|
+
owner = msg.sender;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// @notice Returns the rate, last update timestamp, and current block timestamp for any base/USD pair.
|
|
51
|
+
/// @return rate The price scaled by 1e18
|
|
52
|
+
/// @return lastUpdated Block timestamp when the oracle data was last updated
|
|
53
|
+
/// @return blockTimestamp The current block.timestamp
|
|
54
|
+
function getPriceWithMeta(string calldata _base) external view returns (uint256 rate, uint256 lastUpdated, uint256 blockTimestamp) {
|
|
55
|
+
IStdReference.ReferenceData memory data = _getPrice(_base);
|
|
56
|
+
rate = data.rate;
|
|
57
|
+
lastUpdated = data.lastUpdatedBase;
|
|
58
|
+
blockTimestamp = block.timestamp;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
63
|
+
// Internal helper
|
|
64
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @dev Queries the Band oracle for `_base`/USD and optionally enforces staleness.
|
|
68
|
+
*/
|
|
69
|
+
function _getPrice(string memory _base) internal view returns (IStdReference.ReferenceData memory data) {
|
|
70
|
+
data = ref.getReferenceData(_base, "USD");
|
|
71
|
+
|
|
72
|
+
uint256 threshold = block.timestamp - maxStaleness;
|
|
73
|
+
if (data.lastUpdatedBase < threshold) {
|
|
74
|
+
revert StaleOracleData(data.lastUpdatedBase, threshold);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
80
|
+
// Generic getter — query any symbol the oracle supports
|
|
81
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
/// @notice Returns the rate for an arbitrary base/USD pair scaled by 1e18.
|
|
84
|
+
function getPrice(string calldata _base) external view returns (uint256) {
|
|
85
|
+
return _getPrice(_base).rate;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
/// @notice Returns the full ReferenceData for an arbitrary base/USD pair.
|
|
90
|
+
function getPriceData(string calldata _base) external view returns (IStdReference.ReferenceData memory) {
|
|
91
|
+
return _getPrice(_base);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @notice Updates the maximum staleness threshold.
|
|
96
|
+
* @param _maxStaleness New threshold in seconds (0 = disable check).
|
|
97
|
+
*/
|
|
98
|
+
function setMaxStaleness(uint256 _maxStaleness) external onlyOwner {
|
|
99
|
+
if (_maxStaleness < MIN_STALENESS) revert StalenessTooLow(_maxStaleness, MIN_STALENESS);
|
|
100
|
+
emit MaxStalenessUpdated(maxStaleness, _maxStaleness);
|
|
101
|
+
maxStaleness = _maxStaleness;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.19;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title ICotiPriceConsumer
|
|
6
|
+
* @notice Minimal interface for the CotiPriceConsumer oracle used by the bridge
|
|
7
|
+
*/
|
|
8
|
+
interface ICotiPriceConsumer {
|
|
9
|
+
|
|
10
|
+
/// @notice Returns the rate for an arbitrary base/USD pair scaled by 1e18.
|
|
11
|
+
function getPrice(string calldata _base) external view returns (uint256);
|
|
12
|
+
|
|
13
|
+
/// @notice Returns rate + metadata for any base/USD pair.
|
|
14
|
+
function getPriceWithMeta(string calldata _base) external view returns (uint256 rate, uint256 lastUpdated, uint256 blockTimestamp);
|
|
15
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @title IStdReference
|
|
6
|
+
* @notice Band Protocol Standard Reference interface for querying price data.
|
|
7
|
+
*/
|
|
8
|
+
interface IStdReference {
|
|
9
|
+
struct ReferenceData {
|
|
10
|
+
uint256 rate; // base/quote exchange rate, scaled by 1e18
|
|
11
|
+
uint256 lastUpdatedBase; // UNIX epoch when the base price was last updated
|
|
12
|
+
uint256 lastUpdatedQuote; // UNIX epoch when the quote price was last updated
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/// @notice Returns the price data for a single base/quote pair.
|
|
16
|
+
function getReferenceData(
|
|
17
|
+
string memory _base,
|
|
18
|
+
string memory _quote
|
|
19
|
+
) external view returns (ReferenceData memory);
|
|
20
|
+
|
|
21
|
+
/// @notice Returns the price data for multiple base/quote pairs.
|
|
22
|
+
function getReferenceDataBulk(
|
|
23
|
+
string[] memory _bases,
|
|
24
|
+
string[] memory _quotes
|
|
25
|
+
) external view returns (ReferenceData[] memory);
|
|
26
|
+
}
|