├── base64_nft ├── .gitignore ├── src │ ├── nft_render.cairo │ ├── nft.cairo │ ├── lib.cairo │ ├── test │ │ └── test.cairo │ ├── nft │ │ └── nft.cairo │ └── common.cairo ├── Scarb.toml └── Scarb.lock ├── marketplace ├── src │ ├── ERC721_flex.cairo │ ├── contract_deployer.cairo │ ├── signature_checker.cairo │ ├── interfaces │ │ └── nft_transfer_manager.cairo │ ├── HighestBidderAuctionSale.md │ ├── mocks │ │ ├── erc1155.cairo │ │ ├── strategy.cairo │ │ ├── account.cairo │ │ └── erc721.cairo │ ├── lib.cairo │ ├── proxy.cairo │ ├── utils │ │ └── order_types.cairo │ ├── transfer_manager_ERC721.cairo │ ├── transfer_manager_ERC1155.cairo │ ├── execution_manager.cairo │ └── strategy_standard_sale_for_fixed_price.cairo ├── .tool-versions ├── .snfoundry_cache │ └── .prev_tests_failed ├── scripts │ ├── .gitignore │ ├── .env.example │ ├── tsconfig.json │ └── package.json ├── tests │ └── lib.cairo ├── Scarb.toml ├── Scarb.lock └── Sell_any_item_at_fixed_price.md ├── flex_haus ├── .tool-versions ├── src │ ├── lib.cairo │ └── interface │ │ ├── IFlexHausCollectible.cairo │ │ └── IFlexHausFactory.cairo ├── Scarb.toml └── Scarb.lock ├── .tool-versions ├── experimental ├── fractional │ ├── src │ │ ├── mocks.cairo │ │ ├── lib.cairo │ │ ├── interfaces.cairo │ │ ├── interfaces │ │ │ ├── ierc20.cairo │ │ │ ├── ifractional_nft.cairo │ │ │ └── ierc721.cairo │ │ └── mocks │ │ │ └── flex_nft.cairo │ ├── .gitignore │ ├── .tool-versions │ ├── Scarb.toml │ ├── tests │ │ └── test_contract.cairo │ ├── README.md │ └── Scarb.lock ├── erc_6806_holding_time_tracking │ ├── src │ │ └── lib.cairo │ ├── .gitignore │ ├── Scarb.lock │ ├── snfoundry.toml │ ├── tests │ │ └── test_contract.cairo │ ├── Scarb.toml │ └── README.md ├── erc_4907_rental_nft │ ├── .gitignore │ ├── tests │ │ ├── lib.cairo │ │ ├── utils.cairo │ │ └── test_contract.cairo │ ├── src │ │ ├── lib.cairo │ │ ├── erc4907 │ │ │ └── interface.cairo │ │ └── presets │ │ │ └── erc4907_rental_nft.cairo │ ├── README.md │ ├── Scarb.toml │ └── Scarb.lock ├── erc_5006_rental_nft │ ├── .gitignore │ ├── src │ │ ├── lib.cairo │ │ ├── types.cairo │ │ ├── interface.cairo │ │ ├── uintset.cairo │ │ └── preset.cairo │ ├── Scarb.toml │ ├── snfoundry.toml │ ├── tests │ │ └── test_contract.cairo │ └── Scarb.lock ├── erc_7662_ai_agent_nft │ ├── .gitignore │ ├── .tool-versions │ ├── src │ │ ├── lib.cairo │ │ ├── types.cairo │ │ └── interfaces.cairo │ ├── Scarb.toml │ ├── README.md │ └── Scarb.lock ├── erc_5173_future_rewards │ ├── .gitignore │ ├── .tool-versions │ ├── src │ │ ├── lib.cairo │ │ └── interfaces │ │ │ ├── ierc5173.cairo │ │ │ ├── ierc20.cairo │ │ │ └── ierc721.cairo │ ├── Scarb.toml │ ├── Scarb.lock │ └── test │ │ └── erc5173.test.cairo ├── erc_1523_insurance_policies │ ├── .gitignore │ ├── src │ │ ├── lib.cairo │ │ ├── types.cairo │ │ └── interfaces.cairo │ ├── Scarb.toml │ ├── Scarb.lock │ ├── tests │ │ └── test_erc1523.cairo │ └── README.md ├── erc_5643_subscription_nft │ ├── .tool-versions │ ├── tests │ │ ├── lib.cairo │ │ ├── utils.cairo │ │ └── erc5643.cairo │ ├── .gitignore │ ├── src │ │ ├── lib.cairo │ │ ├── erc5643 │ │ │ └── interface.cairo │ │ └── presets │ │ │ └── erc5643_subscription_nft.cairo │ ├── Scarb.toml │ ├── solidity │ │ ├── src │ │ │ ├── IERC5643.sol │ │ │ └── ERC5643.sol │ │ └── test │ │ │ └── ERC5643.t.sol │ └── README.md ├── erc_7765_rwa_integration │ ├── .tool-versions │ ├── src │ │ ├── lib.cairo │ │ ├── scripts │ │ │ └── calculate_interface_id.py │ │ └── interfaces │ │ │ └── IERC7765.cairo │ ├── README.md │ ├── Scarb.toml │ └── Scarb.lock ├── erc_6105_no_intermediary_nft_trading_protocol │ ├── .gitignore │ ├── .tool-versions │ ├── tests │ │ ├── lib.cairo │ │ └── utils.cairo │ ├── src │ │ ├── lib.cairo │ │ ├── errors.cairo │ │ └── types.cairo │ ├── Scarb.toml │ └── Scarb.lock ├── erc_5585_nft_authorization │ ├── .gitignore │ ├── src │ │ ├── lib.cairo │ │ ├── types.cairo │ │ ├── errors.cairo │ │ └── interface.cairo │ ├── Scarb.lock │ └── Scarb.toml └── erc_7683_cross_chain_intents │ ├── src │ ├── lib.cairo │ ├── interfaces │ │ └── nft_settlement.cairo │ └── cross_chain_types.cairo │ ├── Scarb.lock │ └── Scarb.toml ├── stakingpool ├── tests │ └── lib.cairo ├── src │ ├── lib.cairo │ └── interfaces │ │ └── IFlexStakingPool.cairo ├── Scarb.toml ├── Scarb.lock └── README.md ├── assets ├── logo.png ├── marketplace-buy.png ├── marketplace-listing.png ├── marketplace-make-offer.png ├── marketplace-overview.png └── marketplace-accept-offer.png ├── .gitignore ├── openedition ├── src │ ├── interfaces │ │ ├── IFlexDropContractMetadata.cairo │ │ ├── ICurrencyManager.cairo │ │ ├── IFlexDrop.cairo │ │ ├── INonFungibleFlexDropToken.cairo │ │ └── ISignatureChecker2.cairo │ ├── utils │ │ └── openedition.cairo │ └── lib.cairo ├── Scarb.toml └── Scarb.lock └── README.md /base64_nft/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /marketplace/src/ERC721_flex.cairo: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /flex_haus/.tool-versions: -------------------------------------------------------------------------------- 1 | scarb 2.8.4 2 | -------------------------------------------------------------------------------- /marketplace/.tool-versions: -------------------------------------------------------------------------------- 1 | scarb 2.6.3 2 | -------------------------------------------------------------------------------- /marketplace/.snfoundry_cache/.prev_tests_failed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /marketplace/src/contract_deployer.cairo: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /marketplace/scripts/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | starknet-foundry 0.27.0 2 | scarb 2.8.2 3 | -------------------------------------------------------------------------------- /base64_nft/src/nft_render.cairo: -------------------------------------------------------------------------------- 1 | pub mod NftRender; 2 | -------------------------------------------------------------------------------- /experimental/fractional/src/mocks.cairo: -------------------------------------------------------------------------------- 1 | pub mod flex_nft; -------------------------------------------------------------------------------- /marketplace/tests/lib.cairo: -------------------------------------------------------------------------------- 1 | mod test_strategy_yolo; 2 | -------------------------------------------------------------------------------- /stakingpool/tests/lib.cairo: -------------------------------------------------------------------------------- 1 | mod test_flex_staking_pool; -------------------------------------------------------------------------------- /base64_nft/src/nft.cairo: -------------------------------------------------------------------------------- 1 | pub mod nft; 2 | pub mod erc721; 3 | -------------------------------------------------------------------------------- /experimental/erc_6806_holding_time_tracking/src/lib.cairo: -------------------------------------------------------------------------------- 1 | mod erc721; -------------------------------------------------------------------------------- /experimental/fractional/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/fractional/.tool-versions: -------------------------------------------------------------------------------- 1 | scarb 2.8.2 2 | starknet-foundry 0.27.0 3 | -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/erc_6806_holding_time_tracking/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/.tool-versions: -------------------------------------------------------------------------------- 1 | starknet-foundry 0.27.0 2 | scarb 2.8.2 -------------------------------------------------------------------------------- /marketplace/scripts/.env.example: -------------------------------------------------------------------------------- 1 | PROVIDER_URL= 2 | ACCOUNT_PRIVATE= 3 | ACCOUNT_PUBLIC= -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/.tool-versions: -------------------------------------------------------------------------------- 1 | scarb 2.8.5 2 | starknet-foundry 0.33.0 3 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/.tool-versions: -------------------------------------------------------------------------------- 1 | scarb 2.8.4 2 | starknet-foundry 0.31.0 3 | -------------------------------------------------------------------------------- /experimental/erc_7765_rwa_integration/.tool-versions: -------------------------------------------------------------------------------- 1 | starknet-foundry 0.27.0 2 | scarb 2.6.3 3 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | -------------------------------------------------------------------------------- /experimental/fractional/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod fractional_nft; 2 | pub mod interfaces; 3 | pub mod mocks; -------------------------------------------------------------------------------- /experimental/erc_5585_nft_authorization/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .snfoundry_cache/ 3 | .snfoundry_cache/ 4 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/HEAD/assets/logo.png -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/.tool-versions: -------------------------------------------------------------------------------- 1 | starknet-foundry 0.32.0 2 | scarb 2.8.4 -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod erc7662; 2 | pub mod interfaces; 3 | pub mod types; 4 | -------------------------------------------------------------------------------- /experimental/fractional/src/interfaces.cairo: -------------------------------------------------------------------------------- 1 | pub mod ierc20; 2 | pub mod ierc721; 3 | pub mod ifractional_nft; -------------------------------------------------------------------------------- /stakingpool/src/lib.cairo: -------------------------------------------------------------------------------- 1 | mod interfaces { 2 | mod IFlexStakingPool; 3 | } 4 | 5 | mod FlexStakingPool; 6 | -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod erc1523; 2 | pub mod interfaces; 3 | pub mod types; 4 | -------------------------------------------------------------------------------- /experimental/erc_5585_nft_authorization/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod interface; 2 | pub mod types; 3 | pub mod errors; 4 | pub mod erc5585; -------------------------------------------------------------------------------- /experimental/erc_7765_rwa_integration/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod interfaces { 2 | pub mod IERC7765; 3 | } 4 | 5 | mod ERC7765; 6 | -------------------------------------------------------------------------------- /assets/marketplace-buy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/HEAD/assets/marketplace-buy.png -------------------------------------------------------------------------------- /base64_nft/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod common; 2 | pub mod nft_render; 3 | pub mod nft; 4 | 5 | pub mod test { 6 | pub mod test; 7 | } 8 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/tests/lib.cairo: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | #[feature("safe_dispatcher")] 3 | mod test_contract; 4 | mod utils; 5 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/src/lib.cairo: -------------------------------------------------------------------------------- 1 | mod uintset; 2 | mod interface; 3 | mod types; 4 | mod erc5006; 5 | pub mod preset; 6 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/tests/lib.cairo: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | #[feature("safe_dispatcher")] 3 | mod erc5643; 4 | mod utils; 5 | -------------------------------------------------------------------------------- /assets/marketplace-listing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/HEAD/assets/marketplace-listing.png -------------------------------------------------------------------------------- /assets/marketplace-make-offer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/HEAD/assets/marketplace-make-offer.png -------------------------------------------------------------------------------- /assets/marketplace-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/HEAD/assets/marketplace-overview.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */target/ 2 | .vscode/ 3 | */scripts/node_modules/ 4 | deployment-script/ 5 | .snfoundry_cache 6 | flex_haus/.snfoundry_cache 7 | .DS_Store -------------------------------------------------------------------------------- /assets/marketplace-accept-offer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/HEAD/assets/marketplace-accept-offer.png -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Starknet 4 | target 5 | Scarb.lock 6 | 7 | # Starknet foundry 8 | .snfoundry_cache 9 | -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/src/lib.cairo: -------------------------------------------------------------------------------- 1 | mod interfaces { 2 | mod ierc20; 3 | mod ierc721; 4 | mod ierc5173; 5 | } 6 | 7 | mod erc5173; 8 | -------------------------------------------------------------------------------- /marketplace/scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/@tsconfig/node20/tsconfig.json", 3 | "include": ["scripts/**/*"], 4 | "files": [] 5 | } -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod erc4907 { 2 | pub mod erc4907; 3 | pub mod interface; 4 | } 5 | 6 | pub mod presets { 7 | pub mod erc4907_rental_nft; 8 | } 9 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod erc5643 { 2 | pub mod erc5643; 3 | pub mod interface; 4 | } 5 | 6 | pub mod presets { 7 | pub mod erc5643_subscription_nft; 8 | } 9 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/tests/lib.cairo: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | #[feature("safe_dispatcher")] 3 | mod utils; 4 | mod test_erc6105; 5 | mod test_collection_offer; 6 | // mod test_item_offer; 7 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/src/lib.cairo: -------------------------------------------------------------------------------- 1 | pub mod interface; 2 | pub mod types; 3 | pub mod errors; 4 | pub mod erc6105; 5 | pub mod collection_offer; 6 | pub mod item_offer; 7 | pub mod preset; 8 | -------------------------------------------------------------------------------- /flex_haus/src/lib.cairo: -------------------------------------------------------------------------------- 1 | mod interface { 2 | mod IFlexHausCollectible; 3 | mod IFlexHausFactory; 4 | } 5 | 6 | mod collectible { 7 | mod FlexHausCollectible; 8 | } 9 | 10 | mod erc721 { 11 | mod ERC721; 12 | } 13 | 14 | mod factory { 15 | mod FlexHausFactory; 16 | } 17 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/src/types.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[derive(Drop, starknet::Store, Serde, Clone, PartialEq)] 4 | pub struct UserRecord { 5 | pub token_id: u256, 6 | pub owner: ContractAddress, 7 | pub amount: u64, 8 | pub user: ContractAddress, 9 | pub expiry: u64 10 | } 11 | -------------------------------------------------------------------------------- /marketplace/scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@tsconfig/node20": "^20.1.2", 4 | "@types/node": "^22.4.2", 5 | "dotenv": "^16.4.5", 6 | "fs": "^0.0.1-security", 7 | "node": "^22.7.0", 8 | "starknet": "^6.11.0", 9 | "ts-node": "^10.9.1", 10 | "typescript": "^5.2.2" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /base64_nft/src/test/test.cairo: -------------------------------------------------------------------------------- 1 | use base64_nft::common::{base64_encode, byte_arr_to_arr_u8}; 2 | 3 | #[test] 4 | fn test_base64_encode() { 5 | let mut i: u256 = 0; 6 | let mut count: u256 = 0; 7 | while i < 3_000_00 { 8 | count += 1; 9 | i += 1; 10 | }; 11 | println!("base64: {}", count); 12 | } 13 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/README.md: -------------------------------------------------------------------------------- 1 | ### About 2 | 3 | A cairo implementation of [EIP-4907](https://github.com/ethereum/ercs/blob/master/ERCS/erc-4907.md). It is an ethereum standard for Rental NFTs. 4 | 5 | ### Project Setup 6 | 7 | ### Compile 8 | 9 | ```bash 10 | scarb build 11 | ``` 12 | 13 | ### Test 14 | 15 | ```bash 16 | scarb test 17 | ``` -------------------------------------------------------------------------------- /experimental/erc_7683_cross_chain_intents/src/lib.cairo: -------------------------------------------------------------------------------- 1 | mod erc721; 2 | mod cross_chain_types; 3 | 4 | mod interfaces { 5 | mod nft_settlement; 6 | } 7 | 8 | mod contracts { 9 | mod nft_settlement; 10 | } 11 | 12 | use cross_chain_types::{CrossChainNFTOrder, ResolvedCrossChainNFTOrder, NFTInput, NFTOutput}; 13 | use interfaces::nft_settlement::INFTSettlement; 14 | -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/src/types.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Drop, starknet::Store, Serde, Clone, PartialEq)] 2 | pub struct Agent { 3 | pub name: ByteArray, 4 | pub description: ByteArray, 5 | pub model: ByteArray, 6 | pub user_prompt_uri: ByteArray, 7 | pub system_prompt_uri: ByteArray, 8 | pub image_uri: ByteArray, 9 | pub category: ByteArray, 10 | pub prompts_encrypted: bool, 11 | } 12 | -------------------------------------------------------------------------------- /experimental/erc_5585_nft_authorization/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc_5585_nft_authorization" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "snforge_std", 9 | ] 10 | 11 | [[package]] 12 | name = "snforge_std" 13 | version = "0.27.0" 14 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" 15 | -------------------------------------------------------------------------------- /openedition/src/interfaces/IFlexDropContractMetadata.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | trait IFlexDropContractMetadata { 5 | fn set_base_uri(ref self: TContractState, new_token_uri: ByteArray); 6 | fn set_contract_uri(ref self: TContractState, new_contract_uri: ByteArray); 7 | fn get_base_uri(self: @TContractState) -> ByteArray; 8 | fn get_contract_uri(self: @TContractState) -> ByteArray; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /experimental/erc_5585_nft_authorization/src/types.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | // use core::array::ArrayTrait; 3 | 4 | #[derive(Drop, Serde, starknet::Store, Clone, PartialEq)] 5 | pub struct UserRecord { 6 | pub user: ContractAddress, 7 | pub expires: u64 8 | } 9 | 10 | #[derive(Drop, Serde, starknet::Store, Clone, PartialEq)] 11 | pub struct NFTDetails { 12 | pub owner: ContractAddress, 13 | pub approved: ContractAddress, 14 | pub token_uri: felt252 15 | } 16 | -------------------------------------------------------------------------------- /experimental/erc_7765_rwa_integration/README.md: -------------------------------------------------------------------------------- 1 | ## Experimental ERC-7765 (RWA) Integration 2 | 3 | A test implementation of the (ERC-7765)[https://github.com/Mint-Blockchain/ERCs/blob/master/ERCS/erc-7765.md] for RWA integration into NFTs. Essentially, this extends ERC721 meaning the token should be compatible with ERC-721, as well as extending the functionality for the specific RWA use case. 4 | 5 | The additional functionality consists of a set of preset privileges that can be exercised by the token holder. 6 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc5006_cairo" 3 | version = "0.1.0" 4 | edition = "2024_07" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.2" 10 | openzeppelin_introspection = "0.17.0" 11 | openzeppelin_token = "0.17.0" 12 | 13 | [dev-dependencies] 14 | assert_macros = "2.8.2" 15 | 16 | [[target.starknet-contract]] 17 | sierra = true 18 | 19 | [scripts] 20 | test = "snforge test" -------------------------------------------------------------------------------- /marketplace/src/signature_checker.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | use marketplace::utils::order_types::MakerOrder; 4 | 5 | #[starknet::interface] 6 | trait ISignatureChecker { 7 | fn initializer(ref self: TState, proxy_admin: ContractAddress); 8 | fn compute_maker_order_hash(self: @TState, hash_domain: felt252, order: MakerOrder) -> felt252; 9 | fn verify_maker_order_signature( 10 | self: @TState, hash_domain: felt252, order: MakerOrder, order_signature: Span 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /experimental/erc_5585_nft_authorization/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_5585_nft_authorization" 3 | version = "0.1.0" 4 | edition = "2023_11" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.2" 10 | 11 | [dev-dependencies] 12 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.27.0" } 13 | 14 | [[target.starknet-contract]] 15 | sierra = true 16 | 17 | [scripts] 18 | test = "snforge test" 19 | -------------------------------------------------------------------------------- /flex_haus/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "flexhaus" 3 | version = "0.1.0" 4 | edition = "2023_01" 5 | 6 | [dependencies] 7 | starknet = "2.8.2" 8 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.17.0" } 9 | 10 | [dev-dependencies] 11 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.32.0" } 12 | assert_macros = "2.8.2" 13 | 14 | [scripts] 15 | test = "snforge test" 16 | 17 | [[target.starknet-contract]] 18 | allowed-libfuncs-list.name = "audited" 19 | sierra = true 20 | casm = true 21 | -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_5173_future_rewards" 3 | version = "0.1.0" 4 | edition = "2024_07" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.5" 10 | 11 | [dev-dependencies] 12 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.33.0" } 13 | cairo_test = "2.8.5" 14 | 15 | 16 | [[target.starknet-contract]] 17 | allowed-libfuncs-list.name = "audited" 18 | sierra = true 19 | casm = true -------------------------------------------------------------------------------- /base64_nft/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "base64_nft" 3 | version = "0.1.0" 4 | edition = "2024_07" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [scripts] 9 | test = "snforge test" 10 | 11 | [dependencies] 12 | starknet = ">=2.9.4" 13 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v1.0.0" } 14 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.35.0" } 15 | 16 | [[target.starknet-contract]] 17 | sierra = true 18 | casm = true -------------------------------------------------------------------------------- /experimental/fractional/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fractional" 3 | version = "0.1.0" 4 | edition = "2023_11" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.2" 10 | openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.17.0" } 11 | 12 | [dev-dependencies] 13 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.27.0" } 14 | 15 | [[target.starknet-contract]] 16 | sierra = true 17 | 18 | [scripts] 19 | test = "snforge test" 20 | -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/src/types.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[derive(Drop, starknet::Store, Serde, Clone, PartialEq)] 4 | pub struct Policy { 5 | pub policy_holder: ContractAddress, 6 | pub premium: u256, 7 | pub coverage_period_start: u256, 8 | pub coverage_period_end: u256, 9 | pub risk: ByteArray, 10 | pub underwriter: ContractAddress, 11 | pub metadataURI: ByteArray, 12 | pub state: State, 13 | } 14 | 15 | #[derive(Drop, Copy, starknet::Store, Serde, PartialEq)] 16 | pub enum State { 17 | Active, 18 | Expired, 19 | Claimed, 20 | } 21 | -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/src/interfaces/ierc5173.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC5173 { 5 | fn mint(ref self: TContractState, to: ContractAddress, token_id: felt252); 6 | fn transfer(ref self: TContractState, to: ContractAddress, token_id: felt252 ); 7 | fn distribute_rewards(ref self: TContractState, reward_amount: felt252, token_id: felt252); 8 | fn get_token_owner(self: @TContractState, token_id: felt252) -> ContractAddress; 9 | fn get_reward_balance(self: @TContractState, address: ContractAddress) -> felt252; 10 | } -------------------------------------------------------------------------------- /openedition/src/interfaces/ICurrencyManager.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | trait ICurrencyManager { 5 | fn initializer(ref self: TState, owner: ContractAddress, proxy_admin: ContractAddress); 6 | fn add_currency(ref self: TState, currency: ContractAddress); 7 | fn remove_currency(ref self: TState, currency: ContractAddress); 8 | fn is_currency_whitelisted(self: @TState, currency: ContractAddress) -> bool; 9 | fn whitelisted_currency_count(self: @TState) -> usize; 10 | fn whitelisted_currency(self: @TState, index: usize) -> ContractAddress; 11 | } -------------------------------------------------------------------------------- /openedition/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "openedition" 3 | version = "0.1.0" 4 | edition = "2023_01" 5 | 6 | [dependencies] 7 | starknet = "2.6.3" 8 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.14.0" } 9 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.10.0" } 10 | alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.3.0-rc0" } 11 | 12 | [scripts] 13 | test = "snforge test" 14 | 15 | [[target.starknet-contract]] 16 | allowed-libfuncs-list.name = "audited" 17 | sierra = true 18 | casm = true -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_1523_insurance_policies" 3 | version = "0.1.0" 4 | edition = "2023_11" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.2" 10 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag="v0.16.0" } 11 | 12 | [dev-dependencies] 13 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.27.0" } 14 | 15 | [[target.starknet-contract]] 16 | sierra = true 17 | 18 | [scripts] 19 | test = "snforge test" 20 | -------------------------------------------------------------------------------- /experimental/erc_7683_cross_chain_intents/src/interfaces/nft_settlement.cairo: -------------------------------------------------------------------------------- 1 | #[starknet::interface] 2 | trait INFTSettlement { 3 | fn initiate( 4 | ref self: TContractState, 5 | order: CrossChainNFTOrder, 6 | signature: Array, 7 | filler_data: Array 8 | ); 9 | 10 | fn resolve( 11 | self: @TContractState, order: CrossChainNFTOrder, filler_data: Array 12 | ) -> ResolvedCrossChainNFTOrder; 13 | 14 | fn fulfill( 15 | ref self: TContractState, order: CrossChainNFTOrder, origin_chain_proof: Array 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /experimental/erc_7683_cross_chain_intents/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "alexandria_storage" 6 | version = "0.3.0" 7 | source = "git+https://github.com/keep-starknet-strange/alexandria.git#95d98a5182001d07673b856a356eff0e6bd05354" 8 | 9 | [[package]] 10 | name = "flex_cross_chain_intents" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "alexandria_storage", 14 | "snforge_std", 15 | ] 16 | 17 | [[package]] 18 | name = "snforge_std" 19 | version = "0.1.0" 20 | source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.10.1#2f1597fb724b7df3050468bd0e6a8a3a0e225001" 21 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_4907_rental_nft" 3 | version = "0.1.0" 4 | edition = "2024_07" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.4" 10 | openzeppelin_access = "0.20.0" 11 | openzeppelin_introspection = "0.20.0" 12 | openzeppelin_token = "0.20.0" 13 | 14 | [dev-dependencies] 15 | assert_macros = "2.8.4" 16 | openzeppelin_utils = "0.20.0" 17 | openzeppelin_testing = "0.20.0" 18 | snforge_std = "0.34.0" 19 | 20 | [lib] 21 | 22 | [[target.starknet-contract]] 23 | 24 | [scripts] 25 | test = "snforge test" 26 | 27 | -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc_5173_future_rewards" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "snforge_std", 9 | ] 10 | 11 | [[package]] 12 | name = "snforge_scarb_plugin" 13 | version = "0.33.0" 14 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.33.0#221b1dbff42d650e9855afd4283508da8f8cacba" 15 | 16 | [[package]] 17 | name = "snforge_std" 18 | version = "0.33.0" 19 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.33.0#221b1dbff42d650e9855afd4283508da8f8cacba" 20 | dependencies = [ 21 | "snforge_scarb_plugin", 22 | ] 23 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_6105_no_intermediary_nft_trading_protocol" 3 | version = "0.1.0" 4 | edition = "2023_11" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.2" 10 | openzeppelin_introspection = "0.17.0" 11 | openzeppelin_token = "0.17.0" 12 | 13 | [dev-dependencies] 14 | assert_macros = "2.8.2" 15 | openzeppelin_utils = "0.17.0" 16 | openzeppelin_testing = "0.17.0" 17 | snforge_std = '0.30.0' 18 | 19 | [[target.starknet-contract]] 20 | sierra = true 21 | 22 | [scripts] 23 | test = "snforge test" -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_7662_ai_agent_nft" 3 | version = "0.1.0" 4 | edition = "2024_07" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.2" 10 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag="v0.17.0" } 11 | 12 | [dev-dependencies] 13 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.27.0" } 14 | 15 | [[target.starknet-contract]] 16 | allowed-libfuncs-list.name = "audited" 17 | sierra = true 18 | casm = true 19 | 20 | [scripts] 21 | test = "snforge test" 22 | -------------------------------------------------------------------------------- /experimental/erc_7683_cross_chain_intents/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "flex_cross_chain_intents" 3 | version = "0.1.0" 4 | description = "POC implementing NFT cross-chain intents based on the ERC-7683 standard" 5 | homepage = "https://github.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract" 6 | 7 | [dependencies] 8 | starknet = "2.6.3" 9 | alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria.git" } 10 | 11 | [[target.starknet-contract]] 12 | sierra = true 13 | casm = true 14 | 15 | [dev-dependencies] 16 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.10.1" } 17 | 18 | [scripts] 19 | test = "snforge test" -------------------------------------------------------------------------------- /marketplace/src/interfaces/nft_transfer_manager.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | trait ITransferManagerNFT { 5 | fn initializer(ref self: TState, marketplace: ContractAddress, owner: ContractAddress,); 6 | fn transfer_non_fungible_token( 7 | ref self: TState, 8 | collection: ContractAddress, 9 | from: ContractAddress, 10 | to: ContractAddress, 11 | token_id: u256, 12 | amount: u128, 13 | data: Span, 14 | ); 15 | fn update_marketplace(ref self: TState, new_address: ContractAddress); 16 | fn get_marketplace(self: @TState) -> ContractAddress; 17 | } 18 | -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/src/interfaces.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | use erc_1523_insurance_policies::types::{Policy, State}; 4 | 5 | #[starknet::interface] 6 | pub trait IERC1523 { 7 | fn create_policy(ref self: TState, policy: Policy) -> u256; 8 | fn update_policy_state(ref self: TState, token_id: u256, state: State); 9 | fn transfer_policy(ref self: TState, token_id: u256, to: ContractAddress); 10 | fn get_policy(self: @TState, token_id: u256) -> Policy; 11 | fn get_all_user_policies(self: @TState, user: ContractAddress) -> Array; 12 | fn get_user_policy_amount(self: @TState, user: ContractAddress) -> u64; 13 | } 14 | -------------------------------------------------------------------------------- /experimental/erc_6806_holding_time_tracking/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc_6806_holding_time_tracking" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "snforge_std", 9 | ] 10 | 11 | [[package]] 12 | name = "snforge_scarb_plugin" 13 | version = "0.33.0" 14 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.33.0#221b1dbff42d650e9855afd4283508da8f8cacba" 15 | 16 | [[package]] 17 | name = "snforge_std" 18 | version = "0.33.0" 19 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.33.0#221b1dbff42d650e9855afd4283508da8f8cacba" 20 | dependencies = [ 21 | "snforge_scarb_plugin", 22 | ] 23 | -------------------------------------------------------------------------------- /marketplace/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "marketplace" 3 | version = "0.1.0" 4 | edition = "2023_01" 5 | 6 | [dependencies] 7 | starknet = "2.6.3" 8 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.26.0" } 9 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.10.0" } 10 | alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.3.0-rc0" } 11 | pragma_lib = { git = "https://github.com/astraly-labs/pragma-lib", rev = "fe9a467" } 12 | [scripts] 13 | test = "snforge test" 14 | 15 | [[target.starknet-contract]] 16 | allowed-libfuncs-list.name = "audited" 17 | sierra = true 18 | casm = true 19 | -------------------------------------------------------------------------------- /experimental/fractional/src/interfaces/ierc20.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC20 { 5 | fn total_supply(self: @TContractState) -> u256; 6 | fn balance_of(self: @TContractState, account: ContractAddress) -> u256; 7 | fn allowance(self: @TContractState, owner: ContractAddress, spender: ContractAddress) -> u256; 8 | fn transfer(ref self: TContractState, recipient: ContractAddress, amount: u256) -> bool; 9 | fn transfer_from( 10 | ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256 11 | ) -> bool; 12 | fn approve(ref self: TContractState, spender: ContractAddress, amount: u256) -> bool; 13 | } -------------------------------------------------------------------------------- /stakingpool/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stakingpool" 3 | version = "0.1.0" 4 | edition = "2023_01" 5 | 6 | [dependencies] 7 | starknet = "2.6.3" 8 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.22.0" } 9 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.10.0" } 10 | alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.3.0-rc0" } 11 | 12 | [scripts] 13 | test = "snforge test" 14 | 15 | [[target.starknet-contract]] 16 | build-external-contracts = ["openzeppelin::presets::account::Account", "openzeppelin::presets::erc721::ERC721"] 17 | allowed-libfuncs-list.name = "audited" 18 | sierra = true 19 | casm = true -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/src/interfaces/ierc20.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC20 { 5 | fn total_supply(self: @TContractState) -> felt252; 6 | fn balance_of(self: @TContractState, account: ContractAddress) -> felt252; 7 | fn allowance(self: @TContractState, owner: ContractAddress, spender: ContractAddress) -> felt252; 8 | fn transfer(ref self: TContractState, recipient: ContractAddress, amount: felt252) -> bool; 9 | fn transfer_from( 10 | ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, amount: felt252 11 | ) -> bool; 12 | fn approve(ref self: TContractState, spender: ContractAddress, amount: felt252) -> bool; 13 | } -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/src/interface.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use erc5006_cairo::types::UserRecord; 3 | 4 | #[starknet::interface] 5 | pub trait IERC5006 { 6 | fn usable_balance_of(self: @TState, account: ContractAddress, token_id: u256) -> u256; 7 | 8 | fn frozen_balance_of(self: @TState, account: ContractAddress, token_id: u256) -> u256; 9 | 10 | fn user_record_of(self: @TState, record_id: u256) -> UserRecord; 11 | 12 | fn create_user_record( 13 | ref self: TState, 14 | owner: ContractAddress, 15 | user: ContractAddress, 16 | token_id: u256, 17 | amount: u64, 18 | expiry: u64 19 | ) -> u256; 20 | 21 | fn delete_user_record(ref self: TState, record_id: u256); 22 | } 23 | -------------------------------------------------------------------------------- /experimental/erc_7765_rwa_integration/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_7765_rwa_integration" 3 | version = "0.1.0" 4 | edition = "2024_07" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.6.3" 10 | openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.17.0" } 11 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.14.0" } 12 | alexandria_storage = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.3.0-rc0" } 13 | 14 | 15 | [scripts] 16 | test = "snforge test" 17 | 18 | 19 | [[target.starknet-contract]] 20 | allowed-libfuncs-list.name = "audited" 21 | sierra = true 22 | casm = true -------------------------------------------------------------------------------- /marketplace/src/HighestBidderAuctionSale.md: -------------------------------------------------------------------------------- 1 | # This is an explainer doc for the Highest Bidder Auction Sale Strategy 2 | 3 | The contract makes possible an auction where the highest valid bid during the period of auction will be the winning bid. 4 | 5 | ## Addition 6 | 7 | ### Validate Highest Bid 8 | 9 | The logic here is to check if the new/incoming bid (`taker_bid` or `maker_bid`) is the highest bid, by comparing the prices, in both the `can_execute_taker_ask` and `can_execute_taker_bid`. 10 | 11 | #### Bid Acceptance 12 | 13 | If the bid is higher than the current highest bid i.e the valid bid, the auction will proceed with that bid. 14 | 15 | #### Winning Bid Amount 16 | 17 | The value that is returned here is either the `taker_bid.price` or `maker_bid.price` which in this case includes the winning bid price. 18 | -------------------------------------------------------------------------------- /openedition/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "alexandria_storage" 6 | version = "0.2.0" 7 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.3.0-rc0#ae1d5149ff601a7ac5b39edc867d33ebd83d7f4f" 8 | 9 | [[package]] 10 | name = "openedition" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "alexandria_storage", 14 | "openzeppelin", 15 | "snforge_std", 16 | ] 17 | 18 | [[package]] 19 | name = "openzeppelin" 20 | version = "0.10.0" 21 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.10.0#d77082732daab2690ba50742ea41080eb23299d3" 22 | 23 | [[package]] 24 | name = "snforge_std" 25 | version = "0.14.0" 26 | source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.14.0#e8cbecee4e31ed428c76d5173eaa90c8df796fe3" 27 | -------------------------------------------------------------------------------- /stakingpool/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "alexandria_storage" 6 | version = "0.2.0" 7 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.3.0-rc0#ae1d5149ff601a7ac5b39edc867d33ebd83d7f4f" 8 | 9 | [[package]] 10 | name = "openzeppelin" 11 | version = "0.10.0" 12 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.10.0#d77082732daab2690ba50742ea41080eb23299d3" 13 | 14 | [[package]] 15 | name = "snforge_std" 16 | version = "0.22.0" 17 | source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.22.0#9b215944c6c5871c738381b4ded61bbf06e7ba35" 18 | 19 | [[package]] 20 | name = "stakingpool" 21 | version = "0.1.0" 22 | dependencies = [ 23 | "alexandria_storage", 24 | "openzeppelin", 25 | "snforge_std", 26 | ] 27 | -------------------------------------------------------------------------------- /experimental/fractional/src/interfaces/ifractional_nft.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IFractionalNFT { 5 | fn initialized(ref self: TContractState, nft_collection: ContractAddress, accepted_purchase_token: ContractAddress, token_id: u256, amount: u256); 6 | fn put_for_sell(ref self: TContractState, price: u256); 7 | fn purchase(ref self: TContractState, amount: u256); 8 | fn redeem(ref self: TContractState, amount: u256); 9 | 10 | fn nft_collection(self: @TContractState) -> ContractAddress; 11 | fn token_id(self: @TContractState) -> u256; 12 | fn is_initialized(self: @TContractState) -> bool; 13 | fn for_sale(self: @TContractState) -> bool; 14 | fn redeemable(self: @TContractState) -> bool; 15 | fn sale_price(self: @TContractState) -> u256; 16 | } -------------------------------------------------------------------------------- /experimental/erc_5585_nft_authorization/src/errors.cairo: -------------------------------------------------------------------------------- 1 | pub mod Errors { 2 | pub const INVALID_TOKEN_ID: felt252 = 'Invalid token ID'; 3 | pub const UNAUTHORIZED: felt252 = 'Not authorized'; 4 | pub const ALREADY_MINTED: felt252 = 'Already minted'; 5 | pub const WRONG_OWNER: felt252 = 'Wrong owner'; 6 | pub const INVALID_APPROVAL: felt252 = 'Invalid approval'; 7 | pub const INVALID_OPERATOR: felt252 = 'Invalid operator'; 8 | pub const ZERO_ADDRESS: felt252 = 'Zero address'; 9 | 10 | // Authorization specific errors 11 | pub const INVALID_RIGHTS: felt252 = 'Invalid rights'; 12 | pub const EXPIRED_AUTH: felt252 = 'Auth expired'; 13 | pub const INVALID_USER: felt252 = 'Invalid user'; 14 | pub const USER_LIMIT: felt252 = 'User limit exceeded'; 15 | pub const RESET_DISABLED: felt252 = 'Reset disabled'; 16 | } 17 | -------------------------------------------------------------------------------- /experimental/erc_6806_holding_time_tracking/snfoundry.toml: -------------------------------------------------------------------------------- 1 | # Visit https://foundry-rs.github.io/starknet-foundry/appendix/snfoundry-toml.html for more information 2 | 3 | # [sncast.myprofile1] # Define a profile name 4 | # url = "http://127.0.0.1:5050/" # Url of the RPC provider 5 | # accounts_file = "../account-file" # Path to the file with the account data 6 | # account = "mainuser" # Account from `accounts_file` or default account file that will be used for the transactions 7 | # keystore = "~/keystore" # Path to the keystore file 8 | # wait_params = { timeout = 500, retry_interval = 10 } # Wait for submitted transaction parameters 9 | # block_explorer = "StarkScan" # Block explorer service used to display links to transaction details 10 | -------------------------------------------------------------------------------- /marketplace/src/mocks/erc1155.cairo: -------------------------------------------------------------------------------- 1 | const IERC1155_ID: felt252 = 0x6114a8f75559e1b39fcba08ce02961a1aa082d9256a158dd3e64964e4b1b52; 2 | 3 | #[starknet::interface] 4 | trait IERC1155 { 5 | fn safe_transfer_from( 6 | ref self: TContractState, 7 | from: starknet::ContractAddress, 8 | to: starknet::ContractAddress, 9 | id: u256, 10 | amount: u128, 11 | data: Span 12 | ); 13 | } 14 | 15 | #[starknet::contract] 16 | mod ERC1155 { 17 | #[storage] 18 | struct Storage {} 19 | 20 | #[abi(embed_v0)] 21 | impl ERC1155Impl of super::IERC1155 { 22 | fn safe_transfer_from( 23 | ref self: ContractState, 24 | from: starknet::ContractAddress, 25 | to: starknet::ContractAddress, 26 | id: u256, 27 | amount: u128, 28 | data: Span 29 | ) {} 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /openedition/src/utils/openedition.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use array::Array; 3 | 4 | #[derive(Drop, Copy, Serde, starknet::Store)] 5 | struct PhaseDrop { 6 | mint_price: u256, 7 | currency: ContractAddress, 8 | start_time: u64, 9 | end_time: u64, 10 | max_mint_per_wallet: u64, 11 | phase_type: u8 // 1 for public sale, 2 for private sale... 12 | } 13 | 14 | #[derive(Drop, Copy, Serde)] 15 | struct WhiteListParam { 16 | phase_id: u64, 17 | nft_address: ContractAddress, 18 | minter: ContractAddress, 19 | mint_price: u256, 20 | } 21 | 22 | #[derive(Drop, Serde)] 23 | struct MultiConfigureStruct { 24 | base_uri: ByteArray, 25 | contract_uri: ByteArray, 26 | flex_drop: ContractAddress, 27 | phase_drop: PhaseDrop, 28 | new_phase: bool, 29 | creator_payout_address: ContractAddress, 30 | fee_recipient: ContractAddress, 31 | allowed_payers: Array::, 32 | disallowed_payers: Array::, 33 | } 34 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/src/errors.cairo: -------------------------------------------------------------------------------- 1 | pub mod Errors { 2 | pub const INVALID_PRICE: felt252 = 'ERC6105: invalid sale price'; 3 | pub const INVALID_AMOUNT: felt252 = 'ERC6105: invalid amount'; 4 | pub const INSUFFICIENT_BALANCE: felt252 = 'ERC6105: insufficient balance'; 5 | pub const INVALID_TOKEN: felt252 = 'ERC6105: invalid token'; 6 | pub const SALE_PRICE_ZERO: felt252 = 'ERC6105: price MUST NOT be 0'; 7 | pub const INVALID_EXPIRES: felt252 = 'ERC6105: invalid expires'; 8 | pub const NOT_OWNER_OR_APPROVED: felt252 = 'ERC6105: not owner nor approved'; 9 | pub const INVALID_LISTING: felt252 = 'ERC6105: invalid listing'; 10 | pub const INCONSISTENT_PRICE: felt252 = 'ERC6105: inconsistent price'; 11 | pub const INCONSISTENT_TOKENS: felt252 = 'ERC6105: inconsistent tokens'; 12 | pub const INCORRECT_VALUE: felt252 = 'ERC6105: incorrect value'; 13 | pub const INSUFFICIENT_ALLOWANCE: felt252 = 'ERC6105: insufficient allowance'; 14 | } 15 | -------------------------------------------------------------------------------- /experimental/fractional/src/interfaces/ierc721.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC721 { 5 | fn balance_of(self: @TContractState, account: ContractAddress) -> u256; 6 | fn owner_of(self: @TContractState, token_id: u256) -> ContractAddress; 7 | fn safe_transfer_from( 8 | ref self: TContractState, 9 | from: ContractAddress, 10 | to: ContractAddress, 11 | token_id: u256, 12 | data: Span 13 | ); 14 | fn transfer_from(ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256); 15 | fn approve(ref self: TContractState, to: ContractAddress, token_id: u256); 16 | fn set_approval_for_all(ref self: TContractState, operator: ContractAddress, approved: bool); 17 | fn get_approved(self: @TContractState, token_id: u256) -> ContractAddress; 18 | fn is_approved_for_all( 19 | self: @TContractState, owner: ContractAddress, operator: ContractAddress 20 | ) -> bool; 21 | } -------------------------------------------------------------------------------- /marketplace/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "alexandria_storage" 6 | version = "0.2.0" 7 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.3.0-rc0#ae1d5149ff601a7ac5b39edc867d33ebd83d7f4f" 8 | 9 | [[package]] 10 | name = "marketplace" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "alexandria_storage", 14 | "openzeppelin", 15 | "pragma_lib", 16 | "snforge_std", 17 | ] 18 | 19 | [[package]] 20 | name = "openzeppelin" 21 | version = "0.10.0" 22 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.10.0#d77082732daab2690ba50742ea41080eb23299d3" 23 | 24 | [[package]] 25 | name = "pragma_lib" 26 | version = "1.0.0" 27 | source = "git+https://github.com/astraly-labs/pragma-lib?rev=fe9a467#fe9a46743254182ac331da488ccfc05e0185cdd0" 28 | 29 | [[package]] 30 | name = "snforge_std" 31 | version = "0.26.0" 32 | source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.26.0#50eb589db65e113efe4f09241feb59b574228c7e" 33 | -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/src/interfaces.cairo: -------------------------------------------------------------------------------- 1 | use starknet::{ContractAddress}; 2 | use erc_7662_ai_agent_nft::types::Agent; 3 | 4 | #[starknet::interface] 5 | pub trait IERC7662 { 6 | fn mint_agent( 7 | ref self: TState, 8 | to: ContractAddress, 9 | name: ByteArray, 10 | description: ByteArray, 11 | model: ByteArray, 12 | user_prompt_uri: ByteArray, 13 | system_prompt_uri: ByteArray, 14 | image_uri: ByteArray, 15 | category: ByteArray 16 | ) -> u256; 17 | fn add_encrypted_prompts( 18 | ref self: TState, 19 | token_id: u256, 20 | encrypted_user_prompt_uri: ByteArray, 21 | encrypted_system_prompt_uri: ByteArray 22 | ); 23 | fn get_collection_ids(self: @TState, address: ContractAddress) -> Array; 24 | fn get_agent(self: @TState, token_id: u256) -> Agent; 25 | fn get_agent_data( 26 | self: @TState, token_id: u256 27 | ) -> (ByteArray, ByteArray, ByteArray, ByteArray, ByteArray, bool); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/src/interfaces/ierc721.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC721 { 5 | fn balance_of(self: @TContractState, account: ContractAddress) -> felt252; 6 | fn owner_of(self: @TContractState, token_id: felt252) -> ContractAddress; 7 | fn safe_transfer_from( 8 | ref self: TContractState, 9 | from: ContractAddress, 10 | to: ContractAddress, 11 | token_id: felt252, 12 | data: Span 13 | ); 14 | fn transfer_from(ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: felt252); 15 | fn approve(ref self: TContractState, to: ContractAddress, token_id: felt252); 16 | fn set_approval_for_all(ref self: TContractState, operator: ContractAddress, approved: bool); 17 | fn get_approved(self: @TContractState, token_id: felt252) -> ContractAddress; 18 | fn is_approved_for_all( 19 | self: @TContractState, owner: ContractAddress, operator: ContractAddress 20 | ) -> bool; 21 | } -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_5643_subscription_nft" 3 | readme = "README.md" 4 | version = "0.1.0" 5 | edition = "2024_07" 6 | cairo-version = "2.8.4" 7 | scarb-version = "2.8.4" 8 | authors = ["Flex Marketplace"] 9 | description = "Subscription NFTs (ERC-5643) written in Cairo for Starknet." 10 | documentation = "https://github.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/tree/main/experimental/erc_5643_subscription_nft" 11 | repository = "https://github.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract" 12 | license-file = "LICENSE" 13 | keywords = [ 14 | "erc5643", 15 | "subscription", 16 | ] 17 | 18 | [dependencies] 19 | starknet = "2.8.4" 20 | openzeppelin_access = "0.18.0" 21 | openzeppelin_introspection = "0.18.0" 22 | openzeppelin_token = "0.18.0" 23 | 24 | [dev-dependencies] 25 | assert_macros = "2.8.4" 26 | openzeppelin_utils = "0.18.0" 27 | openzeppelin_testing = "0.18.0" 28 | snforge_std = "0.31.0" 29 | 30 | [lib] 31 | 32 | [[target.starknet-contract]] 33 | 34 | [scripts] 35 | test = "snforge test" 36 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/snfoundry.toml: -------------------------------------------------------------------------------- 1 | # Visit https://foundry-rs.github.io/starknet-foundry/appendix/snfoundry-toml.html 2 | # and https://foundry-rs.github.io/starknet-foundry/projects/configuration.html for more information 3 | 4 | # [sncast.default] # Define a profile name 5 | # url = "https://free-rpc.nethermind.io/sepolia-juno/v0_7" # Url of the RPC provider 6 | # accounts-file = "../account-file" # Path to the file with the account data 7 | # account = "mainuser" # Account from `accounts_file` or default account file that will be used for the transactions 8 | # keystore = "~/keystore" # Path to the keystore file 9 | # wait-params = { timeout = 300, retry-interval = 10 } # Wait for submitted transaction parameters 10 | # block-explorer = "StarkScan" # Block explorer service used to display links to transaction details 11 | # show-explorer-links = true # Print links pointing to pages with transaction details in the chosen block explorer 12 | -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/README.md: -------------------------------------------------------------------------------- 1 | ## Experimental ERC-7662 AI Agent NFTs 2 | 3 | A test implementation of the [ERC-7662](https://github.com/ethereum/ERCs/blob/ea6b5c5fb9bc3ab0f6183c84ab81c54b9b57e7ab/ERCS/erc-7662.md) to create AI Agent NFTs. 4 | The AI Agents NFT standard introduces additional features and data to the standard ERC-721 protocol, aimed at addressing the practical requirements of using NFTs to store, trade and use AI Agents. It is designed to be fully backward-compatible with the original ERC-721 standard. 5 | 6 | ### Key aspects 7 | 8 | - Agent struct to store agent-related data 9 | - Mapping between NFT Token ID and its Agent information in the smart-contract storage 10 | - `mint_agent` function to mint a new Agent NFT 11 | - `add_encrypted_prompts` function to add encrypted prompts to an Agent NFT (only callable by the owner) 12 | - `get_agent` function to retrieve Agent data by token ID 13 | - `get_collection_ids` function to retrieve all token IDs owned by an address 14 | - `get_agent_data` function to retrieve all Agent NFT data required by the ERC-7662 standard 15 | - Integration with OpenZeppelin's Ownable component to manage ownership 16 | 17 | 18 | -------------------------------------------------------------------------------- /openedition/src/interfaces/IFlexDrop.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use openedition::utils::openedition::{PhaseDrop, WhiteListParam}; 3 | 4 | #[starknet::interface] 5 | trait IFlexDrop { 6 | fn mint_public( 7 | ref self: TContractState, 8 | nft_address: ContractAddress, 9 | phase_id: u64, 10 | fee_recipient: ContractAddress, 11 | minter_if_not_payer: ContractAddress, 12 | quantity: u64, 13 | is_warpcast: bool, 14 | ); 15 | fn whitelist_mint( 16 | ref self: TContractState, 17 | whitelist_data: WhiteListParam, 18 | fee_recipient: ContractAddress, 19 | proof: Array 20 | ); 21 | fn start_new_phase_drop( 22 | ref self: TContractState, 23 | phase_drop_id: u64, 24 | phase_drop: PhaseDrop, 25 | fee_recipient: ContractAddress, 26 | ); 27 | fn update_phase_drop(ref self: TContractState, phase_drop_id: u64, phase_drop: PhaseDrop); 28 | fn update_creator_payout_address(ref self: TContractState, new_payout_address: ContractAddress); 29 | fn update_payer(ref self: TContractState, payer: ContractAddress, allowed: bool); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/src/erc4907/interface.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | pub const IERC4907_ID: felt252 = 0xad092b5c; 4 | 5 | #[starknet::interface] 6 | pub trait IERC4907 { 7 | /// @notice set the user and expires of an NFT 8 | /// @dev The zero address indicates there is no user 9 | /// Throws if `tokenId` is not valid NFT 10 | /// @param user The new user of the NFT 11 | /// @param expires UNIX timestamp, The new user could use the NFT before expires 12 | fn setUser(ref self: TState, token_id: u256, user: ContractAddress, expires: u64); 13 | 14 | /// @notice Get the user address of an NFT 15 | /// @dev The zero address indicates that there is no user or the user is expired 16 | /// @param tokenId The NFT to get the user address for 17 | /// @return The user address for this NFT 18 | fn userOf(self: @TState, token_id: u256) -> ContractAddress; 19 | 20 | /// @notice Get the user expires of an NFT 21 | /// @dev The zero value indicates that there is no user 22 | /// @param tokenId The NFT to get the user expires for 23 | /// @return The user expires for this NFT 24 | fn userExpires(self: @TState, token_id: u256) -> u64; 25 | } 26 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/src/erc5643/interface.cairo: -------------------------------------------------------------------------------- 1 | pub const IERC5643_ID: felt252 = 0x8c65f84d; 2 | 3 | #[starknet::interface] 4 | pub trait IERC5643 { 5 | /// @notice Renews the subscription to an NFT 6 | /// Throws if `tokenId` is not a valid NFT 7 | /// @param tokenId The NFT to renew the subscription for 8 | /// @param duration The number of seconds to extend a subscription for 9 | fn renew_subscription(ref self: TState, token_id: u256, duration: u64); 10 | /// @notice Cancels the subscription of an NFT 11 | /// @dev Throws if `tokenId` is not a valid NFT 12 | /// @param tokenId The NFT to cancel the subscription for 13 | fn cancel_subscription(ref self: TState, token_id: u256); 14 | /// @notice Gets the expiration date of a subscription 15 | /// @dev Throws if `tokenId` is not a valid NFT 16 | /// @param tokenId The NFT to get the expiration date of 17 | /// @return The expiration date of the subscription 18 | fn expires_at(self: @TState, token_id: u256) -> u64; 19 | /// @notice Determines whether a subscription can be renewed 20 | /// @dev Throws if `tokenId` is not a valid NFT 21 | /// @param tokenId The NFT to get the expiration date of 22 | /// @return The renewability of a the subscription 23 | fn is_renewable(self: @TState, token_id: u256) -> bool; 24 | } 25 | -------------------------------------------------------------------------------- /openedition/src/lib.cairo: -------------------------------------------------------------------------------- 1 | use core::fmt::{Display, Error, Formatter, Debug}; 2 | use starknet::{contract_address_to_felt252, ContractAddress, contract_address_const}; 3 | 4 | impl DisplayContractAddress of Display { 5 | fn fmt(self: @starknet::ContractAddress, ref f: Formatter) -> Result<(), Error> { 6 | write!(f, "{}", contract_address_to_felt252(*self)) 7 | } 8 | } 9 | 10 | impl DebugContractAddress of Debug { 11 | fn fmt(self: @starknet::ContractAddress, ref f: Formatter) -> Result<(), Error> { 12 | Display::fmt(self, ref f) 13 | } 14 | } 15 | 16 | impl DefaultContractAddress of Default { 17 | fn default() -> ContractAddress { 18 | contract_address_const::<0>() 19 | } 20 | } 21 | 22 | mod erc721 { 23 | mod ERC721; 24 | mod ERC721MultiMetadata; 25 | } 26 | 27 | mod interfaces { 28 | mod IERC721; 29 | mod IFlexDrop; 30 | mod IFlexDropContractMetadata; 31 | mod INonFungibleFlexDropToken; 32 | mod ICurrencyManager; 33 | mod ISignatureChecker2; 34 | } 35 | 36 | mod utils { 37 | mod openedition; 38 | } 39 | 40 | mod ERC721_open_edition_multi_metadata; 41 | 42 | mod ERC721_open_edition; 43 | 44 | mod FlexDrop; 45 | 46 | use erc721::ERC721; 47 | use erc721::ERC721MultiMetadata; 48 | use interfaces::IFlexDrop::IFlexDrop; 49 | use interfaces::INonFungibleFlexDropToken::INonFungibleFlexDropToken; -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/src/uintset.cairo: -------------------------------------------------------------------------------- 1 | pub mod UintSet { 2 | use core::starknet::storage::{ 3 | Map, StoragePath, StorageMapReadAccess, StorageMapWriteAccess, StoragePointerReadAccess, 4 | StoragePointerWriteAccess, Mutable 5 | }; 6 | 7 | #[starknet::storage_node] 8 | pub struct UintSet { 9 | pub indices: Map, 10 | pub indices_len: u32, 11 | pub values: Map, 12 | pub size: u32 13 | } 14 | 15 | #[generate_trait] 16 | pub impl UintSetImpl of UintSetTrait { 17 | fn add(self: StoragePath>, value: u256) { 18 | if (self.indices.read(value) == 0) { 19 | let fresh_index: u32 = self.indices_len.read() + 1; 20 | self.indices.write(value, fresh_index); 21 | self.indices_len.write(fresh_index); 22 | self.values.write(fresh_index, value); 23 | self.size.write(self.size.read() + 1); 24 | } 25 | } 26 | fn remove(self: StoragePath>, value: u256) { 27 | if (self.indices.read(value) != 0) { 28 | self.values.write(self.indices.read(value), 0); 29 | self.indices.write(value, 0); 30 | self.indices_len.write(self.indices_len.read() - 1); 31 | self.size.write(self.size.read() - 1); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/tests/utils.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use openzeppelin_utils::serde::SerializedAppend; 3 | use openzeppelin_testing::constants::{NAME, SYMBOL, BASE_URI, OWNER}; 4 | use erc_6105_no_intermediary_nft_trading_protocol::preset::{ 5 | IERC6105MixinDispatcher, IERC6105MixinDispatcherTrait, IERC6105MixinSafeDispatcher 6 | }; 7 | use openzeppelin_testing::deployment::declare_and_deploy; 8 | 9 | 10 | #[derive(Copy, Drop)] 11 | pub struct ERC6105Test { 12 | pub erc6105_address: ContractAddress, 13 | pub erc6105: IERC6105MixinDispatcher, 14 | pub erc6105_safe: IERC6105MixinSafeDispatcher, 15 | } 16 | 17 | #[generate_trait] 18 | pub impl ERC6105TestImpl of ERC6105TestTrait { 19 | fn setup() -> ERC6105Test { 20 | let mut calldata = array![]; 21 | calldata.append_serde(NAME()); 22 | calldata.append_serde(SYMBOL()); 23 | calldata.append_serde(BASE_URI()); 24 | calldata.append_serde(1); 25 | let erc6105_address = declare_and_deploy( 26 | "ERC6105NoIntermediaryNftTradingProtocol", calldata 27 | ); 28 | let erc6105 = IERC6105MixinDispatcher { contract_address: erc6105_address }; 29 | let erc6105_safe = IERC6105MixinSafeDispatcher { contract_address: erc6105_address }; 30 | erc6105.mint(OWNER(), 69420); 31 | ERC6105Test { erc6105_address, erc6105, erc6105_safe } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /experimental/erc_7683_cross_chain_intents/src/cross_chain_types.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[derive(Copy, Drop, Serde, starknet::Store)] 4 | struct CrossChainNFTOrder { 5 | // Standard ERC-7683 fields 6 | settlement_contract: ContractAddress, 7 | swapper: ContractAddress, 8 | nonce: u256, 9 | origin_chain_id: u32, 10 | initiate_deadline: u32, 11 | fill_deadline: u32, 12 | // NFT-specific fields 13 | nft_contract: ContractAddress, 14 | token_id: u256, 15 | destination_chain_id: u32, 16 | destination_address: ContractAddress, 17 | } 18 | 19 | #[derive(Copy, Drop, Serde)] 20 | struct ResolvedCrossChainNFTOrder { 21 | // Standard ERC-7683 fields 22 | settlement_contract: ContractAddress, 23 | swapper: ContractAddress, 24 | nonce: u256, 25 | origin_chain_id: u32, 26 | initiate_deadline: u32, 27 | fill_deadline: u32, 28 | // Input (NFT being transferred) 29 | swapper_input: NFTInput, 30 | // Output (NFT on destination chain) 31 | swapper_output: NFTOutput, 32 | // Filler rewards (if any) 33 | filler_outputs: Array 34 | } 35 | 36 | #[derive(Copy, Drop, Serde)] 37 | struct NFTInput { 38 | nft_contract: ContractAddress, 39 | token_id: u256, 40 | chain_id: u32 41 | } 42 | 43 | #[derive(Copy, Drop, Serde)] 44 | struct NFTOutput { 45 | nft_contract: ContractAddress, 46 | token_id: u256, 47 | recipient: ContractAddress, 48 | chain_id: u32 49 | } 50 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/src/types.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | /// @dev A structure representing a listed token 4 | /// The zero `salePrice` indicates that the token is not for sale 5 | /// The zero `expires` indicates that the token is not for sale 6 | /// @param salePrice - the price the token is being sold for 7 | /// @param expires - UNIX timestamp, the buyer could buy the token before expires 8 | /// @param supportedToken - contract addresses of supported ERC20 token or zero address 9 | /// The zero address indicates that the supported token is ETH 10 | /// Buyer needs to purchase item with supported token 11 | /// @param historicalPrice - The price at which the seller last bought this token 12 | #[derive(Drop, starknet::Store, Serde, Clone, PartialEq)] 13 | pub struct Listing { 14 | pub sale_price: u256, 15 | pub expires: u64, 16 | pub supported_token: ContractAddress, 17 | pub historical_price: u256 18 | } 19 | 20 | #[derive(Drop, starknet::Store, Serde, Clone, PartialEq)] 21 | pub struct CollectionOffer { 22 | pub buyer: ContractAddress, 23 | pub amount: u256, 24 | pub sale_price: u256, 25 | pub expires: u64, 26 | pub supported_token: ContractAddress 27 | } 28 | 29 | #[derive(Drop, starknet::Store, Serde, Clone, PartialEq)] 30 | pub struct ItemOffer { 31 | pub token_id: u256, 32 | pub buyer: ContractAddress, 33 | pub sale_price: u256, 34 | pub expires: u64, 35 | pub supported_token: ContractAddress 36 | } 37 | -------------------------------------------------------------------------------- /marketplace/src/lib.cairo: -------------------------------------------------------------------------------- 1 | use core::fmt::{Display, Error, Formatter, Debug}; 2 | use starknet::{contract_address_to_felt252, ContractAddress, contract_address_const}; 3 | 4 | impl DisplayContractAddress of Display { 5 | fn fmt(self: @starknet::ContractAddress, ref f: Formatter) -> Result<(), Error> { 6 | write!(f, "{}", contract_address_to_felt252(*self)) 7 | } 8 | } 9 | 10 | impl DebugContractAddress of Debug { 11 | fn fmt(self: @starknet::ContractAddress, ref f: Formatter) -> Result<(), Error> { 12 | Display::fmt(self, ref f) 13 | } 14 | } 15 | 16 | impl DefaultContractAddress of Default { 17 | fn default() -> ContractAddress { 18 | contract_address_const::<0>() 19 | } 20 | } 21 | 22 | mod utils { 23 | mod order_types; 24 | } 25 | 26 | mod interfaces { 27 | mod nft_transfer_manager; 28 | } 29 | 30 | mod mocks { 31 | mod account; 32 | mod erc20; 33 | mod erc1155; 34 | mod erc721; 35 | mod strategy; 36 | mod randomness; 37 | } 38 | 39 | mod contract_deployer; 40 | mod currency_manager; 41 | mod execution_manager; 42 | mod marketplace; 43 | mod proxy; 44 | mod royalty_fee_manager; 45 | mod royalty_fee_registry; 46 | mod signature_checker; 47 | mod signature_checker2; 48 | mod strategy_any_item_from_collection_for_fixed_price; 49 | mod strategy_highest_bidder_auction_sale; 50 | mod strategy_private_sale; 51 | mod strategy_standard_sale_for_fixed_price; 52 | mod strategy_yolo_buy; 53 | mod transfer_manager_ERC721; 54 | mod transfer_manager_ERC1155; 55 | mod transfer_selector_NFT; 56 | 57 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/solidity/src/IERC5643.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: CC0-1.0 2 | pragma solidity ^0.8.27; 3 | 4 | interface IERC5643 { 5 | /// @notice Emitted when a subscription expiration changes 6 | /// @dev When a subscription is canceled, the expiration value should also be 0. 7 | event SubscriptionUpdate(uint256 indexed tokenId, uint64 expiration); 8 | 9 | /// @notice Renews the subscription to an NFT 10 | /// Throws if `tokenId` is not a valid NFT 11 | /// @param tokenId The NFT to renew the subscription for 12 | /// @param duration The number of seconds to extend a subscription for 13 | function renewSubscription(uint256 tokenId, uint64 duration) external payable; 14 | 15 | /// @notice Cancels the subscription of an NFT 16 | /// @dev Throws if `tokenId` is not a valid NFT 17 | /// @param tokenId The NFT to cancel the subscription for 18 | function cancelSubscription(uint256 tokenId) external payable; 19 | 20 | /// @notice Gets the expiration date of a subscription 21 | /// @dev Throws if `tokenId` is not a valid NFT 22 | /// @param tokenId The NFT to get the expiration date of 23 | /// @return The expiration date of the subscription 24 | function expiresAt(uint256 tokenId) external view returns(uint64); 25 | 26 | /// @notice Determines whether a subscription can be renewed 27 | /// @dev Throws if `tokenId` is not a valid NFT 28 | /// @param tokenId The NFT to get the expiration date of 29 | /// @return The renewability of a the subscription 30 | function isRenewable(uint256 tokenId) external view returns(bool); 31 | } 32 | -------------------------------------------------------------------------------- /experimental/fractional/src/mocks/flex_nft.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | #[starknet::interface] 3 | pub trait IFlexNFT { 4 | fn mint(ref self: TContractState, to: ContractAddress, token_id: u256); 5 | } 6 | 7 | #[starknet::contract] 8 | mod FlexNFT { 9 | use starknet::ContractAddress; 10 | use openzeppelin::introspection::src5::SRC5Component; 11 | use openzeppelin::token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; 12 | 13 | component!(path: ERC721Component, storage: erc721, event: ERC721Event); 14 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 15 | 16 | #[storage] 17 | struct Storage { 18 | #[substorage(v0)] 19 | erc721: ERC721Component::Storage, 20 | #[substorage(v0)] 21 | src5: SRC5Component::Storage, 22 | } 23 | 24 | #[event] 25 | #[derive(Drop, starknet::Event)] 26 | enum Event { 27 | #[flat] 28 | ERC721Event: ERC721Component::Event, 29 | #[flat] 30 | SRC5Event: SRC5Component::Event 31 | } 32 | 33 | #[constructor] 34 | fn constructor(ref self: ContractState, base_uri: ByteArray) { 35 | self.erc721.initializer("Flex NFT", "FNT", base_uri); 36 | } 37 | 38 | #[abi(embed_v0)] 39 | impl ERC721Impl = ERC721Component::ERC721MixinImpl; 40 | 41 | impl ERC721InternalImpl = ERC721Component::InternalImpl; 42 | 43 | #[abi(embed_v0)] 44 | impl Impl of super::IFlexNFT { 45 | fn mint(ref self: ContractState, to: ContractAddress, token_id: u256) { 46 | self.erc721.mint(to, token_id); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/tests/utils.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use openzeppelin_utils::serde::SerializedAppend; 3 | use openzeppelin_testing::constants::{NAME, SYMBOL, BASE_URI, OWNER, TOKEN_ID}; 4 | use openzeppelin_testing::deployment::declare_and_deploy; 5 | use erc_4907_rental_nft::presets::erc4907_rental_nft::{ 6 | IERC4907RentalNftMixinDispatcher, IERC4907RentalNftMixinDispatcherTrait, 7 | IERC4907RentalNftMixinSafeDispatcher, 8 | }; 9 | 10 | #[derive(Copy, Drop)] 11 | pub struct ERC4907Test { 12 | pub erc4907_rental_nft_address: ContractAddress, 13 | pub erc4907_rental_nft: IERC4907RentalNftMixinDispatcher, 14 | pub erc4907_rental_nft_safe: IERC4907RentalNftMixinSafeDispatcher, 15 | } 16 | 17 | #[generate_trait] 18 | pub impl ERC4907TestImpl of ERC4907TestTrait { 19 | fn setup() -> ERC4907Test { 20 | let mut erc4907_rental_nft_calldata = array![]; 21 | erc4907_rental_nft_calldata.append_serde(NAME()); 22 | erc4907_rental_nft_calldata.append_serde(SYMBOL()); 23 | erc4907_rental_nft_calldata.append_serde(BASE_URI()); 24 | let erc4907_rental_nft_address = declare_and_deploy( 25 | "ERC4907RentalNft", erc4907_rental_nft_calldata, 26 | ); 27 | let erc4907_rental_nft = IERC4907RentalNftMixinDispatcher { 28 | contract_address: erc4907_rental_nft_address, 29 | }; 30 | let erc4907_rental_nft_safe = IERC4907RentalNftMixinSafeDispatcher { 31 | contract_address: erc4907_rental_nft_address, 32 | }; 33 | erc4907_rental_nft.mint(OWNER(), TOKEN_ID); 34 | 35 | ERC4907Test { erc4907_rental_nft_address, erc4907_rental_nft, erc4907_rental_nft_safe } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /experimental/fractional/tests/test_contract.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | use snforge_std::{declare, ContractClassTrait}; 4 | 5 | use fractional::IHelloStarknetSafeDispatcher; 6 | use fractional::IHelloStarknetSafeDispatcherTrait; 7 | use fractional::IHelloStarknetDispatcher; 8 | use fractional::IHelloStarknetDispatcherTrait; 9 | 10 | fn deploy_contract(name: ByteArray) -> ContractAddress { 11 | let contract = declare(name).unwrap(); 12 | let (contract_address, _) = contract.deploy(@ArrayTrait::new()).unwrap(); 13 | contract_address 14 | } 15 | 16 | #[test] 17 | fn test_increase_balance() { 18 | let contract_address = deploy_contract("HelloStarknet"); 19 | 20 | let dispatcher = IHelloStarknetDispatcher { contract_address }; 21 | 22 | let balance_before = dispatcher.get_balance(); 23 | assert(balance_before == 0, 'Invalid balance'); 24 | 25 | dispatcher.increase_balance(42); 26 | 27 | let balance_after = dispatcher.get_balance(); 28 | assert(balance_after == 42, 'Invalid balance'); 29 | } 30 | 31 | #[test] 32 | #[feature("safe_dispatcher")] 33 | fn test_cannot_increase_balance_with_zero_value() { 34 | let contract_address = deploy_contract("HelloStarknet"); 35 | 36 | let safe_dispatcher = IHelloStarknetSafeDispatcher { contract_address }; 37 | 38 | let balance_before = safe_dispatcher.get_balance().unwrap(); 39 | assert(balance_before == 0, 'Invalid balance'); 40 | 41 | match safe_dispatcher.increase_balance(0) { 42 | Result::Ok(_) => core::panic_with_felt252('Should have panicked'), 43 | Result::Err(panic_data) => { 44 | assert(*panic_data.at(0) == 'Amount cannot be 0', *panic_data.at(0)); 45 | } 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/tests/test_contract.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | use snforge_std::{declare, ContractClassTrait, DeclareResultTrait}; 4 | 5 | use erc5006_cairo::IHelloStarknetSafeDispatcher; 6 | use erc5006_cairo::IHelloStarknetSafeDispatcherTrait; 7 | use erc5006_cairo::IHelloStarknetDispatcher; 8 | use erc5006_cairo::IHelloStarknetDispatcherTrait; 9 | 10 | fn deploy_contract(name: ByteArray) -> ContractAddress { 11 | let contract = declare(name).unwrap().contract_class(); 12 | let (contract_address, _) = contract.deploy(@ArrayTrait::new()).unwrap(); 13 | contract_address 14 | } 15 | 16 | #[test] 17 | fn test_increase_balance() { 18 | let contract_address = deploy_contract("HelloStarknet"); 19 | 20 | let dispatcher = IHelloStarknetDispatcher { contract_address }; 21 | 22 | let balance_before = dispatcher.get_balance(); 23 | assert(balance_before == 0, 'Invalid balance'); 24 | 25 | dispatcher.increase_balance(42); 26 | 27 | let balance_after = dispatcher.get_balance(); 28 | assert(balance_after == 42, 'Invalid balance'); 29 | } 30 | 31 | #[test] 32 | #[feature("safe_dispatcher")] 33 | fn test_cannot_increase_balance_with_zero_value() { 34 | let contract_address = deploy_contract("HelloStarknet"); 35 | 36 | let safe_dispatcher = IHelloStarknetSafeDispatcher { contract_address }; 37 | 38 | let balance_before = safe_dispatcher.get_balance().unwrap(); 39 | assert(balance_before == 0, 'Invalid balance'); 40 | 41 | match safe_dispatcher.increase_balance(0) { 42 | Result::Ok(_) => core::panic_with_felt252('Should have panicked'), 43 | Result::Err(panic_data) => { 44 | assert(*panic_data.at(0) == 'Amount cannot be 0', *panic_data.at(0)); 45 | } 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /stakingpool/src/interfaces/IFlexStakingPool.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[derive(Copy, Drop, Serde, Hash, PartialEq, starknet::Store)] 4 | struct Item { 5 | collection: ContractAddress, 6 | tokenId: u256 7 | } 8 | 9 | #[derive(Copy, Drop, Serde, Hash, starknet::Store)] 10 | struct Stake { 11 | owner: ContractAddress, 12 | stakedAt: u64 13 | } 14 | 15 | #[starknet::interface] 16 | trait IFlexStakingPool { 17 | fn setAllowedCollection(ref self: TContractState, collection: ContractAddress, allowed: bool); 18 | fn setRewardPerUnitTime(ref self: TContractState, collection: ContractAddress, reward: u256); 19 | fn setTimeUnit(ref self: TContractState, collection: ContractAddress, timeUnit: u64); 20 | fn stakeNFT(ref self: TContractState, collection: ContractAddress, tokenId: u256); 21 | fn unstakeNFT(ref self: TContractState, collection: ContractAddress, tokenId: u256); 22 | fn getUserPointByItem( 23 | self: @TContractState, user: ContractAddress, nftCollection: ContractAddress, tokenId: u256 24 | ) -> u256; 25 | fn getUserTotalPoint(self: @TContractState, user: ContractAddress,) -> u256; 26 | } 27 | 28 | #[starknet::interface] 29 | trait IAdditionalImpl { 30 | fn getStakedStatus(self: @TContractState, collection: ContractAddress, tokenId: u256) -> Stake; 31 | fn getItemStaked(self: @TContractState, user: ContractAddress) -> Array::; 32 | fn isEligibleCollection(self: @TContractState, collection: ContractAddress) -> bool; 33 | fn totalStaked(self: @TContractState, collection: ContractAddress) -> u256; 34 | fn getTimeUnit(self: @TContractState, collection: ContractAddress) -> u64; 35 | fn getRewardPerUnitTime(self: @TContractState, collection: ContractAddress) -> u256; 36 | } 37 | -------------------------------------------------------------------------------- /experimental/erc_6806_holding_time_tracking/tests/test_contract.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | use snforge_std::{declare, ContractClassTrait, DeclareResultTrait}; 4 | 5 | use erc_6806_holding_time_tracking::IHelloStarknetSafeDispatcher; 6 | use erc_6806_holding_time_tracking::IHelloStarknetSafeDispatcherTrait; 7 | use erc_6806_holding_time_tracking::IHelloStarknetDispatcher; 8 | use erc_6806_holding_time_tracking::IHelloStarknetDispatcherTrait; 9 | 10 | fn deploy_contract(name: ByteArray) -> ContractAddress { 11 | let contract = declare(name).unwrap().contract_class(); 12 | let (contract_address, _) = contract.deploy(@ArrayTrait::new()).unwrap(); 13 | contract_address 14 | } 15 | 16 | #[test] 17 | fn test_increase_balance() { 18 | let contract_address = deploy_contract("HelloStarknet"); 19 | 20 | let dispatcher = IHelloStarknetDispatcher { contract_address }; 21 | 22 | let balance_before = dispatcher.get_balance(); 23 | assert(balance_before == 0, 'Invalid balance'); 24 | 25 | dispatcher.increase_balance(42); 26 | 27 | let balance_after = dispatcher.get_balance(); 28 | assert(balance_after == 42, 'Invalid balance'); 29 | } 30 | 31 | #[test] 32 | #[feature("safe_dispatcher")] 33 | fn test_cannot_increase_balance_with_zero_value() { 34 | let contract_address = deploy_contract("HelloStarknet"); 35 | 36 | let safe_dispatcher = IHelloStarknetSafeDispatcher { contract_address }; 37 | 38 | let balance_before = safe_dispatcher.get_balance().unwrap(); 39 | assert(balance_before == 0, 'Invalid balance'); 40 | 41 | match safe_dispatcher.increase_balance(0) { 42 | Result::Ok(_) => core::panic_with_felt252('Should have panicked'), 43 | Result::Err(panic_data) => { 44 | assert(*panic_data.at(0) == 'Amount cannot be 0', *panic_data.at(0)); 45 | } 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/README.md: -------------------------------------------------------------------------------- 1 | # ERC 5643 Subscription NFT 2 | 3 | ## Overview 4 | 5 | ERC 5643 is a standard for subscription-based NFTs that allows users to subscribe to digital assets. This standard provides a framework for managing subscriptions, including renewal and cancellation processes. 6 | 7 | ## Features 8 | 9 | ### Core Functionality 10 | - Subscription creation and management 11 | - Token-based subscription tracking 12 | - Automatic expiration handling 13 | - Subscription renewal management 14 | - Transfer capability between users 15 | 16 | ### Technical Integration 17 | - Starknet-compatible implementation 18 | - Cairo-specific optimizations 19 | - Comprehensive test coverage 20 | 21 | ## Interface Definition 22 | 23 | ```cairo 24 | pub trait IERC5643 { 25 | fn renew_subscription(ref self: TState, token_id: u256, duration: u64); 26 | fn cancel_subscription(ref self: TState, token_id: u256); 27 | fn expires_at(self: @TState, token_id: u256) -> u64; 28 | fn is_renewable(self: @TState, token_id: u256) -> bool; 29 | } 30 | ``` 31 | 32 | 33 | 34 | ## Cairo Implementation Notes 35 | 36 | ### Syntax Adaptations 37 | - Use of `felt` type for integer values 38 | - Explicit return type declarations 39 | - Clear modifier definitions for access control 40 | - Integration with Starknet's storage model 41 | 42 | ### Development Requirements 43 | - [scarb](https://docs.swmansion.com/scarb/) 44 | - [starknet-foundry](https://github.com/foundry-rs/starknet-foundry) 45 | 46 | ### Build and Test 47 | ```bash 48 | # Compile the project 49 | scarb build 50 | 51 | # Run tests 52 | scarb test 53 | 54 | # Format code 55 | scarb fmt 56 | ``` 57 | 58 | ## Warning 59 | 60 | ⚠️ This implementation is experimental and under active development. Use with caution in production environments. 61 | 62 | ## License 63 | 64 | Released under the Apache License. -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/solidity/src/ERC5643.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: CC0-1.0 2 | pragma solidity ^0.8.27; 3 | 4 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 5 | import "./IERC5643.sol"; 6 | 7 | contract ERC5643 is ERC721, IERC5643 { 8 | mapping(uint256 => uint64) private _expirations; 9 | 10 | error SubscriptionNotRenewable(); 11 | 12 | constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {} 13 | 14 | function renewSubscription(uint256 tokenId, uint64 duration) external payable { 15 | _checkAuthorized(_ownerOf(tokenId), msg.sender, tokenId); 16 | 17 | uint64 currentExpiration = _expirations[tokenId]; 18 | uint64 newExpiration; 19 | if (currentExpiration == 0) { 20 | newExpiration = uint64(block.timestamp) + duration; 21 | } else { 22 | if (!isRenewable(tokenId)) { 23 | revert SubscriptionNotRenewable(); 24 | } 25 | newExpiration = currentExpiration + duration; 26 | } 27 | 28 | _expirations[tokenId] = newExpiration; 29 | 30 | emit SubscriptionUpdate(tokenId, newExpiration); 31 | } 32 | 33 | function cancelSubscription(uint256 tokenId) external payable { 34 | _checkAuthorized(_ownerOf(tokenId), msg.sender, tokenId); 35 | delete _expirations[tokenId]; 36 | emit SubscriptionUpdate(tokenId, 0); 37 | } 38 | 39 | function expiresAt(uint256 tokenId) external view returns(uint64) { 40 | return _expirations[tokenId]; 41 | } 42 | 43 | function isRenewable(uint256) public pure returns(bool) { 44 | return true; 45 | } 46 | 47 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 48 | return interfaceId == type(IERC5643).interfaceId || super.supportsInterface(interfaceId); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /openedition/src/interfaces/INonFungibleFlexDropToken.cairo: -------------------------------------------------------------------------------- 1 | use array::Array; 2 | use starknet::ContractAddress; 3 | use openedition::utils::openedition::{PhaseDrop, MultiConfigureStruct}; 4 | 5 | const I_NON_FUNGIBLE_FLEX_DROP_TOKEN_ID: felt252 = 6 | 0x3e8437a5f69da6b8bd474c863221741d75466a9500cfe343ac93d0e38135c16; 7 | 8 | #[starknet::interface] 9 | trait INonFungibleFlexDropToken { 10 | // update FlexDrop contract addresses 11 | fn update_allowed_flex_drop( 12 | ref self: TContractState, allowed_flex_drop: Array:: 13 | ); 14 | // mint tokens, restricted to the FlexDrop contract 15 | fn mint_flex_drop( 16 | ref self: TContractState, minter: ContractAddress, phase_id: u64, quantity: u64 17 | ); 18 | fn create_new_phase_drop( 19 | ref self: TContractState, 20 | flex_drop: ContractAddress, 21 | phase_detail: PhaseDrop, 22 | fee_recipient: ContractAddress, 23 | ); 24 | fn update_phase_drop( 25 | ref self: TContractState, flex_drop: ContractAddress, phase_id: u64, phase_detail: PhaseDrop 26 | ); 27 | fn update_creator_payout( 28 | ref self: TContractState, flex_drop: ContractAddress, payout_address: ContractAddress 29 | ); 30 | // update payer address for paying gas fee of minting NFT 31 | fn update_payer( 32 | ref self: TContractState, flex_drop: ContractAddress, payer: ContractAddress, allowed: bool 33 | ); 34 | fn multi_configure(ref self: TContractState, config: MultiConfigureStruct); 35 | // return (number minted, current total supply, max supply) 36 | fn get_mint_state( 37 | self: @TContractState, minter: ContractAddress, phase_id: u64 38 | ) -> (u64, u64, u64); 39 | fn get_current_token_id(self: @TContractState) -> u256; 40 | fn get_allowed_flex_drops(self: @TContractState) -> Span::; 41 | } 42 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc5006_cairo" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin_introspection", 9 | "openzeppelin_token", 10 | ] 11 | 12 | [[package]] 13 | name = "openzeppelin_access" 14 | version = "0.17.0" 15 | source = "registry+https://scarbs.xyz/" 16 | checksum = "sha256:541bb8fdf1ad17fe0d275b00acb9f0d7f56ea5534741e21535ac3fda2c600281" 17 | dependencies = [ 18 | "openzeppelin_introspection", 19 | "openzeppelin_utils", 20 | ] 21 | 22 | [[package]] 23 | name = "openzeppelin_account" 24 | version = "0.17.0" 25 | source = "registry+https://scarbs.xyz/" 26 | checksum = "sha256:c4e11609fdd1f4c3d3004cd1468711bd2ea664739c9e59a4b270567fe4c23ee3" 27 | dependencies = [ 28 | "openzeppelin_introspection", 29 | "openzeppelin_utils", 30 | ] 31 | 32 | [[package]] 33 | name = "openzeppelin_governance" 34 | version = "0.17.0" 35 | source = "registry+https://scarbs.xyz/" 36 | checksum = "sha256:b7e0142d88d69a8c367aea8c9dc7f659f27372551efc23f39a0cf71a189c1302" 37 | dependencies = [ 38 | "openzeppelin_access", 39 | "openzeppelin_introspection", 40 | ] 41 | 42 | [[package]] 43 | name = "openzeppelin_introspection" 44 | version = "0.17.0" 45 | source = "registry+https://scarbs.xyz/" 46 | checksum = "sha256:892433a4a1ea0fc9cf7cdb01e06ddc2782182abcc188e4ea5dd480906d006cf8" 47 | 48 | [[package]] 49 | name = "openzeppelin_token" 50 | version = "0.17.0" 51 | source = "registry+https://scarbs.xyz/" 52 | checksum = "sha256:77997a7e217b69674c34b402dc0c7b2210540db66a56087572679c31896eaabb" 53 | dependencies = [ 54 | "openzeppelin_account", 55 | "openzeppelin_governance", 56 | "openzeppelin_introspection", 57 | ] 58 | 59 | [[package]] 60 | name = "openzeppelin_utils" 61 | version = "0.17.0" 62 | source = "registry+https://scarbs.xyz/" 63 | checksum = "sha256:36d93e353f42fd6b824abcd8b4b51c3f5d02c893c5f886ae81403b0368aa5fde" 64 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/tests/utils.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use openzeppelin_utils::serde::SerializedAppend; 3 | use openzeppelin_testing::constants::{NAME, SYMBOL, BASE_URI, OWNER, TOKEN_ID}; 4 | use openzeppelin_testing::deployment::declare_and_deploy; 5 | use erc_5643_subscription_nft::presets::erc5643_subscription_nft::{ 6 | IERC5643SubscriptionNftMixinDispatcher, IERC5643SubscriptionNftMixinDispatcherTrait, 7 | IERC5643SubscriptionNftMixinSafeDispatcher, 8 | }; 9 | 10 | #[derive(Copy, Drop)] 11 | pub struct ERC5643Test { 12 | pub erc5643_subscription_nft_address: ContractAddress, 13 | pub erc5643_subscription_nft: IERC5643SubscriptionNftMixinDispatcher, 14 | pub erc5643_subscription_nft_safe: IERC5643SubscriptionNftMixinSafeDispatcher, 15 | } 16 | 17 | #[generate_trait] 18 | pub impl ERC5643TestImpl of ERC5643TestTrait { 19 | fn setup() -> ERC5643Test { 20 | let mut erc5643_subscription_nft_calldata = array![]; 21 | erc5643_subscription_nft_calldata.append_serde(NAME()); 22 | erc5643_subscription_nft_calldata.append_serde(SYMBOL()); 23 | erc5643_subscription_nft_calldata.append_serde(BASE_URI()); 24 | let erc5643_subscription_nft_address = declare_and_deploy( 25 | "ERC5643SubscriptionNft", erc5643_subscription_nft_calldata 26 | ); 27 | let erc5643_subscription_nft = IERC5643SubscriptionNftMixinDispatcher { 28 | contract_address: erc5643_subscription_nft_address 29 | }; 30 | let erc5643_subscription_nft_safe = IERC5643SubscriptionNftMixinSafeDispatcher { 31 | contract_address: erc5643_subscription_nft_address 32 | }; 33 | erc5643_subscription_nft.mint(OWNER(), TOKEN_ID); 34 | ERC5643Test { 35 | erc5643_subscription_nft_address, 36 | erc5643_subscription_nft, 37 | erc5643_subscription_nft_safe, 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /marketplace/src/proxy.cairo: -------------------------------------------------------------------------------- 1 | use starknet::{ContractAddress, class_hash::ClassHash}; 2 | 3 | #[starknet::interface] 4 | trait IProxy { 5 | fn upgrade(ref self: TState, new_implementation: ClassHash); 6 | fn set_admin(ref self: TState, new_admin: ContractAddress); 7 | fn get_implementation(self: @TState) -> ClassHash; 8 | fn get_admin(self: @TState) -> ContractAddress; 9 | fn __default__(self: @TState, selector: felt252, calldata: Span) -> Span; 10 | fn __l1_default__(self: @TState, selector: felt252, calldata: Span); 11 | } 12 | 13 | #[starknet::contract] 14 | mod Proxy { 15 | use starknet::{ContractAddress, contract_address_const, class_hash::ClassHash}; 16 | 17 | #[storage] 18 | struct Storage {} 19 | 20 | #[constructor] 21 | fn constructor( 22 | ref self: ContractState, 23 | implementation_hash: ClassHash, 24 | selector: felt252, 25 | calldata: Span 26 | ) { // TODO 27 | } 28 | 29 | #[abi(embed_v0)] 30 | impl ProxyImpl of super::IProxy { 31 | fn upgrade(ref self: ContractState, new_implementation: ClassHash) { // TODO 32 | } 33 | 34 | fn set_admin(ref self: ContractState, new_admin: ContractAddress) { // TODO 35 | } 36 | 37 | fn get_implementation(self: @ContractState) -> ClassHash { 38 | // TODO 39 | Zeroable::zero() 40 | } 41 | 42 | fn get_admin(self: @ContractState) -> ContractAddress { 43 | // TODO 44 | contract_address_const::<0>() 45 | } 46 | fn __default__( 47 | self: @ContractState, selector: felt252, calldata: Span 48 | ) -> Span { 49 | // TODO 50 | array![0].span() 51 | } 52 | fn __l1_default__( 53 | self: @ContractState, selector: felt252, calldata: Span 54 | ) { // TODO 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /experimental/erc_7765_rwa_integration/src/scripts/calculate_interface_id.py: -------------------------------------------------------------------------------- 1 | # calculate_interface_id.py 2 | 3 | from starkware.starknet.public.abi import starknet_keccak 4 | 5 | extended_function_selector_signatures_list_metadata = [ 6 | 'name()->ByteArray', 7 | 'symbol()->ByteArray', 8 | 'token_uri(u256)->ByteArray', 9 | 'privilegeURI(u256)->ByteArray', 10 | ] 11 | 12 | extended_function_selector_signatures_list = [ 13 | 'balance_of(ContractAddress)->u256', 14 | 'owner_of(u256)->ContractAddress', 15 | 'safe_transfer_from(ContractAddress,ContractAddress,u256,Span)->()', 16 | 'transfer_from(ContractAddress,ContractAddress,u256)->()', 17 | 'approve(ContractAddress,u256)->()', 18 | 'set_approval_for_all(ContractAddress,bool)->()', 19 | 'get_approved(u256)->ContractAddress', 20 | 'is_approved_for_all(ContractAddress,ContractAddress)->bool', 21 | 'is_exercisable(u256,u256)->bool', 22 | 'is_exercised(u256,u256)->bool', 23 | 'get_privilege_ids(u256)->Array', 24 | 'exercise_privilege(u256,ContractAddress,u256)->()', 25 | ] 26 | 27 | extended_function_selector_signatures_list_receiver = [ 28 | 'on_erc7765_received(ContractAddress,ContractAddress,u256,Span)->felt252' 29 | ] 30 | 31 | def generate(arr): 32 | interface_id = 0x0 33 | for function_signature in arr: 34 | function_id = starknet_keccak(function_signature.encode()) 35 | interface_id ^= function_id 36 | return hex(interface_id) 37 | 38 | 39 | def main(): 40 | # interface_id = 0x0 41 | # for function_signature in extended_function_selector_signatures_list: 42 | # function_id = starknet_keccak(function_signature.encode()) 43 | # interface_id ^= function_id 44 | 45 | print('ERC7765 ID:') 46 | print(generate(extended_function_selector_signatures_list)) 47 | 48 | print('ERC7765Metadata ID:') 49 | print(generate(extended_function_selector_signatures_list_metadata)) 50 | 51 | print('ERC7765Receiver ID:') 52 | print(generate(extended_function_selector_signatures_list_receiver)) 53 | 54 | 55 | main() -------------------------------------------------------------------------------- /stakingpool/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 1. Stakingpool 5 | Includes implementation of the staking NFT pool contracts. 6 | 7 | #### Overview 8 | The `StakingPool` contract allows users to stake their NFTs (ERC721 tokens) from specified eligible collections and earn rewards over time. This incentivizes NFT holders by rewarding them based on the duration their NFTs remain staked 9 | 10 | #### Key Features: 11 | - **NFT Staking:** Users can stake their NFTs from collections that are approved by the contract owner. 12 | - **Reward Accumulation:** Rewards are earned based on the amount of time an NFT is staked. The longer an NFT is staked, the more rewards it accrues. 13 | - **Flexibility:** The contract supports various NFT collections, each with customizable reward parameters set by the contract owner. 14 | 15 | #### Staking Process 16 | 17 | **Stake an NFT:** 18 | - Users call the `stakeNFT` function, providing the collection address and the token ID of the NFT they wish to stake. 19 | - Once staked, the NFT is locked in the contract and cannot be transferred until it is unstaked. 20 | 21 | **Unstake an NFT:** 22 | - Users can call the `unstakeNFT` function to retrieve their staked NFT. 23 | - During the unstaking process, any accumulated rewards are claimed and credited to the user. 24 | 25 | **Claiming Rewards:** 26 | - Rewards are Based on the staking duration and the reward rate set for the NFT collection. 27 | - Users can view their accumulated rewards for each staked NFT using the `getUserPointByItem` function. 28 | 29 | #### Contract Configuration 30 | 31 | - **Eligible Collections:** Only NFTs from collections that have been approved by the contract owner can be staked. 32 | - **Reward Calculation:** The contract owner sets the time unit (in seconds) and the reward per unit time for each collection. These parameters determine how rewards accumulate for staked NFTs. 33 | 34 | #### Security Considerations 35 | 36 | - The contract implements reentrancy protection to secure staking and unstaking operations. 37 | - Only the contract owner has the authority to modify which NFT collections are eligible for staking and to set the reward parameters. -------------------------------------------------------------------------------- /experimental/erc_5585_nft_authorization/src/interface.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC721 { 5 | fn balance_of(self: @TState, owner: ContractAddress) -> u256; 6 | fn owner_of(self: @TState, token_id: u256) -> ContractAddress; 7 | fn get_approved(self: @TState, token_id: u256) -> ContractAddress; 8 | fn is_approved_for_all( 9 | self: @TState, owner: ContractAddress, operator: ContractAddress 10 | ) -> bool; 11 | fn approve(ref self: TState, to: ContractAddress, token_id: u256); 12 | fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); 13 | fn transfer_from(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256); 14 | fn safe_transfer_from( 15 | ref self: TState, 16 | from: ContractAddress, 17 | to: ContractAddress, 18 | token_id: u256, 19 | data: Span 20 | ); 21 | } 22 | 23 | #[starknet::interface] 24 | pub trait IERC5585 { 25 | fn get_rights(self: @TState) -> Array; 26 | fn authorize_user(ref self: TState, token_id: u256, user: ContractAddress, duration: u64); 27 | fn authorize_user_with_rights( 28 | ref self: TState, 29 | token_id: u256, 30 | user: ContractAddress, 31 | rights: Array, 32 | duration: u64 33 | ); 34 | fn transfer_user_rights(ref self: TState, token_id: u256, new_user: ContractAddress); 35 | fn extend_duration(ref self: TState, token_id: u256, user: ContractAddress, duration: u64); 36 | fn update_user_rights( 37 | ref self: TState, token_id: u256, user: ContractAddress, rights: Array 38 | ); 39 | fn get_expires(self: @TState, token_id: u256, user: ContractAddress) -> u64; 40 | fn get_user_rights(self: @TState, token_id: u256, user: ContractAddress) -> Array; 41 | fn update_user_limit(ref self: TState, user_limit: u256); 42 | fn update_reset_allowed(ref self: TState, reset_allowed: bool); 43 | fn check_authorization_availability(self: @TState, token_id: u256) -> bool; 44 | fn reset_user(ref self: TState, token_id: u256, user: ContractAddress); 45 | } 46 | -------------------------------------------------------------------------------- /marketplace/Sell_any_item_at_fixed_price.md: -------------------------------------------------------------------------------- 1 | ## Strategy for Selling Any Item at a Fixed Price 2 | 3 | This contract, StrategySaleAnyItemAtFixedPrice, implements a strategy for selling items at a fixed price on StarkNet. The contract manages sales by allowing owners to list items (identified by token_id), set prices, handle buyer bids, and upgrade the contract. 4 | Key Functionalities 5 | 6 | Initialization (constructor): 7 | Initializes the contract with the owner's address and a protocol fee. The owner's address must not be zero, and the protocol fee is set during the initialization process. 8 | 9 | Updating Protocol Fee (update_protocol_fee): 10 | Allows the contract owner to update the protocol fee, which is a fee applied to transactions executed within the marketplace. Only the contract owner has the authority to modify this fee. 11 | 12 | Getting Protocol Fee (protocol_fee): 13 | Retrieves the current protocol fee stored in the contract. 14 | 15 | Setting Buy-Back Price for any item (set_buy_back_price_for_any_item): 16 | Allows a buyer to set a buy-back price for any item from a specific collection. 17 | 18 | Executing Buyer Bids (can_execute_buyer_bid): 19 | Verifies whether a buyer's bid can be executed. The contract checks if the token was listed for sale by the seller and compares the bid price with the existing buy-back price to determine if the bid is valid and executable. 20 | 21 | Contract Upgrading (upgrade): 22 | Allows the contract owner to upgrade the contract's implementation using a new ClassHash. This operation can only be performed by the contract owner to ensure the contract's integrity. 23 | 24 | Events 25 | 26 | SetBuyBackPriceForItem: 27 | Emitted when a buyer sets a buy-back price for an item. This event logs the buyer's address, the price set, and the collection address. 28 | 29 | Integrations 30 | 31 | This contract integrates with StarkNet's OwnableComponent for ownership management and UpgradeableComponent for upgradability. These integrations ensure that sensitive operations, such as updating protocol fees and upgrading the contract, are restricted to authorized users only. 32 | 33 | PR: https://github.com/Flex-NFT-Marketplace/Flex-Marketplace-Contract/pull/98 34 | -------------------------------------------------------------------------------- /marketplace/src/mocks/strategy.cairo: -------------------------------------------------------------------------------- 1 | use marketplace::utils::order_types::{MakerOrder, TakerOrder}; 2 | use starknet::ContractAddress; 3 | 4 | #[starknet::interface] 5 | trait IExecutionStrategy { 6 | fn protocolFee(self: @TState) -> u128; 7 | fn canExecuteTakerAsk( 8 | self: @TState, taker_ask: TakerOrder, maker_bid: MakerOrder, extra_params: Array 9 | ) -> (bool, u256, u128); 10 | fn canExecuteTakerBid( 11 | self: @TState, taker_bid: TakerOrder, maker_ask: MakerOrder 12 | ) -> (bool, u256, u128); 13 | } 14 | 15 | #[starknet::interface] 16 | trait IAuctionStrategy { 17 | fn auctionRelayer(self: @TState) -> ContractAddress; 18 | fn canExecuteAuctionSale( 19 | self: @TState, maker_ask: MakerOrder, maker_bid: MakerOrder 20 | ) -> (bool, u256, u128); 21 | } 22 | 23 | #[starknet::contract] 24 | mod Strategy { 25 | use marketplace::utils::order_types::{MakerOrder, TakerOrder}; 26 | use starknet::ContractAddress; 27 | 28 | const E18: u128 = 1_000_000_000_000_000_000; 29 | 30 | #[storage] 31 | struct Storage {} 32 | 33 | #[abi(embed_v0)] 34 | impl MockExecutionStrategyImpl of super::IExecutionStrategy { 35 | fn protocolFee(self: @ContractState) -> u128 { 36 | 1000 37 | } 38 | fn canExecuteTakerAsk( 39 | self: @ContractState, 40 | taker_ask: super::TakerOrder, 41 | maker_bid: super::MakerOrder, 42 | extra_params: Array 43 | ) -> (bool, u256, u128) { 44 | (true, 1, E18) 45 | } 46 | fn canExecuteTakerBid( 47 | self: @ContractState, taker_bid: super::TakerOrder, maker_ask: super::MakerOrder 48 | ) -> (bool, u256, u128) { 49 | (true, 1, E18) 50 | } 51 | } 52 | 53 | #[abi(embed_v0)] 54 | impl MockAuctionStrategyImpl of super::IAuctionStrategy { 55 | fn auctionRelayer(self: @ContractState) -> ContractAddress { 56 | starknet::contract_address_const::<'RELAYER'>() 57 | } 58 | fn canExecuteAuctionSale( 59 | self: @ContractState, maker_ask: MakerOrder, maker_bid: MakerOrder 60 | ) -> (bool, u256, u128) { 61 | (true, 1, E18) 62 | } 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /marketplace/src/utils/order_types.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use marketplace::DefaultContractAddress; 3 | use poseidon::poseidon_hash_span; 4 | 5 | #[derive(Copy, Drop, Serde, Default)] 6 | struct MakerOrder { 7 | is_order_ask: bool, // 1 = ask / 0 = bid 8 | signer: ContractAddress, // signer of the maker order 9 | collection: ContractAddress, // collection address 10 | price: u128, 11 | seller: ContractAddress, 12 | token_id: u256, 13 | amount: u128, // amount of tokens to sell/purchase (must be 1 for ERC721, 1+ for ERC1155) 14 | strategy: ContractAddress, // strategy address for trade execution (e.g. StandardSaleForFixedPrice) 15 | currency: ContractAddress, // currency address 16 | salt_nonce: u128, // order nonce (must be unique unless new maker order is meant to override existing one e.g. lower ask price) 17 | start_time: u64, // startTime in timestamp 18 | end_time: u64, // endTime in timestamp 19 | min_percentage_to_ask: u128, // slippage protection (9000 = 90% of the final price must return to ask) 20 | params: felt252, 21 | } 22 | 23 | #[derive(Copy, Drop, Serde, Default)] 24 | struct BuyerBidOrder { 25 | token_id: u128, 26 | buyer_adddress: ContractAddress, 27 | price: u128 28 | } 29 | 30 | 31 | #[derive(Copy, Drop, Serde, Default)] 32 | struct TakerOrder { 33 | is_order_ask: bool, // 1 = ask / 0 = bid 34 | taker: ContractAddress, // caller 35 | price: u128, // final price for the purchase 36 | token_id: u256, 37 | amount: u128, 38 | min_percentage_to_ask: u128, // slippage protection (9000 = 90% of the final price must return to ask) 39 | params: felt252, 40 | } 41 | 42 | trait YoloTrait { 43 | fn compute_order_hash(self: @TState) -> felt252; 44 | } 45 | 46 | impl YoloTraitImpl of YoloTrait { 47 | fn compute_order_hash(self: @TakerOrder) -> felt252 { 48 | let mut buf = array![]; 49 | self.serialize(ref buf); 50 | poseidon_hash_span(buf.span()) 51 | } 52 | } 53 | 54 | #[derive(Clone, Drop, Serde, starknet::Store)] 55 | struct PendingRequest { 56 | request_id: u64, 57 | ask_price: u128, 58 | bid_price: u128, 59 | taker: ContractAddress, 60 | collection: ContractAddress, 61 | token_id: u256, 62 | amount: u128, 63 | finished: bool, 64 | won: bool, 65 | } 66 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc_4907_rental_nft" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin_access", 9 | "openzeppelin_introspection", 10 | "openzeppelin_testing", 11 | "openzeppelin_token", 12 | "openzeppelin_utils", 13 | "snforge_std", 14 | ] 15 | 16 | [[package]] 17 | name = "openzeppelin_access" 18 | version = "0.20.0" 19 | source = "registry+https://scarbs.xyz/" 20 | checksum = "sha256:7734901a0ca7a7065e69416fea615dd1dc586c8dc9e76c032f25ee62e8b2a06c" 21 | dependencies = [ 22 | "openzeppelin_introspection", 23 | ] 24 | 25 | [[package]] 26 | name = "openzeppelin_account" 27 | version = "0.20.0" 28 | source = "registry+https://scarbs.xyz/" 29 | checksum = "sha256:1aa3a71e2f40f66f98d96aa9bf9f361f53db0fd20fa83ef7df04426a3c3a926a" 30 | dependencies = [ 31 | "openzeppelin_introspection", 32 | "openzeppelin_utils", 33 | ] 34 | 35 | [[package]] 36 | name = "openzeppelin_introspection" 37 | version = "0.20.0" 38 | source = "registry+https://scarbs.xyz/" 39 | checksum = "sha256:13e04a2190684e6804229a77a6c56de7d033db8b9ef519e5e8dee400a70d8a3d" 40 | 41 | [[package]] 42 | name = "openzeppelin_testing" 43 | version = "0.20.0" 44 | source = "registry+https://scarbs.xyz/" 45 | checksum = "sha256:2fa9aaadacffd6a95754781ed18f6ee660f52a30d27b024efcde2b4b5648e0b3" 46 | dependencies = [ 47 | "snforge_std", 48 | ] 49 | 50 | [[package]] 51 | name = "openzeppelin_token" 52 | version = "0.20.0" 53 | source = "registry+https://scarbs.xyz/" 54 | checksum = "sha256:4452f449dc6c1ea97cf69d1d9182749abd40e85bd826cd79652c06a627eafd91" 55 | dependencies = [ 56 | "openzeppelin_access", 57 | "openzeppelin_account", 58 | "openzeppelin_introspection", 59 | "openzeppelin_utils", 60 | ] 61 | 62 | [[package]] 63 | name = "openzeppelin_utils" 64 | version = "0.20.0" 65 | source = "registry+https://scarbs.xyz/" 66 | checksum = "sha256:44f32d242af1e43982decc49c563e613a9b67ade552f5c3d5cde504e92f74607" 67 | 68 | [[package]] 69 | name = "snforge_scarb_plugin" 70 | version = "0.34.0" 71 | source = "registry+https://scarbs.xyz/" 72 | checksum = "sha256:56f2b06ff2f0d8bbdfb7fb6c211fba7e4da6e5334ea70ba849af329a739faf11" 73 | 74 | [[package]] 75 | name = "snforge_std" 76 | version = "0.34.0" 77 | source = "registry+https://scarbs.xyz/" 78 | checksum = "sha256:bd20964bde07e6fd0f7adb50d41216f05d66abd422ed82241030369333385876" 79 | dependencies = [ 80 | "snforge_scarb_plugin", 81 | ] 82 | -------------------------------------------------------------------------------- /openedition/src/interfaces/ISignatureChecker2.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use openedition::DefaultContractAddress; 3 | 4 | use openedition::utils::openedition::WhiteListParam; 5 | 6 | #[derive(Copy, Drop, Serde, Default)] 7 | struct MakerOrder { 8 | is_order_ask: bool, // 1 = ask / 0 = bid 9 | signer: ContractAddress, // signer of the maker order 10 | collection: ContractAddress, // collection address 11 | price: u128, 12 | seller: ContractAddress, 13 | token_id: u256, 14 | amount: u128, // amount of tokens to sell/purchase (must be 1 for ERC721, 1+ for ERC1155) 15 | strategy: ContractAddress, // strategy address for trade execution (e.g. StandardSaleForFixedPrice) 16 | currency: ContractAddress, // currency address 17 | salt_nonce: u128, // order nonce (must be unique unless new maker order is meant to override existing one e.g. lower ask price) 18 | start_time: u64, // startTime in timestamp 19 | end_time: u64, // endTime in timestamp 20 | min_percentage_to_ask: u128, // slippage protection (9000 = 90% of the final price must return to ask) 21 | params: felt252, 22 | } 23 | 24 | #[derive(Copy, Drop, Serde, Default)] 25 | struct TakerOrder { 26 | is_order_ask: bool, // 1 = ask / 0 = bid 27 | taker: ContractAddress, // caller 28 | price: u128, // final price for the purchase 29 | token_id: u256, 30 | amount: u128, 31 | min_percentage_to_ask: u128, // slippage protection (9000 = 90% of the final price must return to ask) 32 | params: felt252, 33 | } 34 | 35 | #[starknet::interface] 36 | trait ISignatureChecker2 { 37 | fn compute_maker_order_hash(self: @TState, hash_domain: felt252, order: MakerOrder) -> felt252; 38 | fn verify_maker_order_signature( 39 | self: @TState, hash_domain: felt252, order: MakerOrder, order_signature: Array 40 | ); 41 | fn compute_message_hash(self: @TState, domain_hash: felt252, order: MakerOrder) -> felt252; 42 | fn verify_maker_order_signature_v2( 43 | self: @TState, domain_hash: felt252, order: MakerOrder, order_signature: Array 44 | ); 45 | 46 | fn compute_whitelist_mint_message_hash( 47 | self: @TState, domain_hash: felt252, signer: ContractAddress, whitelist_data: WhiteListParam 48 | ) -> felt252; 49 | fn verify_whitelist_mint_proof( 50 | self: @TState, 51 | domain_hash: felt252, 52 | signer: ContractAddress, 53 | whitelist_data: WhiteListParam, 54 | proof: Array 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /experimental/erc_6806_holding_time_tracking/Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "erc_6806_holding_time_tracking" 3 | version = "0.1.0" 4 | edition = "2024_07" 5 | 6 | # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html 7 | 8 | [dependencies] 9 | starknet = "2.8.5" 10 | 11 | [dev-dependencies] 12 | snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.33.0" } 13 | assert_macros = "2.8.5" 14 | 15 | [[target.starknet-contract]] 16 | sierra = true 17 | 18 | [scripts] 19 | test = "snforge test" 20 | 21 | # Visit https://foundry-rs.github.io/starknet-foundry/appendix/scarb-toml.html for more information 22 | 23 | # [tool.snforge] # Define `snforge` tool section 24 | # exit_first = true # Stop tests execution immediately upon the first failure 25 | # fuzzer_runs = 1234 # Number of runs of the random fuzzer 26 | # fuzzer_seed = 1111 # Seed for the random fuzzer 27 | 28 | # [[tool.snforge.fork]] # Used for fork testing 29 | # name = "SOME_NAME" # Fork name 30 | # url = "http://your.rpc.url" # Url of the RPC provider 31 | # block_id.tag = "latest" # Block to fork from (block tag) 32 | 33 | # [[tool.snforge.fork]] 34 | # name = "SOME_SECOND_NAME" 35 | # url = "http://your.second.rpc.url" 36 | # block_id.number = "123" # Block to fork from (block number) 37 | 38 | # [[tool.snforge.fork]] 39 | # name = "SOME_THIRD_NAME" 40 | # url = "http://your.third.rpc.url" 41 | # block_id.hash = "0x123" # Block to fork from (block hash) 42 | 43 | # [profile.dev.cairo] # Configure Cairo compiler 44 | # unstable-add-statements-code-locations-debug-info = true # Should be used if you want to use coverage 45 | # unstable-add-statements-functions-debug-info = true # Should be used if you want to use coverage/profiler 46 | # inlining-strategy = "avoid" # Should be used if you want to use coverage 47 | 48 | # [features] # Used for conditional compilation 49 | # enable_for_tests = [] # Feature name and list of other features that should be enabled with it 50 | -------------------------------------------------------------------------------- /experimental/erc_7765_rwa_integration/src/interfaces/IERC7765.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | const IERC7765_ID: felt252 = 0x268bbe921710b42e87712bcee4aabbbdb8cbc7357c63fadab829af96e720bd7; 4 | const IERC7765_METADATA_ID: felt252 = 0x2de8c9aaf5439dd78e47cd7d4d2b480b0fa16524f156d6b326250c7c699f52; 5 | const IERC7765_RECEIVER_ID: felt252 = 0x35d6ca22886b5b97fa088a439543db8a121ef5466930e998d501a711eb878d5; 6 | 7 | #[starknet::interface] 8 | pub trait IERC7765 { 9 | 10 | // From ERC-721 11 | fn balance_of(self: @TContractState, account: ContractAddress) -> u256; 12 | fn owner_of(self: @TContractState, token_id: u256) -> ContractAddress; 13 | fn safe_transfer_from( 14 | ref self: TContractState, 15 | from: ContractAddress, 16 | to: ContractAddress, 17 | token_id: u256, 18 | data: Span 19 | ); 20 | fn transfer_from(ref self: TContractState, from: ContractAddress, to: ContractAddress, token_id: u256); 21 | fn approve(ref self: TContractState, to: ContractAddress, token_id: u256); 22 | fn set_approval_for_all(ref self: TContractState, operator: ContractAddress, approved: bool); 23 | fn get_approved(self: @TContractState, token_id: u256) -> ContractAddress; 24 | fn is_approved_for_all( 25 | self: @TContractState, owner: ContractAddress, operator: ContractAddress 26 | ) -> bool; 27 | 28 | // Specific to ERC7765 29 | fn is_exercisable(self: @TContractState, token_id: u256, privilege_id: u256, ) -> bool; 30 | fn is_exercised(self: @TContractState, token_id: u256, privilege_id: u256, ) -> bool; 31 | fn get_privilege_ids(self: @TContractState, token_id: u256) -> Array; 32 | fn exercise_privilege(ref self: TContractState, token_id: u256, to: ContractAddress, privilege_id: u256, calldata: Array); 33 | 34 | } 35 | 36 | #[starknet::interface] 37 | pub trait IERC7765Metadata { 38 | 39 | // From ERC-721 40 | fn name(self: @TContractState) -> ByteArray; 41 | fn symbol(self: @TContractState) -> ByteArray; 42 | fn token_uri(self: @TContractState, token_id: u256) -> ByteArray; 43 | 44 | // Specific to ERC7765 45 | fn privilegeURI(self: @TContractState, privilege_id: u256) -> ByteArray; 46 | } 47 | 48 | // ERC7765Receiver 49 | #[starknet::interface] 50 | trait IERC7765Receiver { 51 | fn on_erc7765_received( 52 | self: @TContractState, 53 | operator: ContractAddress, 54 | from: ContractAddress, 55 | token_id: u256, 56 | data: Span 57 | ) -> felt252; 58 | } -------------------------------------------------------------------------------- /experimental/erc_6806_holding_time_tracking/README.md: -------------------------------------------------------------------------------- 1 |
2 |

Cairo ERC-6806 Holding Time Tracking

3 |

Holding Time Tracking (ERC-6806) written in Cairo for Starknet.

4 |
5 | 6 | ### About 7 | 8 | A Cairo implementation of [EIP-6806](https://eips.ethereum.org/EIPS/eip-6806). EIP-6806 is an Ethereum standard for Holding Time Tracking NFTs. 9 | 10 | > ## ⚠️ WARNING! ⚠️ 11 | > 12 | > This repo contains highly experimental code. 13 | > Expect rapid iteration. 14 | > **Use at your own risk.** 15 | 16 | ### Project setup 17 | 18 | #### 📦 Requirements 19 | 20 | - [scarb](https://docs.swmansion.com/scarb/) 21 | - [starknet-foundry](https://github.com/foundry-rs/starknet-foundry) 22 | 23 | ### ⛏️ Compile 24 | 25 | ```bash 26 | scarb build 27 | ``` 28 | 29 | ### 💄 Code style 30 | 31 | ```bash 32 | scarb fmt 33 | ``` 34 | 35 | ### 🌡️ Test 36 | 37 | ```bash 38 | scarb test 39 | ``` 40 | 41 | ## ERC-6806 Details 42 | 43 | ### Overview 44 | ERC-6806 is a standard for Holding Time Tracking NFTs, allowing for the tracking of the duration for which a token is held. 45 | 46 | ### Functions 47 | - `get_holding_info(token_id: u256) -> (ContractAddress, u64)`: Returns the holder's address and the holding time for the specified token ID. 48 | - `set_holding_time_whitelisted_address(account: ContractAddress, ignore_reset: bool)`: Sets an address as whitelisted for holding time tracking. 49 | 50 | ## Syntax Changes for Starknet's Cairo 51 | 52 | ### Interface Definition 53 | ```cairo 54 | #[starknet::interface] 55 | pub trait IERC721 { 56 | fn get_holding_info(self: @TContractState, token_id: u256) -> (ContractAddress, u64); 57 | fn set_holding_time_whitelisted_address(ref self: TContractState, account: ContractAddress, ignore_reset: bool); 58 | } 59 | ``` 60 | 61 | ### Contract Implementation 62 | ```cairo 63 | #[starknet::contract] 64 | pub mod ERC721 { 65 | // Storage variables 66 | #[storage] 67 | struct Storage { 68 | holder: Map, 69 | hold_start: Map, 70 | } 71 | 72 | #[abi(embed_v0)] 73 | impl IERC721Impl of super::IERC721 { 74 | fn get_holding_info(self: @ContractState, token_id: u256) -> (ContractAddress, u64) { 75 | let holder = self.holder.read(token_id); 76 | let hold_start = self.hold_start.read(token_id); 77 | let current_time = get_block_timestamp(); 78 | let holding_time = current_time - hold_start; 79 | (holder, holding_time) 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/solidity/test/ERC5643.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: CC0-1.0 2 | pragma solidity ^0.8.27; 3 | 4 | import "forge-std/Test.sol"; 5 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 6 | import {IERC721Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; 7 | import "../src/ERC5643.sol"; 8 | 9 | contract ERC5643Mock is ERC5643 { 10 | constructor(string memory name_, string memory symbol_) ERC5643(name_, symbol_) {} 11 | 12 | function mint(address to, uint256 tokenId) public { 13 | _mint(to, tokenId); 14 | } 15 | } 16 | 17 | contract ERC5643Test is Test { 18 | event SubscriptionUpdate(uint256 indexed tokenId, uint64 expiration); 19 | 20 | address user1; 21 | uint256 tokenId; 22 | ERC5643Mock erc5643; 23 | 24 | function setUp() public { 25 | tokenId = 1; 26 | user1 = address(0x1); 27 | 28 | erc5643 = new ERC5643Mock("erc5369", "ERC5643"); 29 | erc5643.mint(user1, tokenId); 30 | } 31 | 32 | function testRenewalValid() public { 33 | vm.warp(1000); 34 | vm.prank(user1); 35 | vm.expectEmit(true, true, false, true); 36 | emit SubscriptionUpdate(tokenId, 3000); 37 | erc5643.renewSubscription(tokenId, 2000); 38 | } 39 | 40 | function testRenewalNotOwner() public { 41 | vm.expectRevert( 42 | abi.encodeWithSelector( 43 | IERC721Errors.ERC721InsufficientApproval.selector, 44 | address(this), 45 | tokenId 46 | ) 47 | ); 48 | erc5643.renewSubscription(tokenId, 2000); 49 | } 50 | 51 | function testCancelValid() public { 52 | vm.prank(user1); 53 | vm.expectEmit(true, true, false, true); 54 | emit SubscriptionUpdate(tokenId, 0); 55 | erc5643.cancelSubscription(tokenId); 56 | } 57 | 58 | function testCancelNotOwner() public { 59 | vm.expectRevert( 60 | abi.encodeWithSelector( 61 | IERC721Errors.ERC721InsufficientApproval.selector, 62 | address(this), 63 | tokenId 64 | ) 65 | ); 66 | erc5643.cancelSubscription(tokenId); 67 | } 68 | 69 | function testExpiresAt() public { 70 | vm.warp(1000); 71 | 72 | assertEq(erc5643.expiresAt(tokenId), 0); 73 | vm.startPrank(user1); 74 | erc5643.renewSubscription(tokenId, 2000); 75 | assertEq(erc5643.expiresAt(tokenId), 3000); 76 | 77 | erc5643.cancelSubscription(tokenId); 78 | assertEq(erc5643.expiresAt(tokenId), 0); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /marketplace/src/transfer_manager_ERC721.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::contract] 4 | mod TransferManagerNFT { 5 | use starknet::{ContractAddress, get_caller_address}; 6 | use marketplace::interfaces::nft_transfer_manager::ITransferManagerNFT; 7 | use marketplace::{DebugContractAddress, DisplayContractAddress}; 8 | use marketplace::utils::order_types::{MakerOrder, TakerOrder}; 9 | 10 | use openzeppelin::token::erc721::interface::{ 11 | IERC721CamelOnlyDispatcher, IERC721CamelOnlyDispatcherTrait 12 | }; 13 | use openzeppelin::access::ownable::OwnableComponent; 14 | component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); 15 | 16 | #[abi(embed_v0)] 17 | impl OwnableImpl = OwnableComponent::OwnableImpl; 18 | 19 | impl OwnableInternalImpl = OwnableComponent::InternalImpl; 20 | 21 | #[storage] 22 | struct Storage { 23 | marketplace: ContractAddress, 24 | #[substorage(v0)] 25 | ownable: OwnableComponent::Storage 26 | } 27 | 28 | #[event] 29 | #[derive(Drop, starknet::Event)] 30 | enum Event { 31 | #[flat] 32 | OwnableEvent: OwnableComponent::Event 33 | } 34 | 35 | #[abi(embed_v0)] 36 | impl TransferManagerNFTImpl of ITransferManagerNFT { 37 | fn initializer( 38 | ref self: ContractState, marketplace: ContractAddress, owner: ContractAddress, 39 | ) { 40 | // TODO: verify the role of Proxy here. 41 | self.marketplace.write(marketplace); 42 | self.ownable.initializer(owner); 43 | } 44 | 45 | fn transfer_non_fungible_token( 46 | ref self: ContractState, 47 | collection: ContractAddress, 48 | from: ContractAddress, 49 | to: ContractAddress, 50 | token_id: u256, 51 | amount: u128, 52 | data: Span, 53 | ) { 54 | let caller = get_caller_address(); 55 | assert!( 56 | caller == self.get_marketplace(), 57 | "TransferManagerNFT: caller {} is not MarketPlace", 58 | caller 59 | ); 60 | IERC721CamelOnlyDispatcher { contract_address: collection } 61 | .safeTransferFrom(from, to, token_id, data); 62 | } 63 | 64 | fn update_marketplace(ref self: ContractState, new_address: ContractAddress) { 65 | self.marketplace.write(new_address); 66 | } 67 | 68 | fn get_marketplace(self: @ContractState) -> ContractAddress { 69 | self.marketplace.read() 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /marketplace/src/mocks/account.cairo: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts for Cairo v0.7.0 (account/account.cairo) 3 | 4 | trait PublicKeyTrait { 5 | fn set_public_key(ref self: TState, new_public_key: felt252); 6 | fn get_public_key(self: @TState) -> felt252; 7 | } 8 | 9 | trait PublicKeyCamelTrait { 10 | fn setPublicKey(ref self: TState, newPublicKey: felt252); 11 | fn getPublicKey(self: @TState) -> felt252; 12 | } 13 | 14 | #[starknet::contract] 15 | mod Account { 16 | use ecdsa::check_ecdsa_signature; 17 | 18 | use openzeppelin::account::interface; 19 | use openzeppelin::introspection::interface::ISRC5; 20 | use openzeppelin::introspection::interface::ISRC5Camel; 21 | use openzeppelin::account::account::AccountComponent; 22 | use starknet::account::Call; 23 | use starknet::get_caller_address; 24 | use starknet::get_contract_address; 25 | use starknet::get_tx_info; 26 | use openzeppelin::introspection::src5::SRC5Component; 27 | 28 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 29 | 30 | #[abi(embed_v0)] 31 | impl SRC5Impl = SRC5Component::SRC5Impl; 32 | #[abi(embed_v0)] 33 | impl SRC5CamelImpl = SRC5Component::SRC5CamelImpl; 34 | impl SRC5InternalImpl = SRC5Component::InternalImpl; 35 | 36 | component!(path: AccountComponent, storage: account, event: AccountEvent); 37 | 38 | #[abi(embed_v0)] 39 | impl SRC6Impl = AccountComponent::SRC6Impl; 40 | #[abi(embed_v0)] 41 | impl DeployableImpl = AccountComponent::DeployableImpl; 42 | #[abi(embed_v0)] 43 | impl DeclarerImpl = AccountComponent::DeclarerImpl; 44 | #[abi(embed_v0)] 45 | impl PublicKeyImpl = AccountComponent::PublicKeyImpl; 46 | #[abi(embed_v0)] 47 | impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl; 48 | #[abi(embed_v0)] 49 | impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl; 50 | impl InternalImpl = AccountComponent::InternalImpl; 51 | 52 | #[storage] 53 | struct Storage { 54 | #[substorage(v0)] 55 | src5: SRC5Component::Storage, 56 | #[substorage(v0)] 57 | account: AccountComponent::Storage 58 | } 59 | 60 | #[event] 61 | #[derive(Drop, starknet::Event)] 62 | enum Event { 63 | #[flat] 64 | SRC5Event: SRC5Component::Event, 65 | #[flat] 66 | AccountEvent: AccountComponent::Event 67 | } 68 | 69 | #[constructor] 70 | fn constructor(ref self: ContractState, _public_key: felt252) { 71 | self.account.initializer(_public_key); 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /experimental/erc_6105_no_intermediary_nft_trading_protocol/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc_6105_no_intermediary_nft_trading_protocol" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin_introspection", 9 | "openzeppelin_testing", 10 | "openzeppelin_token", 11 | "openzeppelin_utils", 12 | "snforge_std", 13 | ] 14 | 15 | [[package]] 16 | name = "openzeppelin_access" 17 | version = "0.17.0" 18 | source = "registry+https://scarbs.xyz/" 19 | checksum = "sha256:541bb8fdf1ad17fe0d275b00acb9f0d7f56ea5534741e21535ac3fda2c600281" 20 | dependencies = [ 21 | "openzeppelin_introspection", 22 | "openzeppelin_utils", 23 | ] 24 | 25 | [[package]] 26 | name = "openzeppelin_account" 27 | version = "0.17.0" 28 | source = "registry+https://scarbs.xyz/" 29 | checksum = "sha256:c4e11609fdd1f4c3d3004cd1468711bd2ea664739c9e59a4b270567fe4c23ee3" 30 | dependencies = [ 31 | "openzeppelin_introspection", 32 | "openzeppelin_utils", 33 | ] 34 | 35 | [[package]] 36 | name = "openzeppelin_governance" 37 | version = "0.17.0" 38 | source = "registry+https://scarbs.xyz/" 39 | checksum = "sha256:b7e0142d88d69a8c367aea8c9dc7f659f27372551efc23f39a0cf71a189c1302" 40 | dependencies = [ 41 | "openzeppelin_access", 42 | "openzeppelin_introspection", 43 | ] 44 | 45 | [[package]] 46 | name = "openzeppelin_introspection" 47 | version = "0.17.0" 48 | source = "registry+https://scarbs.xyz/" 49 | checksum = "sha256:892433a4a1ea0fc9cf7cdb01e06ddc2782182abcc188e4ea5dd480906d006cf8" 50 | 51 | [[package]] 52 | name = "openzeppelin_testing" 53 | version = "0.17.0" 54 | source = "registry+https://scarbs.xyz/" 55 | checksum = "sha256:2993a8f6ff53488976e003261ac733f0ef3703125c449cc9861652d117dcd5ea" 56 | dependencies = [ 57 | "snforge_std", 58 | ] 59 | 60 | [[package]] 61 | name = "openzeppelin_token" 62 | version = "0.17.0" 63 | source = "registry+https://scarbs.xyz/" 64 | checksum = "sha256:77997a7e217b69674c34b402dc0c7b2210540db66a56087572679c31896eaabb" 65 | dependencies = [ 66 | "openzeppelin_account", 67 | "openzeppelin_governance", 68 | "openzeppelin_introspection", 69 | ] 70 | 71 | [[package]] 72 | name = "openzeppelin_utils" 73 | version = "0.17.0" 74 | source = "registry+https://scarbs.xyz/" 75 | checksum = "sha256:36d93e353f42fd6b824abcd8b4b51c3f5d02c893c5f886ae81403b0368aa5fde" 76 | 77 | [[package]] 78 | name = "snforge_scarb_plugin" 79 | version = "0.2.0" 80 | source = "registry+https://scarbs.xyz/" 81 | checksum = "sha256:2e4ce3ebe3f49548bd26908391b5d78537a765d827df0d96c32aeb88941d0d67" 82 | 83 | [[package]] 84 | name = "snforge_std" 85 | version = "0.30.0" 86 | source = "registry+https://scarbs.xyz/" 87 | checksum = "sha256:2f3c4846881813ac0f5d1460981249c9f5e2a6831e752beedf9b70975495b4ec" 88 | dependencies = [ 89 | "snforge_scarb_plugin", 90 | ] 91 | -------------------------------------------------------------------------------- /experimental/fractional/README.md: -------------------------------------------------------------------------------- 1 | # Fractional NFT 2 | NFT fractionalization is an implementation that enables fractional ownership of an asset (NFT) where the cost of an asset is split between multiple individuals who also shares the ownership of the asset. 3 | 4 | ## How the Smart Contract Works 5 | To achieve NFT fractionalization, we have to make use of an ERC20 token which will serve as the fractions for the NFT. Anyone that holds the ERC20 token that is attached to an NFT with a given id, automatically holds a fraction of the NFT, depending on how many ERC20 tokens they hold.
6 | 7 | With the ERC20 tokens, holders can claim a fraction of the value of the NFT after it has been sold. 8 | 9 | ### FractionalNFT Smart Contract: `src/fractional_nft.cairo` 10 | - The `FractionalNFT` contract will take in the `id` of the NFT to be fractionalized and also the NFT will be transferred into the `FractionalNFT` contract when the `initialized()` function is called.
11 | 12 | ### 13 | 14 | - The `initialized()` function takes in `nft_collection`, `accepted_purchase_token`, `token_id` and `amount` as arguments:
15 | - `nft_collection` : This is the address of the NFT smart contract to be fractionalize
16 | - `accepted_purchase_token`: The token to be accepted as payment for purchase of the NFT whose id was transferred to the smart contract.
17 | - `token_id`: This is the NFT token id of the NFT that will transferred into the contract and fractionalized.
18 | - `amount`: This is the amount of ERC20 token to be minted, which will be the fractions of the NFT whose id was passed in.
19 | 20 | ### 21 | 22 | - The `put_for_sell()` puts the NFT in the `FractionalNFT` contract for sell passing in the `price` for the NFT.
23 | 24 | - The `purchase()` function is used to purchase the NFT from the `FractionalNFT` contract at a price that was set.
25 | 26 | - The `redeem()` function is used to redeem the value after the NFT has been sold. The redeemed value sends value to the redeemer based on the amount of the FractionalNFT ERC20 token that they hold. This ERC20 token is what is used as the shares, indication how much of a fraction on the NFT a user owns. The ERC20 tokens are burnt from the redeemer's account when they redeem their shared value/reward, to prevent them from redeeming more than once with the same ERC20 tokens. 27 | 28 | ### FlexNFT Smart Contract: `src/mocks/flex_nft.cairo` 29 | The `FlexNFT` smart contract is a mock ERC721 contract implemented using Openzeppelin component. It is a representation of an NFT which will be used for testing the `FractionalNFT` contract. 30 | 31 | ### Summary 32 | For an NFT to be fractionalized, an ERC20 token is needed, to serve as the fractions of a single NFT item whose ID is given to the `FractionalNFT` smart contract. -------------------------------------------------------------------------------- /marketplace/src/mocks/erc721.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | trait IERC721 { 5 | fn mint(ref self: TContractState, recipient: ContractAddress); 6 | fn approve(ref self: TContractState, to: ContractAddress, token_id: u256); 7 | fn balance_of(self: @TContractState, account: ContractAddress) -> u256; 8 | } 9 | 10 | 11 | #[starknet::contract] 12 | mod ERC721 { 13 | use openzeppelin::token::erc721::interface::IERC721; 14 | use openzeppelin::token::erc721::erc721::ERC721Component::InternalTrait; 15 | use starknet::ContractAddress; 16 | use openzeppelin::introspection::src5::SRC5Component; 17 | use openzeppelin::token::erc721::ERC721Component; 18 | 19 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 20 | component!(path: ERC721Component, storage: erc721, event: ERC721Event); 21 | 22 | #[storage] 23 | struct Storage { 24 | id: u256, 25 | #[substorage(v0)] 26 | erc721: ERC721Component::Storage, 27 | #[substorage(v0)] 28 | src5: SRC5Component::Storage 29 | } 30 | 31 | #[event] 32 | #[derive(Drop, starknet::Event)] 33 | enum Event { 34 | #[flat] 35 | SRC5Event: SRC5Component::Event, 36 | #[flat] 37 | ERC721Event: ERC721Component::Event 38 | } 39 | 40 | #[abi(embed_v0)] 41 | impl ERC721CamelOnlyImpl = ERC721Component::ERC721CamelOnlyImpl; 42 | impl ERC721InternalImpl = ERC721Component::InternalImpl; 43 | 44 | // src5 45 | #[abi(embed_v0)] 46 | impl SRC5Impl = SRC5Component::SRC5Impl; 47 | 48 | #[constructor] 49 | fn constructor(ref self: ContractState) { 50 | let name: ByteArray = "FLEX TOKEN"; 51 | let symbol: ByteArray = "FLX"; 52 | let base_uri: ByteArray = ""; 53 | self.erc721.initializer(name, symbol, base_uri); 54 | } 55 | 56 | #[abi(embed_v0)] 57 | impl ERC721 of super::IERC721 { 58 | fn mint(ref self: ContractState, recipient: ContractAddress) { 59 | self._mint_with_uri(recipient); 60 | } 61 | 62 | fn approve(ref self: ContractState, to: ContractAddress, token_id: u256) { 63 | self.erc721._approve(to, token_id); 64 | } 65 | 66 | fn balance_of(self: @ContractState, account: ContractAddress) -> u256 { 67 | self.erc721.balance_of(account) 68 | } 69 | } 70 | 71 | #[generate_trait] 72 | impl Private of PrivateTrait { 73 | fn _mint_with_uri(ref self: ContractState, recipient: ContractAddress) { 74 | let token_id = self.id.read() + 1; 75 | self.id.write(token_id); 76 | 77 | self.erc721._mint(recipient, token_id); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /experimental/erc_5173_future_rewards/test/erc5173.test.cairo: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use super::*; 4 | use starknet::testing::contract::Contract; 5 | use starknet::testing::accounts::Account; 6 | use starknet::testing::setup; 7 | 8 | #[test] 9 | fn test_mint() { 10 | let mut contract = ERC5173::default(); 11 | let account1 = Address::from_str("0x3dB43319576aF8EC93e64239517Db69a83FB5087").unwrap(); // Replace with a valid address 12 | let token_id = 1; 13 | 14 | let result = contract.mint(account1, token_id); 15 | assert!(result.is_ok()); 16 | 17 | assert_eq!(contract.token_owners.get(&token_id), Some(&account1)); 18 | } 19 | 20 | #[test] 21 | fn test_transfer_from() { 22 | let (mut contract, account1, account2) = setup(); 23 | 24 | let erc721_address = account1.deploy_erc721(); 25 | let erc20_address = account1.deploy_erc20(); 26 | contract.new(erc721_address, erc20_address); 27 | 28 | let tokenId = 1; 29 | contract.mint(account1.address, tokenId); 30 | 31 | let sold_price = 1000; 32 | contract.transfer_from(account1.address, account2.address, tokenId, sold_price); 33 | 34 | assert_eq!(contract.token_owners.get(&tokenId), account2.address); 35 | 36 | let previous_owner_balance = contract.reward_balances.get(account1.address); 37 | assert_eq!(previous_owner_balance, sold_price); 38 | 39 | let fr_info = contract.fr_info.get(tokenId); 40 | assert_eq!(fr_info.lastSoldPrice, sold_price); 41 | } 42 | 43 | #[test] 44 | fn test_releaseFR() { 45 | let (mut contract, account1) = setup(); 46 | 47 | let erc20_address = account1.deploy_erc20(); 48 | contract.new(erc721_address, erc20_address); 49 | 50 | let account = account1.address; 51 | contract.allotted_fr.insert(account, 500); 52 | 53 | contract.releaseFR(account); 54 | 55 | let allotted_after_release = contract.allotted_fr.get(&account); 56 | assert_eq!(allotted_after_release, 0); 57 | } 58 | 59 | #[test] 60 | fn test_shiftGenerations() { 61 | let (mut contract, account1, account2) = setup(); 62 | 63 | let erc20_address = account1.deploy_erc20(); 64 | contract.new(erc721_address, erc20_address); 65 | 66 | // Add addresses to the FRInfo 67 | let tokenId = 1; 68 | contract.fr_info.insert(tokenId, FRInfo { 69 | numGenerations: 1, 70 | percentOfProfit: 100, 71 | successiveRatio: 2, 72 | lastSoldPrice: 0, 73 | ownerAmount: 1, 74 | addressesInFR: vec![account1.address, account2.address], 75 | }); 76 | 77 | contract._shiftGenerations(tokenId); 78 | 79 | let fr_info = contract.fr_info.get(tokenId); 80 | assert_eq!(fr_info.addressesInFR, vec![account2.address]); 81 | } 82 | } -------------------------------------------------------------------------------- /flex_haus/src/interface/IFlexHausCollectible.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | const IFLEX_HAUS_COLLECTIBLE_ID: felt252 = 4 | 0xd553e6f52882a90db884cfd1e898d0588b71db449f0f360404b6bb22e641c4; 5 | 6 | #[starknet::interface] 7 | trait IFlexHausCollectible { 8 | fn get_base_uri(self: @TContractState) -> ByteArray; 9 | fn total_supply(self: @TContractState) -> u256; 10 | fn set_base_uri(ref self: TContractState, base_uri: ByteArray); 11 | fn set_total_supply(ref self: TContractState, total_supply: u256); 12 | fn set_name(ref self: TContractState, name: ByteArray); 13 | fn set_symbol(ref self: TContractState, symbol: ByteArray); 14 | fn add_factory(ref self: TContractState, factory: ContractAddress); 15 | fn remove_factory(ref self: TContractState, factory: ContractAddress); 16 | fn mint_collectible(ref self: TContractState, minter: ContractAddress); 17 | } 18 | 19 | #[starknet::interface] 20 | trait IFlexHausCollectibleCamelOnly { 21 | fn getBaseUri(self: @TContractState) -> ByteArray; 22 | fn totalSupply(self: @TContractState) -> u256; 23 | fn setBaseUri(ref self: TContractState, baseUri: ByteArray); 24 | fn setTotalSupply(ref self: TContractState, totalSupply: u256); 25 | fn setName(ref self: TContractState, name: ByteArray); 26 | fn setSymbol(ref self: TContractState, symbol: ByteArray); 27 | fn addFactory(ref self: TContractState, factory: ContractAddress); 28 | fn removeFactory(ref self: TContractState, factory: ContractAddress); 29 | fn mintCollectible(ref self: TContractState, minter: ContractAddress); 30 | } 31 | 32 | #[starknet::interface] 33 | trait IFlexHausCollectibleMixin { 34 | fn get_base_uri(self: @TContractState) -> ByteArray; 35 | fn total_supply(self: @TContractState) -> u256; 36 | fn set_base_uri(ref self: TContractState, base_uri: ByteArray); 37 | fn set_total_supply(ref self: TContractState, total_supply: u256); 38 | fn set_name(ref self: TContractState, name: ByteArray); 39 | fn set_symbol(ref self: TContractState, symbol: ByteArray); 40 | fn mint_collectible(ref self: TContractState, minter: ContractAddress); 41 | fn add_factory(ref self: TContractState, factory: ContractAddress); 42 | fn remove_factory(ref self: TContractState, factory: ContractAddress); 43 | fn getBaseUri(self: @TContractState) -> ByteArray; 44 | fn totalSupply(self: @TContractState) -> u256; 45 | fn setBaseUri(ref self: TContractState, baseUri: ByteArray); 46 | fn setTotalSupply(ref self: TContractState, totalSupply: u256); 47 | fn setName(ref self: TContractState, name: ByteArray); 48 | fn setSymbol(ref self: TContractState, symbol: ByteArray); 49 | fn addFactory(ref self: TContractState, factory: ContractAddress); 50 | fn removeFactory(ref self: TContractState, factory: ContractAddress); 51 | fn mintCollectible(ref self: TContractState, minter: ContractAddress); 52 | } 53 | -------------------------------------------------------------------------------- /marketplace/src/transfer_manager_ERC1155.cairo: -------------------------------------------------------------------------------- 1 | #[starknet::contract] 2 | mod ERC1155TransferManager { 3 | use starknet::{ContractAddress, ClassHash, contract_address_const, get_caller_address}; 4 | 5 | use marketplace::interfaces::nft_transfer_manager::ITransferManagerNFT; 6 | use marketplace::{DebugContractAddress, DisplayContractAddress}; 7 | use marketplace::mocks::erc1155::{IERC1155Dispatcher, IERC1155DispatcherTrait}; 8 | 9 | use openzeppelin::access::ownable::OwnableComponent; 10 | component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); 11 | #[abi(embed_v0)] 12 | impl OwnableImpl = OwnableComponent::OwnableImpl; 13 | impl OwnableInternalImpl = OwnableComponent::InternalImpl; 14 | 15 | component!(path: UpgradeableComponent, storage: upgradable, event: UpgradeableEvent); 16 | use openzeppelin::upgrades::upgradeable::UpgradeableComponent::InternalTrait; 17 | use openzeppelin::upgrades::UpgradeableComponent; 18 | 19 | 20 | #[storage] 21 | struct Storage { 22 | marketplace: ContractAddress, 23 | #[substorage(v0)] 24 | ownable: OwnableComponent::Storage, 25 | #[substorage(v0)] 26 | upgradable: UpgradeableComponent::Storage, 27 | } 28 | 29 | #[event] 30 | #[derive(Drop, starknet::Event)] 31 | enum Event { 32 | #[flat] 33 | OwnableEvent: OwnableComponent::Event, 34 | #[flat] 35 | UpgradeableEvent: UpgradeableComponent::Event, 36 | } 37 | 38 | #[abi(embed_v0)] 39 | impl ERC1155TransferManagerImpl of ITransferManagerNFT { 40 | fn initializer( 41 | ref self: ContractState, marketplace: ContractAddress, owner: ContractAddress, 42 | ) { 43 | self.ownable.initializer(owner); 44 | self.marketplace.write(marketplace); 45 | } 46 | 47 | fn transfer_non_fungible_token( 48 | ref self: ContractState, 49 | collection: ContractAddress, 50 | from: ContractAddress, 51 | to: ContractAddress, 52 | token_id: u256, 53 | amount: u128, 54 | data: Span, 55 | ) { 56 | let caller: ContractAddress = get_caller_address(); 57 | let marketplace: ContractAddress = self.get_marketplace(); 58 | assert!( 59 | caller == marketplace, 60 | "ERC1155TransferManager: caller {} is not marketplace", 61 | caller 62 | ); 63 | IERC1155Dispatcher { contract_address: collection } 64 | .safe_transfer_from(from, to, token_id, amount, data); 65 | } 66 | 67 | fn update_marketplace(ref self: ContractState, new_address: ContractAddress) { 68 | self.ownable.assert_only_owner(); 69 | self.marketplace.write(new_address); 70 | } 71 | 72 | fn get_marketplace(self: @ContractState) -> ContractAddress { 73 | self.marketplace.read() 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /base64_nft/src/nft/nft.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | trait NftTrait { 5 | fn mint(ref self: TState, recipient: ContractAddress); 6 | } 7 | 8 | #[starknet::contract] 9 | mod Nft { 10 | use starknet::{ContractAddress, get_block_timestamp}; 11 | use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; 12 | use base64_nft::nft::erc721::{ERC721Component, ERC721HooksEmptyImpl}; 13 | use openzeppelin::access::ownable::OwnableComponent; 14 | use openzeppelin::introspection::src5::SRC5Component; 15 | use core::hash::{HashStateTrait, HashStateExTrait}; 16 | use core::pedersen::PedersenTrait; 17 | use super::NftTrait; 18 | 19 | component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); 20 | component!(path: ERC721Component, storage: erc721, event: Erc721Event); 21 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 22 | 23 | #[abi(embed_v0)] 24 | impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl; 25 | impl ERC721InternalImpl = ERC721Component::InternalImpl; 26 | 27 | #[storage] 28 | struct Storage { 29 | seed: u128, 30 | #[substorage(v0)] 31 | erc721: ERC721Component::Storage, 32 | #[substorage(v0)] 33 | ownable: OwnableComponent::Storage, 34 | #[substorage(v0)] 35 | src5: SRC5Component::Storage, 36 | } 37 | 38 | #[event] 39 | #[derive(Drop, starknet::Event)] 40 | enum Event { 41 | #[flat] 42 | OwnableEvent: OwnableComponent::Event, 43 | #[flat] 44 | Erc721Event: ERC721Component::Event, 45 | #[flat] 46 | SRC5Event: SRC5Component::Event, 47 | } 48 | 49 | #[constructor] 50 | fn constructor(ref self: ContractState, recipient: ContractAddress, render: ContractAddress) { 51 | let name = "MyNFT"; 52 | let symbol = "NFT"; 53 | 54 | let mut token_id_felt = PedersenTrait::new(0); 55 | token_id_felt = token_id_felt.update_with(0); 56 | token_id_felt = token_id_felt.update_with(get_block_timestamp()); 57 | token_id_felt = token_id_felt.update_with(recipient); 58 | let token_id: u256 = token_id_felt.finalize().into(); 59 | self.erc721.initializer(name, symbol, render); 60 | self.erc721.mint(recipient, token_id); 61 | self.seed.write(1); 62 | } 63 | 64 | #[abi(embed_v0)] 65 | impl NftImpl of NftTrait { 66 | fn mint(ref self: ContractState, recipient: ContractAddress) { 67 | let seed = self.seed.read(); 68 | let mut token_id_felt = PedersenTrait::new(0); 69 | token_id_felt = token_id_felt.update_with(seed); 70 | token_id_felt = token_id_felt.update_with(get_block_timestamp()); 71 | token_id_felt = token_id_felt.update_with(recipient); 72 | let token_id: u256 = token_id_felt.finalize().into(); 73 | self.erc721.mint(recipient, token_id); 74 | 75 | self.seed.write(seed + 1); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /experimental/erc_5006_rental_nft/src/preset.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use erc5006_cairo::types::UserRecord; 3 | 4 | #[starknet::interface] 5 | pub trait IERC5006Mixin { 6 | fn usable_balance_of(self: @TState, account: ContractAddress, token_id: u256) -> u256; 7 | 8 | fn frozen_balance_of(self: @TState, account: ContractAddress, token_id: u256) -> u256; 9 | 10 | fn user_record_of(self: @TState, record_id: u256) -> UserRecord; 11 | 12 | fn create_user_record( 13 | ref self: TState, 14 | owner: ContractAddress, 15 | user: ContractAddress, 16 | token_id: u256, 17 | amount: u64, 18 | expiry: u64 19 | ) -> u256; 20 | 21 | fn delete_user_record(ref self: TState, record_id: u256); 22 | 23 | fn balance_of(self: @TState, account: ContractAddress, token_id: u256) -> u256; 24 | fn balance_of_batch( 25 | self: @TState, accounts: Span, token_ids: Span, 26 | ) -> Span; 27 | fn safe_transfer_from( 28 | ref self: TState, 29 | from: ContractAddress, 30 | to: ContractAddress, 31 | token_id: u256, 32 | value: u256, 33 | data: Span, 34 | ); 35 | fn safe_batch_transfer_from( 36 | ref self: TState, 37 | from: ContractAddress, 38 | to: ContractAddress, 39 | token_ids: Span, 40 | values: Span, 41 | data: Span, 42 | ); 43 | fn is_approved_for_all( 44 | self: @TState, owner: ContractAddress, operator: ContractAddress, 45 | ) -> bool; 46 | fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); 47 | } 48 | 49 | #[starknet::contract] 50 | pub mod ERC5006RentalNft { 51 | use openzeppelin_introspection::src5::SRC5Component; 52 | use openzeppelin_token::erc1155::{ERC1155Component, ERC1155HooksEmptyImpl}; 53 | use erc5006_cairo::erc5006::ERC5006Component; 54 | 55 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 56 | component!(path: ERC1155Component, storage: erc1155, event: ERC1155Event); 57 | component!(path: ERC5006Component, storage: erc5006, event: ERC5006Event); 58 | 59 | #[abi(embed_v0)] 60 | impl ERC1155MixinImpl = ERC1155Component::ERC1155MixinImpl; 61 | impl ERC1155InternalImpl = ERC1155Component::InternalImpl; 62 | 63 | // ERC5006 64 | #[abi(embed_v0)] 65 | impl ERC5006Impl = ERC5006Component::ERC5006Impl; 66 | 67 | #[storage] 68 | struct Storage { 69 | #[substorage(v0)] 70 | src5: SRC5Component::Storage, 71 | #[substorage(v0)] 72 | erc1155: ERC1155Component::Storage, 73 | #[substorage(v0)] 74 | erc5006: ERC5006Component::Storage, 75 | } 76 | 77 | #[event] 78 | #[derive(Drop, starknet::Event)] 79 | enum Event { 80 | #[flat] 81 | SRC5Event: SRC5Component::Event, 82 | #[flat] 83 | ERC1155Event: ERC1155Component::Event, 84 | #[flat] 85 | ERC5006Event: ERC5006Component::Event, 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc_1523_insurance_policies" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin", 9 | "snforge_std", 10 | ] 11 | 12 | [[package]] 13 | name = "openzeppelin" 14 | version = "0.16.0" 15 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 16 | dependencies = [ 17 | "openzeppelin_access", 18 | "openzeppelin_account", 19 | "openzeppelin_governance", 20 | "openzeppelin_introspection", 21 | "openzeppelin_merkle_tree", 22 | "openzeppelin_presets", 23 | "openzeppelin_security", 24 | "openzeppelin_token", 25 | "openzeppelin_upgrades", 26 | "openzeppelin_utils", 27 | ] 28 | 29 | [[package]] 30 | name = "openzeppelin_access" 31 | version = "0.16.0" 32 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 33 | dependencies = [ 34 | "openzeppelin_introspection", 35 | "openzeppelin_utils", 36 | ] 37 | 38 | [[package]] 39 | name = "openzeppelin_account" 40 | version = "0.16.0" 41 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 42 | dependencies = [ 43 | "openzeppelin_introspection", 44 | "openzeppelin_utils", 45 | ] 46 | 47 | [[package]] 48 | name = "openzeppelin_governance" 49 | version = "0.16.0" 50 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 51 | dependencies = [ 52 | "openzeppelin_access", 53 | "openzeppelin_introspection", 54 | ] 55 | 56 | [[package]] 57 | name = "openzeppelin_introspection" 58 | version = "0.16.0" 59 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 60 | 61 | [[package]] 62 | name = "openzeppelin_merkle_tree" 63 | version = "0.16.0" 64 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 65 | 66 | [[package]] 67 | name = "openzeppelin_presets" 68 | version = "0.16.0" 69 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 70 | dependencies = [ 71 | "openzeppelin_access", 72 | "openzeppelin_account", 73 | "openzeppelin_introspection", 74 | "openzeppelin_token", 75 | "openzeppelin_upgrades", 76 | ] 77 | 78 | [[package]] 79 | name = "openzeppelin_security" 80 | version = "0.16.0" 81 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 82 | 83 | [[package]] 84 | name = "openzeppelin_token" 85 | version = "0.16.0" 86 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 87 | dependencies = [ 88 | "openzeppelin_account", 89 | "openzeppelin_governance", 90 | "openzeppelin_introspection", 91 | ] 92 | 93 | [[package]] 94 | name = "openzeppelin_upgrades" 95 | version = "0.16.0" 96 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 97 | 98 | [[package]] 99 | name = "openzeppelin_utils" 100 | version = "0.16.0" 101 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb" 102 | 103 | [[package]] 104 | name = "snforge_std" 105 | version = "0.27.0" 106 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![overview](./assets/logo.png) 2 | 3 | # Flex Contracts Monorepo 4 | 5 | ## Repository Structure 6 | 1. **`stakingpool`** 7 | Includes implementation of the staking NFT pool contracts. 8 | - **Purpose**: Stake NFTs (ERC721) to earn time-based rewards. 9 | - **Features**: 10 | - NFT staking with rewards. 11 | - Customizable reward parameters. 12 | - Secure staking and unstaking. 13 | 14 | 2. **`openedition`** 15 | Includes implementation of the marketplace contracts. 16 | - **Purpose**: Open-edition NFT minting with flexible configurations. 17 | - **Contracts**: 18 | - **ERC721OpenEditionMultiMetadata**: Handles metadata, flexible drops, and owner controls. 19 | - **ERC721OpenEdition**: StarkNet ERC-721 implementation for open-edition tokens. 20 | - **FlexDrop**: Manages minting phases and whitelist minting. 21 | 22 | 3. **`marketplace`** 23 | Includes implementation of the marketplace contracts. 24 | - **Purpose**: Manage decentralized trading, auctions, and royalty fees. 25 | - **Contracts**: 26 | - **CurrencyManager**: Whitelists accepted currencies. 27 | - **ExecutionManager**: Manages execution strategies. 28 | - **Marketplace**: Matches orders, manages fees, and secures trades. 29 | - **RoyaltyFeeManager**: Calculates and distributes royalties. 30 | - **Proxy**: Enables contract upgrades. 31 | - **RoyaltyFeeManager**:Handles NFT royalty fees using ERC-2981 standards. 32 | - **RoyaltyFeeRegistry**:enforces and manages royalty fees , allowing updates, retrieval of royalty details. 33 | - **Signature_Checkers2**:verifies digital signatures on StarkNet. 34 | - **StrategyStandardSaleForFixedPrice**:Implements fixed-price sale strategy. 35 | - **TransferManagementNFT**-Manages NFT transfers in StarkNet marketplaces. 36 | - **ERC1155TransferManager**-Manages secure ERC-1155 token transfers. 37 | - **TransferSelectorNFT**-Manages and assigns transfer managers for ERC-721/ERC-1155 tokens. 38 | 39 | 40 | ## Key Features 41 | - **NFT Staking**: Stake ERC721 tokens to earn rewards based on staking duration. 42 | - **Open-Edition Minting**: 43 | - Supports multiple metadata sets. 44 | - Flexible minting phases. 45 | - Whitelist minting. 46 | - **Marketplace**: 47 | - Auction and fixed-price sales. 48 | - Royalty management. 49 | - Secure, upgradeable contracts. 50 | 51 | 52 | 53 | 54 | ## Visual Overview 55 | ![Overview](./assets/marketplace-overview.png) 56 | 57 | ### Key Actions 58 | - **List NFTs** 59 | ![Listing](./assets/marketplace-listing.png) 60 | - **Buy NFTs** 61 | ![Buy](./assets/marketplace-buy.png) 62 | - **Make Offers** 63 | ![Make Offer](./assets/marketplace-make-offer.png) 64 | - **Accept Offers** 65 | ![Accept Offer](./assets/marketplace-accept-offer.png) 66 | 67 | 68 | 69 | ## Development Setup 70 | You will need to have Scarb and Starknet Foundry installed on your system. Refer to the documentations below: 71 | - [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/index.html) 72 | - [Scarb](https://docs.swmansion.com/scarb/download.html) 73 | To use this repository, first clone it: 74 | ``` 75 | git clone git@github.com:Flex-NFT-Marketplace/Flex-Marketplace-Contract.git 76 | ``` 77 | ### Building contracts 78 | To build the contracts, run the command: 79 | ``` 80 | scarb build 81 | ``` 82 | Note: Use scarb version `2.6.3`. 83 | ### Running Tests 84 | To run the tests contained within the `tests` folder, run the command: 85 | ``` 86 | scarb test 87 | ``` 88 | 89 | 90 | 91 | ## Notes 92 | - Ensure you use `scarb` version `2.6.3` for compatibility. -------------------------------------------------------------------------------- /flex_haus/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "flexhaus" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin", 9 | ] 10 | 11 | [[package]] 12 | name = "openzeppelin" 13 | version = "0.17.0" 14 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 15 | dependencies = [ 16 | "openzeppelin_access", 17 | "openzeppelin_account", 18 | "openzeppelin_finance", 19 | "openzeppelin_governance", 20 | "openzeppelin_introspection", 21 | "openzeppelin_merkle_tree", 22 | "openzeppelin_presets", 23 | "openzeppelin_security", 24 | "openzeppelin_token", 25 | "openzeppelin_upgrades", 26 | "openzeppelin_utils", 27 | ] 28 | 29 | [[package]] 30 | name = "openzeppelin_access" 31 | version = "0.17.0" 32 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 33 | dependencies = [ 34 | "openzeppelin_introspection", 35 | "openzeppelin_utils", 36 | ] 37 | 38 | [[package]] 39 | name = "openzeppelin_account" 40 | version = "0.17.0" 41 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 42 | dependencies = [ 43 | "openzeppelin_introspection", 44 | "openzeppelin_utils", 45 | ] 46 | 47 | [[package]] 48 | name = "openzeppelin_finance" 49 | version = "0.17.0" 50 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 51 | dependencies = [ 52 | "openzeppelin_access", 53 | "openzeppelin_token", 54 | ] 55 | 56 | [[package]] 57 | name = "openzeppelin_governance" 58 | version = "0.17.0" 59 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 60 | dependencies = [ 61 | "openzeppelin_access", 62 | "openzeppelin_introspection", 63 | ] 64 | 65 | [[package]] 66 | name = "openzeppelin_introspection" 67 | version = "0.17.0" 68 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 69 | 70 | [[package]] 71 | name = "openzeppelin_merkle_tree" 72 | version = "0.17.0" 73 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 74 | 75 | [[package]] 76 | name = "openzeppelin_presets" 77 | version = "0.17.0" 78 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 79 | dependencies = [ 80 | "openzeppelin_access", 81 | "openzeppelin_account", 82 | "openzeppelin_finance", 83 | "openzeppelin_introspection", 84 | "openzeppelin_token", 85 | "openzeppelin_upgrades", 86 | ] 87 | 88 | [[package]] 89 | name = "openzeppelin_security" 90 | version = "0.17.0" 91 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 92 | 93 | [[package]] 94 | name = "openzeppelin_token" 95 | version = "0.17.0" 96 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 97 | dependencies = [ 98 | "openzeppelin_account", 99 | "openzeppelin_governance", 100 | "openzeppelin_introspection", 101 | ] 102 | 103 | [[package]] 104 | name = "openzeppelin_upgrades" 105 | version = "0.17.0" 106 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 107 | 108 | [[package]] 109 | name = "openzeppelin_utils" 110 | version = "0.17.0" 111 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 112 | -------------------------------------------------------------------------------- /flex_haus/src/interface/IFlexHausFactory.cairo: -------------------------------------------------------------------------------- 1 | use starknet::{ContractAddress, ClassHash}; 2 | 3 | #[derive(Drop, Serde, Copy, starknet::Store)] 4 | struct DropDetail { 5 | drop_type: u8, 6 | secure_amount: u256, 7 | is_random_to_subscribers: bool, 8 | from_top_supporter: u64, 9 | to_top_supporter: u64, 10 | start_time: u64, 11 | expire_time: u64, 12 | } 13 | 14 | #[derive(Drop, Copy, Serde, PartialEq)] 15 | enum CollectibleRarity { 16 | Common, 17 | Rare, 18 | Legendary, 19 | Ultimate, 20 | } 21 | 22 | impl CollectibleRarityInto of Into { 23 | fn into(self: CollectibleRarity) -> felt252 { 24 | match self { 25 | CollectibleRarity::Common => 'common', 26 | CollectibleRarity::Rare => 'rare', 27 | CollectibleRarity::Legendary => 'legendary', 28 | CollectibleRarity::Ultimate => 'ultimate', 29 | } 30 | } 31 | } 32 | 33 | #[starknet::interface] 34 | trait IFlexHausFactory { 35 | fn create_collectible( 36 | ref self: TContractState, 37 | name: ByteArray, 38 | symbol: ByteArray, 39 | base_uri: ByteArray, 40 | total_supply: u256, 41 | rarity: felt252, 42 | ); 43 | fn create_drop( 44 | ref self: TContractState, 45 | collectible: ContractAddress, 46 | drop_type: u8, 47 | secure_amount: u256, 48 | is_random_to_subscribers: bool, 49 | from_top_supporter: u64, 50 | to_top_supporter: u64, 51 | start_time: u64, 52 | expire_time: u64, 53 | ); 54 | fn update_collectible_drop_phase( 55 | ref self: TContractState, 56 | collectible: ContractAddress, 57 | drop_type: u8, 58 | secure_amount: u256, 59 | is_random_to_subscribers: bool, 60 | from_top_supporter: u64, 61 | to_top_supporter: u64, 62 | start_time: u64, 63 | expire_time: u64, 64 | ); 65 | fn update_collectible_detail( 66 | ref self: TContractState, 67 | collectible: ContractAddress, 68 | name: ByteArray, 69 | symbol: ByteArray, 70 | base_uri: ByteArray, 71 | total_supply: u256, 72 | rarity: felt252, 73 | ); 74 | fn claim_collectible( 75 | ref self: TContractState, collectible: ContractAddress, keys: Array 76 | ); 77 | fn set_protocol_fee(ref self: TContractState, new_fee: u256); 78 | fn set_protocol_currency(ref self: TContractState, new_currency: ContractAddress); 79 | fn set_fee_recipient(ref self: TContractState, new_recipient: ContractAddress); 80 | fn set_signer(ref self: TContractState, new_signer: ContractAddress); 81 | fn set_flex_haus_collectible_class(ref self: TContractState, new_class_hash: ClassHash); 82 | fn set_min_duration_time_for_update(ref self: TContractState, new_duration: u64); 83 | fn get_collectible_drop(self: @TContractState, collectible: ContractAddress) -> DropDetail; 84 | fn get_protocol_fee(self: @TContractState) -> u256; 85 | fn get_protocol_currency(self: @TContractState) -> ContractAddress; 86 | fn get_fee_recipient(self: @TContractState) -> ContractAddress; 87 | fn get_signer(self: @TContractState) -> ContractAddress; 88 | fn get_flex_haus_collectible_class(self: @TContractState) -> ClassHash; 89 | fn get_min_duration_time_for_update(self: @TContractState) -> u64; 90 | fn get_all_collectibles_addresses(self: @TContractState) -> Array; 91 | fn get_total_collectibles_count(self: @TContractState) -> u64; 92 | fn get_collectibles_of_owner( 93 | self: @TContractState, owner: ContractAddress 94 | ) -> Array; 95 | } 96 | -------------------------------------------------------------------------------- /experimental/erc_7662_ai_agent_nft/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "erc_7662_ai_agent_nft" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin", 9 | "snforge_std", 10 | ] 11 | 12 | [[package]] 13 | name = "openzeppelin" 14 | version = "0.17.0" 15 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 16 | dependencies = [ 17 | "openzeppelin_access", 18 | "openzeppelin_account", 19 | "openzeppelin_finance", 20 | "openzeppelin_governance", 21 | "openzeppelin_introspection", 22 | "openzeppelin_merkle_tree", 23 | "openzeppelin_presets", 24 | "openzeppelin_security", 25 | "openzeppelin_token", 26 | "openzeppelin_upgrades", 27 | "openzeppelin_utils", 28 | ] 29 | 30 | [[package]] 31 | name = "openzeppelin_access" 32 | version = "0.17.0" 33 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 34 | dependencies = [ 35 | "openzeppelin_introspection", 36 | "openzeppelin_utils", 37 | ] 38 | 39 | [[package]] 40 | name = "openzeppelin_account" 41 | version = "0.17.0" 42 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 43 | dependencies = [ 44 | "openzeppelin_introspection", 45 | "openzeppelin_utils", 46 | ] 47 | 48 | [[package]] 49 | name = "openzeppelin_finance" 50 | version = "0.17.0" 51 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 52 | dependencies = [ 53 | "openzeppelin_access", 54 | "openzeppelin_token", 55 | ] 56 | 57 | [[package]] 58 | name = "openzeppelin_governance" 59 | version = "0.17.0" 60 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 61 | dependencies = [ 62 | "openzeppelin_access", 63 | "openzeppelin_introspection", 64 | ] 65 | 66 | [[package]] 67 | name = "openzeppelin_introspection" 68 | version = "0.17.0" 69 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 70 | 71 | [[package]] 72 | name = "openzeppelin_merkle_tree" 73 | version = "0.17.0" 74 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 75 | 76 | [[package]] 77 | name = "openzeppelin_presets" 78 | version = "0.17.0" 79 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 80 | dependencies = [ 81 | "openzeppelin_access", 82 | "openzeppelin_account", 83 | "openzeppelin_finance", 84 | "openzeppelin_introspection", 85 | "openzeppelin_token", 86 | "openzeppelin_upgrades", 87 | ] 88 | 89 | [[package]] 90 | name = "openzeppelin_security" 91 | version = "0.17.0" 92 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 93 | 94 | [[package]] 95 | name = "openzeppelin_token" 96 | version = "0.17.0" 97 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 98 | dependencies = [ 99 | "openzeppelin_account", 100 | "openzeppelin_governance", 101 | "openzeppelin_introspection", 102 | ] 103 | 104 | [[package]] 105 | name = "openzeppelin_upgrades" 106 | version = "0.17.0" 107 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 108 | 109 | [[package]] 110 | name = "openzeppelin_utils" 111 | version = "0.17.0" 112 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 113 | 114 | [[package]] 115 | name = "snforge_std" 116 | version = "0.27.0" 117 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" 118 | -------------------------------------------------------------------------------- /experimental/fractional/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "fractional" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin", 9 | "snforge_std", 10 | ] 11 | 12 | [[package]] 13 | name = "openzeppelin" 14 | version = "0.17.0" 15 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 16 | dependencies = [ 17 | "openzeppelin_access", 18 | "openzeppelin_account", 19 | "openzeppelin_finance", 20 | "openzeppelin_governance", 21 | "openzeppelin_introspection", 22 | "openzeppelin_merkle_tree", 23 | "openzeppelin_presets", 24 | "openzeppelin_security", 25 | "openzeppelin_token", 26 | "openzeppelin_upgrades", 27 | "openzeppelin_utils", 28 | ] 29 | 30 | [[package]] 31 | name = "openzeppelin_access" 32 | version = "0.17.0" 33 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 34 | dependencies = [ 35 | "openzeppelin_introspection", 36 | "openzeppelin_utils", 37 | ] 38 | 39 | [[package]] 40 | name = "openzeppelin_account" 41 | version = "0.17.0" 42 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 43 | dependencies = [ 44 | "openzeppelin_introspection", 45 | "openzeppelin_utils", 46 | ] 47 | 48 | [[package]] 49 | name = "openzeppelin_finance" 50 | version = "0.17.0" 51 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 52 | dependencies = [ 53 | "openzeppelin_access", 54 | "openzeppelin_token", 55 | ] 56 | 57 | [[package]] 58 | name = "openzeppelin_governance" 59 | version = "0.17.0" 60 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 61 | dependencies = [ 62 | "openzeppelin_access", 63 | "openzeppelin_introspection", 64 | ] 65 | 66 | [[package]] 67 | name = "openzeppelin_introspection" 68 | version = "0.17.0" 69 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 70 | 71 | [[package]] 72 | name = "openzeppelin_merkle_tree" 73 | version = "0.17.0" 74 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 75 | 76 | [[package]] 77 | name = "openzeppelin_presets" 78 | version = "0.17.0" 79 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 80 | dependencies = [ 81 | "openzeppelin_access", 82 | "openzeppelin_account", 83 | "openzeppelin_finance", 84 | "openzeppelin_introspection", 85 | "openzeppelin_token", 86 | "openzeppelin_upgrades", 87 | ] 88 | 89 | [[package]] 90 | name = "openzeppelin_security" 91 | version = "0.17.0" 92 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 93 | 94 | [[package]] 95 | name = "openzeppelin_token" 96 | version = "0.17.0" 97 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 98 | dependencies = [ 99 | "openzeppelin_account", 100 | "openzeppelin_governance", 101 | "openzeppelin_introspection", 102 | ] 103 | 104 | [[package]] 105 | name = "openzeppelin_upgrades" 106 | version = "0.17.0" 107 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 108 | 109 | [[package]] 110 | name = "openzeppelin_utils" 111 | version = "0.17.0" 112 | source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 113 | 114 | [[package]] 115 | name = "snforge_std" 116 | version = "0.27.0" 117 | source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.27.0#2d99b7c00678ef0363881ee0273550c44a9263de" 118 | -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/tests/test_erc1523.cairo: -------------------------------------------------------------------------------- 1 | use snforge_std::{ 2 | start_cheat_caller_address, stop_cheat_caller_address, declare, ContractClassTrait 3 | }; 4 | 5 | use openzeppelin::token::erc721::interface::{IERC721Dispatcher, IERC721DispatcherTrait}; 6 | use starknet::{ContractAddress, get_block_timestamp}; 7 | 8 | use erc_1523_insurance_policies::types::{Policy, State}; 9 | use erc_1523_insurance_policies::interfaces::{IERC1523Dispatcher, IERC1523DispatcherTrait}; 10 | 11 | fn NAME() -> ByteArray { 12 | let name: ByteArray = "name"; 13 | name 14 | } 15 | fn SYMBOL() -> ByteArray { 16 | let symbol: ByteArray = "symbol"; 17 | symbol 18 | } 19 | fn BASE_URI() -> ByteArray { 20 | let base_uri: ByteArray = "base_uri"; 21 | base_uri 22 | } 23 | 24 | fn OWNER() -> ContractAddress { 25 | 'owner'.try_into().unwrap() 26 | } 27 | 28 | fn BOB() -> ContractAddress { 29 | 'bob'.try_into().unwrap() 30 | } 31 | 32 | fn UNDERWRITER() -> ContractAddress { 33 | 'underwriter'.try_into().unwrap() 34 | } 35 | 36 | fn POLICY() -> Policy { 37 | let policy = Policy { 38 | policy_holder: OWNER(), 39 | premium: 200_000, 40 | coverage_period_start: get_block_timestamp().into(), 41 | coverage_period_end: 60, 42 | risk: "car insurance coverage", 43 | underwriter: UNDERWRITER(), 44 | metadataURI: "uri/v1", 45 | state: State::Active, 46 | }; 47 | 48 | policy 49 | } 50 | 51 | 52 | fn setup() -> IERC1523Dispatcher { 53 | let contract_class = declare("ERC1523").unwrap(); 54 | 55 | let mut calldata = array![]; 56 | NAME().serialize(ref calldata); 57 | SYMBOL().serialize(ref calldata); 58 | BASE_URI().serialize(ref calldata); 59 | 60 | let (contract_address, _) = contract_class.deploy(@calldata).unwrap(); 61 | 62 | IERC1523Dispatcher { contract_address } 63 | } 64 | 65 | #[test] 66 | fn test_create_policy() { 67 | let dispatcher = setup(); 68 | let erc721_dispatcher = IERC721Dispatcher { contract_address: dispatcher.contract_address }; 69 | 70 | let id = dispatcher.create_policy(POLICY()); 71 | 72 | assert(id == 1, 'wrong id'); 73 | assert( 74 | erc721_dispatcher.balance_of(OWNER()) == dispatcher.get_user_policy_amount(OWNER()).into(), 75 | 'wrong balance' 76 | ); 77 | } 78 | 79 | #[test] 80 | fn test_get_all_user_policies() { 81 | let dispatcher = setup(); 82 | let amount = 5; 83 | 84 | for _ in 0..amount { 85 | dispatcher.create_policy(POLICY()); 86 | }; 87 | 88 | let user_policies = dispatcher.get_all_user_policies(OWNER()); 89 | 90 | assert(user_policies.len() == amount, 'wrong amount'); 91 | } 92 | 93 | #[test] 94 | fn test_update_policy_state() { 95 | let dispatcher = setup(); 96 | 97 | let id = dispatcher.create_policy(POLICY()); 98 | 99 | dispatcher.update_policy_state(id, State::Claimed); 100 | 101 | let policy = dispatcher.get_policy(id); 102 | 103 | assert(policy.state == State::Claimed, 'wrong state'); 104 | } 105 | 106 | 107 | #[test] 108 | #[should_panic(expected: ('wrong policy holder',))] 109 | fn test_transfer_policy_with_not_owner() { 110 | let dispatcher = setup(); 111 | 112 | let id = dispatcher.create_policy(POLICY()); 113 | 114 | start_cheat_caller_address(dispatcher.contract_address, BOB()); 115 | dispatcher.transfer_policy(id, BOB()); 116 | stop_cheat_caller_address(dispatcher.contract_address); 117 | } 118 | 119 | #[test] 120 | fn test_transfer_policy() { 121 | let dispatcher = setup(); 122 | let erc721_dispatcher = IERC721Dispatcher { contract_address: dispatcher.contract_address }; 123 | 124 | let id = dispatcher.create_policy(POLICY()); 125 | 126 | start_cheat_caller_address(dispatcher.contract_address, OWNER()); 127 | dispatcher.transfer_policy(id, BOB()); 128 | stop_cheat_caller_address(dispatcher.contract_address); 129 | 130 | let policy = dispatcher.get_policy(id); 131 | 132 | assert(policy.policy_holder == BOB(), 'wrong policy holder'); 133 | assert(erc721_dispatcher.owner_of(id) == BOB(), 'wrong owner'); 134 | } 135 | -------------------------------------------------------------------------------- /experimental/erc_7765_rwa_integration/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "alexandria_storage" 6 | version = "0.2.0" 7 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.3.0-rc0#ae1d5149ff601a7ac5b39edc867d33ebd83d7f4f" 8 | 9 | [[package]] 10 | name = "erc_7765_rwa_integration" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "alexandria_storage", 14 | "openzeppelin", 15 | "snforge_std", 16 | ] 17 | 18 | [[package]] 19 | name = "openzeppelin" 20 | version = "0.17.0" 21 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 22 | dependencies = [ 23 | "openzeppelin_access", 24 | "openzeppelin_account", 25 | "openzeppelin_finance", 26 | "openzeppelin_governance", 27 | "openzeppelin_introspection", 28 | "openzeppelin_merkle_tree", 29 | "openzeppelin_presets", 30 | "openzeppelin_security", 31 | "openzeppelin_token", 32 | "openzeppelin_upgrades", 33 | "openzeppelin_utils", 34 | ] 35 | 36 | [[package]] 37 | name = "openzeppelin_access" 38 | version = "0.17.0" 39 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 40 | dependencies = [ 41 | "openzeppelin_introspection", 42 | "openzeppelin_utils", 43 | ] 44 | 45 | [[package]] 46 | name = "openzeppelin_account" 47 | version = "0.17.0" 48 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 49 | dependencies = [ 50 | "openzeppelin_introspection", 51 | "openzeppelin_utils", 52 | ] 53 | 54 | [[package]] 55 | name = "openzeppelin_finance" 56 | version = "0.17.0" 57 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 58 | dependencies = [ 59 | "openzeppelin_access", 60 | "openzeppelin_token", 61 | ] 62 | 63 | [[package]] 64 | name = "openzeppelin_governance" 65 | version = "0.17.0" 66 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 67 | dependencies = [ 68 | "openzeppelin_access", 69 | "openzeppelin_introspection", 70 | ] 71 | 72 | [[package]] 73 | name = "openzeppelin_introspection" 74 | version = "0.17.0" 75 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 76 | 77 | [[package]] 78 | name = "openzeppelin_merkle_tree" 79 | version = "0.17.0" 80 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 81 | 82 | [[package]] 83 | name = "openzeppelin_presets" 84 | version = "0.17.0" 85 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 86 | dependencies = [ 87 | "openzeppelin_access", 88 | "openzeppelin_account", 89 | "openzeppelin_finance", 90 | "openzeppelin_introspection", 91 | "openzeppelin_token", 92 | "openzeppelin_upgrades", 93 | ] 94 | 95 | [[package]] 96 | name = "openzeppelin_security" 97 | version = "0.17.0" 98 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 99 | 100 | [[package]] 101 | name = "openzeppelin_token" 102 | version = "0.17.0" 103 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 104 | dependencies = [ 105 | "openzeppelin_account", 106 | "openzeppelin_governance", 107 | "openzeppelin_introspection", 108 | ] 109 | 110 | [[package]] 111 | name = "openzeppelin_upgrades" 112 | version = "0.17.0" 113 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 114 | 115 | [[package]] 116 | name = "openzeppelin_utils" 117 | version = "0.17.0" 118 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.17.0#bf5d02c25c989ccc24f3ab42ec649617d3f21289" 119 | 120 | [[package]] 121 | name = "snforge_std" 122 | version = "0.14.0" 123 | source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.14.0#e8cbecee4e31ed428c76d5173eaa90c8df796fe3" 124 | -------------------------------------------------------------------------------- /base64_nft/src/common.cairo: -------------------------------------------------------------------------------- 1 | pub fn base64_encode(input: ByteArray) -> ByteArray { 2 | let BASE64_TABLE: Array = array![ 3 | "A", 4 | "B", 5 | "C", 6 | "D", 7 | "E", 8 | "F", 9 | "G", 10 | "H", 11 | "I", 12 | "J", 13 | "K", 14 | "L", 15 | "M", 16 | "N", 17 | "O", 18 | "P", 19 | "Q", 20 | "R", 21 | "S", 22 | "T", 23 | "U", 24 | "V", 25 | "W", 26 | "X", 27 | "Y", 28 | "Z", 29 | "a", 30 | "b", 31 | "c", 32 | "d", 33 | "e", 34 | "f", 35 | "g", 36 | "h", 37 | "i", 38 | "j", 39 | "k", 40 | "l", 41 | "m", 42 | "n", 43 | "o", 44 | "p", 45 | "q", 46 | "r", 47 | "s", 48 | "t", 49 | "u", 50 | "v", 51 | "w", 52 | "x", 53 | "y", 54 | "z", 55 | "0", 56 | "1", 57 | "2", 58 | "3", 59 | "4", 60 | "5", 61 | "6", 62 | "7", 63 | "8", 64 | "9", 65 | "+", 66 | "/", 67 | ]; 68 | let mut output: ByteArray = ""; 69 | 70 | let mut i = 0; 71 | loop { 72 | if i >= input.len() { 73 | break output.clone(); 74 | } 75 | 76 | let b0 = input.at(i).unwrap(); 77 | let b1 = if i + 1 < input.len() { 78 | input.at(i + 1).unwrap() 79 | } else { 80 | 0 81 | }; 82 | let b2 = if i + 2 < input.len() { 83 | input.at(i + 2).unwrap() 84 | } else { 85 | 0 86 | }; 87 | 88 | let triple: u32 = (left_shift(b0.into(), 16).try_into().unwrap()) 89 | | (left_shift(b1.into(), 8).try_into().unwrap()) 90 | | b2.into(); 91 | 92 | output 93 | .append(BASE64_TABLE.at(((right_shift(triple.into(), 18)) & 0x3F).try_into().unwrap())); 94 | output 95 | .append(BASE64_TABLE.at(((right_shift(triple.into(), 12)) & 0x3F).try_into().unwrap())); 96 | output 97 | .append( 98 | if i + 1 < input.len() { 99 | BASE64_TABLE.at(((right_shift(triple.into(), 6)) & 0x3F).try_into().unwrap()) 100 | } else { 101 | @"=" 102 | }, 103 | ); 104 | output 105 | .append( 106 | if i + 2 < input.len() { 107 | BASE64_TABLE.at((triple & 0x3F).into()) 108 | } else { 109 | @"=" 110 | }, 111 | ); 112 | 113 | i += 3; 114 | } 115 | } 116 | 117 | pub fn multi_div(num: u256, div: u256) -> u256 { 118 | let mut result = num; 119 | let mut index = 1; 120 | while (index < div) { 121 | result = result / 10; 122 | index += 1; 123 | }; 124 | result 125 | } 126 | 127 | pub fn left_shift(input: u256, count: u256) -> u256 { 128 | let mut index = 0; 129 | let mut result = input; 130 | loop { 131 | if index == count { 132 | break result; 133 | } 134 | result = result * 2; 135 | index += 1; 136 | } 137 | } 138 | 139 | pub fn right_shift(num: u256, shift_by: u256) -> u256 { 140 | if shift_by == 0 { 141 | return num; 142 | } 143 | 144 | let result = num / (left_shift(1, shift_by)); 145 | result 146 | } 147 | 148 | pub fn uint_to_str(num: u256) -> ByteArray { 149 | if num == 0 { 150 | return "0"; 151 | } 152 | 153 | let mut i = num.clone(); 154 | let mut j = num.clone(); 155 | let mut length = 0; 156 | while (i != 0) { 157 | length += 1; 158 | i /= 10; 159 | }; 160 | 161 | let mut result: ByteArray = ""; 162 | let mut k = length; 163 | while (k != 0) { 164 | k -= 1; 165 | let temp: u8 = (j % 10).try_into().unwrap(); 166 | 167 | result.append(@format!("{}", temp)); 168 | j = j / 10; 169 | }; 170 | 171 | return result.rev(); 172 | } 173 | -------------------------------------------------------------------------------- /base64_nft/Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "base64_nft" 6 | version = "0.1.0" 7 | dependencies = [ 8 | "openzeppelin", 9 | "snforge_std", 10 | ] 11 | 12 | [[package]] 13 | name = "openzeppelin" 14 | version = "1.0.0" 15 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 16 | dependencies = [ 17 | "openzeppelin_access", 18 | "openzeppelin_account", 19 | "openzeppelin_finance", 20 | "openzeppelin_governance", 21 | "openzeppelin_introspection", 22 | "openzeppelin_merkle_tree", 23 | "openzeppelin_presets", 24 | "openzeppelin_security", 25 | "openzeppelin_token", 26 | "openzeppelin_upgrades", 27 | "openzeppelin_utils", 28 | ] 29 | 30 | [[package]] 31 | name = "openzeppelin_access" 32 | version = "1.0.0" 33 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 34 | dependencies = [ 35 | "openzeppelin_introspection", 36 | "openzeppelin_utils", 37 | ] 38 | 39 | [[package]] 40 | name = "openzeppelin_account" 41 | version = "1.0.0" 42 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 43 | dependencies = [ 44 | "openzeppelin_introspection", 45 | "openzeppelin_utils", 46 | ] 47 | 48 | [[package]] 49 | name = "openzeppelin_finance" 50 | version = "1.0.0" 51 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 52 | dependencies = [ 53 | "openzeppelin_access", 54 | "openzeppelin_token", 55 | ] 56 | 57 | [[package]] 58 | name = "openzeppelin_governance" 59 | version = "1.0.0" 60 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 61 | dependencies = [ 62 | "openzeppelin_access", 63 | "openzeppelin_account", 64 | "openzeppelin_introspection", 65 | "openzeppelin_token", 66 | "openzeppelin_utils", 67 | ] 68 | 69 | [[package]] 70 | name = "openzeppelin_introspection" 71 | version = "1.0.0" 72 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 73 | 74 | [[package]] 75 | name = "openzeppelin_merkle_tree" 76 | version = "1.0.0" 77 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 78 | 79 | [[package]] 80 | name = "openzeppelin_presets" 81 | version = "1.0.0" 82 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 83 | dependencies = [ 84 | "openzeppelin_access", 85 | "openzeppelin_account", 86 | "openzeppelin_finance", 87 | "openzeppelin_introspection", 88 | "openzeppelin_token", 89 | "openzeppelin_upgrades", 90 | "openzeppelin_utils", 91 | ] 92 | 93 | [[package]] 94 | name = "openzeppelin_security" 95 | version = "1.0.0" 96 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 97 | 98 | [[package]] 99 | name = "openzeppelin_token" 100 | version = "1.0.0" 101 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 102 | dependencies = [ 103 | "openzeppelin_access", 104 | "openzeppelin_account", 105 | "openzeppelin_introspection", 106 | "openzeppelin_utils", 107 | ] 108 | 109 | [[package]] 110 | name = "openzeppelin_upgrades" 111 | version = "1.0.0" 112 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 113 | 114 | [[package]] 115 | name = "openzeppelin_utils" 116 | version = "1.0.0" 117 | source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v1.0.0#755ce1adbf8d89ed23fbb8daa328fcbeab7c6424" 118 | 119 | [[package]] 120 | name = "snforge_scarb_plugin" 121 | version = "0.35.0" 122 | source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.35.0#281bd6b3e84fb8d5cf2044763b04174d99457f20" 123 | 124 | [[package]] 125 | name = "snforge_std" 126 | version = "0.35.0" 127 | source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.35.0#281bd6b3e84fb8d5cf2044763b04174d99457f20" 128 | dependencies = [ 129 | "snforge_scarb_plugin", 130 | ] 131 | -------------------------------------------------------------------------------- /experimental/erc_1523_insurance_policies/README.md: -------------------------------------------------------------------------------- 1 | # ERC1523: Insurance Policy Standard for NFTs on Starknet 2 | 3 | ## About 4 | 5 | [ERC1523](https://eips.ethereum.org/EIPS/eip-1523) is a standard interface for insurance policies represented as non-fungible tokens (NFTs) on Starknet. This implementation extends ERC721 to provide functionality specific to insurance policies, enabling the creation, management, and transfer of tokenized insurance policies. 6 | 7 | ## Motivation 8 | 9 | Insurance policies as NFTs enable transparent, immutable, and transferable insurance contracts on the blockchain. This standard provides a unified interface for creating, managing, and transferring tokenized insurance policies. 10 | 11 | ## Contract Interface 12 | 13 | ### Core Functions 14 | 15 | ```cairo 16 | #[abi(embed_v0)] 17 | trait IERC1523 { 18 | fn create_policy(ref self: ContractState, policy: Policy) -> u256; 19 | fn update_policy_state(ref self: ContractState, token_id: u256, state: State); 20 | fn get_policy(self: @ContractState, token_id: u256) -> Policy; 21 | fn get_all_user_policies(self: @ContractState, user: ContractAddress) -> Array; 22 | fn get_user_policy_amount(self: @ContractState, user: ContractAddress) -> u64; 23 | fn transfer_policy(ref self: ContractState, token_id: u256, to: ContractAddress); 24 | } 25 | ``` 26 | 27 | ### Key Structures 28 | 29 | ```cairo 30 | struct Policy { 31 | policy_holder: ContractAddress, 32 | coverage_period_start: u256, 33 | coverage_period_end: u256, 34 | risk: ByteArray, 35 | underwriter: ContractAddress, 36 | metadataURI: ByteArray, 37 | state: State 38 | } 39 | ``` 40 | 41 | ## Starknet-Specific Implementation Details 42 | 43 | ### Components and Storage 44 | 45 | The implementation uses OpenZeppelin's component system: 46 | 47 | ```cairo 48 | component!(path: ERC721Component, storage: erc721, event: ERC721Event); 49 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 50 | ``` 51 | 52 | ### Storage structure: 53 | 54 | ```cairo 55 | #[storage] 56 | struct Storage { 57 | #[substorage(v0)] 58 | erc721: ERC721Component::Storage, 59 | #[substorage(v0)] 60 | src5: SRC5Component::Storage, 61 | token_count: u256, 62 | policies: Map, 63 | user_policies: Map>, 64 | } 65 | ``` 66 | 67 | ### Events 68 | 69 | The contract emits events for policy creation: 70 | 71 | ```cairo 72 | #[event] 73 | struct PolicyCreated { 74 | token_id: u256, 75 | policy_holder: ContractAddress, 76 | coverage_period_start: u256, 77 | coverage_period_end: u256, 78 | risk: ByteArray, 79 | underwriter: ContractAddress, 80 | metadataURI: ByteArray, 81 | } 82 | ``` 83 | 84 | ## Key Differences from Ethereum Implementation 85 | 86 | 1. Syntax and Type System 87 | 88 | - Uses ContractAddress instead of Ethereum's address 89 | - Utilizes Cairo's ByteArray for string data 90 | - Implements component-based architecture using OpenZeppelin's components 91 | 92 | 2. Storage Management 93 | 94 | - Uses Starknet's storage maps and vectors 95 | 96 | 3. Event System 97 | 98 | - Uses Starknet's event system with #[event] attribute 99 | - Implements flat event hierarchies for better indexing 100 | 101 | ## Usage Example 102 | 103 | ```cairo 104 | // Initialize the contract 105 | let contract = ERC1523::constructor("Insurance Policies", "INS", "base_uri"); 106 | 107 | // Create a new policy 108 | let policy = Policy { 109 | policy_holder: caller_address, 110 | coverage_period_start: start_time, 111 | coverage_period_end: end_time, 112 | risk: risk_description, 113 | underwriter: underwriter_address, 114 | metadataURI: metadata_uri, 115 | state: State::Active 116 | }; 117 | 118 | let token_id = contract.create_policy(policy); 119 | 120 | // Query user's policies 121 | let user_policies = contract.get_all_user_policies(user_address); 122 | 123 | // Transfer a policy 124 | contract.transfer_policy(token_id, new_holder_address); 125 | ``` 126 | 127 | ### ⛏️ Compile 128 | 129 | ```bash 130 | scarb build 131 | ``` 132 | 133 | ### 💄 Code style 134 | 135 | ```bash 136 | scarb fmt 137 | ``` 138 | 139 | ### 🌡️ Test 140 | 141 | ```bash 142 | scarb test 143 | ``` 144 | 145 | ## 📄 License 146 | 147 | This implementation is released under the Apache license. 148 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/src/presets/erc4907_rental_nft.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC4907RentalNft { 5 | fn mint(ref self: TState, to: ContractAddress, token_id: u256); 6 | } 7 | 8 | #[starknet::interface] 9 | pub trait IERC4907RentalNftMixin { 10 | fn mint(ref self: TState, to: ContractAddress, token_id: u256); 11 | fn setUser(ref self: TState, token_id: u256, user: ContractAddress, expires: u64); 12 | fn userOf(self: @TState, token_id: u256) -> ContractAddress; 13 | fn userExpires(self: @TState, token_id: u256) -> u64; 14 | fn balance_of(self: @TState, account: ContractAddress) -> u256; 15 | fn owner_of(self: @TState, token_id: u256) -> ContractAddress; 16 | fn safe_transfer_from( 17 | ref self: TState, 18 | from: ContractAddress, 19 | to: ContractAddress, 20 | token_id: u256, 21 | data: Span, 22 | ); 23 | fn transfer_from(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256); 24 | fn approve(ref self: TState, to: ContractAddress, token_id: u256); 25 | fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); 26 | fn get_approved(self: @TState, token_id: u256) -> ContractAddress; 27 | fn is_approved_for_all( 28 | self: @TState, owner: ContractAddress, operator: ContractAddress, 29 | ) -> bool; 30 | fn owner(self: @TState) -> ContractAddress; 31 | fn transfer_ownership(ref self: TState, new_owner: ContractAddress); 32 | fn renounce_ownership(ref self: TState); 33 | fn supports_interface(self: @TState, interface_id: felt252) -> bool; 34 | } 35 | 36 | #[starknet::contract] 37 | pub mod erc4907RentalNft { 38 | use starknet::{ContractAddress, get_caller_address}; 39 | use openzeppelin_introspection::src5::SRC5Component; 40 | use openzeppelin_access::ownable::OwnableComponent; 41 | use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; 42 | use erc_4907_rental_nft::erc4907::erc4907::ERC4907Component; 43 | 44 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 45 | component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); 46 | component!(path: ERC721Component, storage: erc721, event: ERC721Event); 47 | component!(path: ERC4907Component, storage: erc4907, event: erc4907Event); 48 | 49 | // Ownable 50 | #[abi(embed_v0)] 51 | impl OwnableImpl = OwnableComponent::OwnableImpl; 52 | impl OwnableInternalImpl = OwnableComponent::InternalImpl; 53 | 54 | // ERC721Mixin 55 | #[abi(embed_v0)] 56 | impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl; 57 | impl ERC721InternalImpl = ERC721Component::InternalImpl; 58 | 59 | // ERC4907 60 | #[abi(embed_v0)] 61 | impl erc4907Impl = ERC4907Component::ERC4907Impl; 62 | impl erc4907InternalImpl = ERC4907Component::InternalImpl; 63 | 64 | #[storage] 65 | struct Storage { 66 | #[substorage(v0)] 67 | src5: SRC5Component::Storage, 68 | #[substorage(v0)] 69 | ownable: OwnableComponent::Storage, 70 | #[substorage(v0)] 71 | erc721: ERC721Component::Storage, 72 | #[substorage(v0)] 73 | erc4907: ERC4907Component::Storage, 74 | } 75 | 76 | #[event] 77 | #[derive(Drop, starknet::Event)] 78 | enum Event { 79 | #[flat] 80 | SRC5Event: SRC5Component::Event, 81 | #[flat] 82 | OwnableEvent: OwnableComponent::Event, 83 | #[flat] 84 | ERC721Event: ERC721Component::Event, 85 | #[flat] 86 | erc4907Event: ERC4907Component::Event, 87 | } 88 | 89 | #[constructor] 90 | fn constructor( 91 | ref self: ContractState, name: ByteArray, symbol: ByteArray, base_uri: ByteArray, 92 | ) { 93 | self.ownable.initializer(get_caller_address()); 94 | self.erc721.initializer(name, symbol, base_uri); 95 | self.erc4907.initializer(); 96 | } 97 | 98 | #[abi(embed_v0)] 99 | impl erc4907RentalNftImpl of super::IERC4907RentalNft { 100 | fn mint(ref self: ContractState, to: ContractAddress, token_id: u256) { 101 | self.ownable.assert_only_owner(); 102 | self.erc721.mint(to, token_id); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /experimental/erc_4907_rental_nft/tests/test_contract.cairo: -------------------------------------------------------------------------------- 1 | use snforge_std::{ 2 | start_cheat_caller_address, start_cheat_block_timestamp, spy_events, EventSpyAssertionsTrait, 3 | }; 4 | use openzeppelin_testing::constants::{OWNER, OTHER, TOKEN_ID}; 5 | use erc_4907_rental_nft::erc4907::interface::IERC4907_ID; 6 | use erc_4907_rental_nft::erc4907::erc4907::ERC4907Component; 7 | use erc_4907_rental_nft::presets::erc4907_rental_nft::IERC4907RentalNftMixinDispatcherTrait; 8 | use core::num::traits::Zero; 9 | use starknet::contract_address_const; 10 | use super::utils::ERC4907TestTrait; 11 | 12 | #[test] 13 | fn test_support_intefrace_id() { 14 | let erc4907_test = ERC4907TestTrait::setup(); 15 | 16 | assert!(erc4907_test.erc4907_rental_nft.supports_interface(IERC4907_ID)); 17 | } 18 | 19 | #[test] 20 | fn test_set_user() { 21 | let erc4907_test = ERC4907TestTrait::setup(); 22 | let mut spy = spy_events(); 23 | start_cheat_block_timestamp(erc4907_test.erc4907_rental_nft_address, 1000); 24 | start_cheat_caller_address(erc4907_test.erc4907_rental_nft_address, OWNER()); 25 | let alice = OTHER(); 26 | erc4907_test.erc4907_rental_nft.setUser(TOKEN_ID, alice, 2000); 27 | 28 | spy 29 | .assert_emitted( 30 | @array![ 31 | ( 32 | erc4907_test.erc4907_rental_nft_address, 33 | ERC4907Component::Event::UpdateUser( 34 | ERC4907Component::UpdateUser { 35 | tokenId: TOKEN_ID, user: alice, expires: 2000, 36 | }, 37 | ), 38 | ), 39 | ], 40 | ) 41 | } 42 | 43 | #[test] 44 | fn test_user_of() { 45 | let erc4907_test = ERC4907TestTrait::setup(); 46 | start_cheat_caller_address(erc4907_test.erc4907_rental_nft_address, OWNER()); 47 | start_cheat_block_timestamp(erc4907_test.erc4907_rental_nft_address, 1000); 48 | let alice = OTHER(); 49 | let expires = 2000; 50 | erc4907_test.erc4907_rental_nft.setUser(TOKEN_ID, alice, expires); 51 | 52 | let actual_user = erc4907_test.erc4907_rental_nft.userOf(TOKEN_ID); 53 | 54 | assert_eq!(alice, actual_user); 55 | } 56 | 57 | #[test] 58 | fn test_not_zero_address() { 59 | let erc4907_test = ERC4907TestTrait::setup(); 60 | start_cheat_caller_address(erc4907_test.erc4907_rental_nft_address, OWNER()); 61 | start_cheat_block_timestamp(erc4907_test.erc4907_rental_nft_address, 1000); 62 | let alice = OTHER(); 63 | let expires = 2000; 64 | let invalid_user = Zero::zero(); 65 | erc4907_test.erc4907_rental_nft.setUser(TOKEN_ID, alice, expires); 66 | 67 | let actual_user = erc4907_test.erc4907_rental_nft.userOf(TOKEN_ID); 68 | 69 | assert_ne!(invalid_user, actual_user); 70 | } 71 | 72 | #[test] 73 | fn test_invalid_user_of() { 74 | let erc4907_test = ERC4907TestTrait::setup(); 75 | start_cheat_caller_address(erc4907_test.erc4907_rental_nft_address, OWNER()); 76 | start_cheat_block_timestamp(erc4907_test.erc4907_rental_nft_address, 1000); 77 | let alice = OTHER(); 78 | let invalid_user = contract_address_const::<'INVALID'>(); 79 | let expires = 2000; 80 | erc4907_test.erc4907_rental_nft.setUser(TOKEN_ID, alice, expires); 81 | 82 | let actual_user = erc4907_test.erc4907_rental_nft.userOf(TOKEN_ID); 83 | 84 | assert_ne!(invalid_user, actual_user); 85 | } 86 | 87 | #[test] 88 | fn test_user_expires() { 89 | let erc4907_test = ERC4907TestTrait::setup(); 90 | start_cheat_block_timestamp(erc4907_test.erc4907_rental_nft_address, 1000); 91 | let alice = OTHER(); 92 | let expires = 2000; 93 | start_cheat_caller_address(erc4907_test.erc4907_rental_nft_address, OWNER()); 94 | erc4907_test.erc4907_rental_nft.setUser(TOKEN_ID, alice, expires); 95 | 96 | let actual_expires = erc4907_test.erc4907_rental_nft.userExpires(TOKEN_ID); 97 | 98 | assert_eq!(expires, actual_expires); 99 | } 100 | 101 | #[test] 102 | fn test_invalid_user_expires() { 103 | let erc4907_test = ERC4907TestTrait::setup(); 104 | start_cheat_block_timestamp(erc4907_test.erc4907_rental_nft_address, 1000); 105 | let alice = OTHER(); 106 | let expires = 2000; 107 | start_cheat_caller_address(erc4907_test.erc4907_rental_nft_address, OWNER()); 108 | erc4907_test.erc4907_rental_nft.setUser(TOKEN_ID, alice, expires); 109 | 110 | let actual_expires = erc4907_test.erc4907_rental_nft.userExpires(TOKEN_ID); 111 | 112 | assert_ne!(expires - 1, actual_expires); 113 | } 114 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/src/presets/erc5643_subscription_nft.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | pub trait IERC5643SubscriptionNft { 5 | fn mint(ref self: TState, to: ContractAddress, token_id: u256); 6 | } 7 | 8 | #[starknet::interface] 9 | pub trait IERC5643SubscriptionNftMixin { 10 | // IERC5643SubscriptionNft 11 | fn mint(ref self: TState, to: ContractAddress, token_id: u256); 12 | // IERC5643 13 | fn renew_subscription(ref self: TState, token_id: u256, duration: u64); 14 | fn cancel_subscription(ref self: TState, token_id: u256); 15 | fn expires_at(self: @TState, token_id: u256) -> u64; 16 | fn is_renewable(self: @TState, token_id: u256) -> bool; 17 | // IERC721 18 | fn balance_of(self: @TState, account: ContractAddress) -> u256; 19 | fn owner_of(self: @TState, token_id: u256) -> ContractAddress; 20 | fn safe_transfer_from( 21 | ref self: TState, 22 | from: ContractAddress, 23 | to: ContractAddress, 24 | token_id: u256, 25 | data: Span 26 | ); 27 | fn transfer_from(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256); 28 | fn approve(ref self: TState, to: ContractAddress, token_id: u256); 29 | fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); 30 | fn get_approved(self: @TState, token_id: u256) -> ContractAddress; 31 | fn is_approved_for_all( 32 | self: @TState, owner: ContractAddress, operator: ContractAddress 33 | ) -> bool; 34 | // Ownable 35 | fn owner(self: @TState) -> ContractAddress; 36 | fn transfer_ownership(ref self: TState, new_owner: ContractAddress); 37 | fn renounce_ownership(ref self: TState); 38 | // ISRC5 39 | fn supports_interface(self: @TState, interface_id: felt252) -> bool; 40 | } 41 | 42 | #[starknet::contract] 43 | pub mod ERC5643SubscriptionNft { 44 | use starknet::{ContractAddress, get_caller_address}; 45 | use openzeppelin_introspection::src5::SRC5Component; 46 | use openzeppelin_access::ownable::OwnableComponent; 47 | use openzeppelin_token::erc721::{ERC721Component, ERC721HooksEmptyImpl}; 48 | use erc_5643_subscription_nft::erc5643::erc5643::ERC5643Component; 49 | 50 | component!(path: SRC5Component, storage: src5, event: SRC5Event); 51 | component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); 52 | component!(path: ERC721Component, storage: erc721, event: ERC721Event); 53 | component!(path: ERC5643Component, storage: erc5643, event: ERC5643Event); 54 | 55 | // Ownable 56 | #[abi(embed_v0)] 57 | impl OwnableImpl = OwnableComponent::OwnableImpl; 58 | impl OwnableInternalImpl = OwnableComponent::InternalImpl; 59 | 60 | // ERC721Mixin 61 | #[abi(embed_v0)] 62 | impl ERC721MixinImpl = ERC721Component::ERC721MixinImpl; 63 | impl ERC721InternalImpl = ERC721Component::InternalImpl; 64 | 65 | // ERC5643 66 | #[abi(embed_v0)] 67 | impl ERC5643Impl = ERC5643Component::ERC5643Impl; 68 | impl ERC5643InternalImpl = ERC5643Component::InternalImpl; 69 | 70 | #[storage] 71 | struct Storage { 72 | #[substorage(v0)] 73 | src5: SRC5Component::Storage, 74 | #[substorage(v0)] 75 | ownable: OwnableComponent::Storage, 76 | #[substorage(v0)] 77 | erc721: ERC721Component::Storage, 78 | #[substorage(v0)] 79 | erc5643: ERC5643Component::Storage, 80 | } 81 | 82 | #[event] 83 | #[derive(Drop, starknet::Event)] 84 | enum Event { 85 | #[flat] 86 | SRC5Event: SRC5Component::Event, 87 | #[flat] 88 | OwnableEvent: OwnableComponent::Event, 89 | #[flat] 90 | ERC721Event: ERC721Component::Event, 91 | #[flat] 92 | ERC5643Event: ERC5643Component::Event, 93 | } 94 | 95 | #[constructor] 96 | fn constructor( 97 | ref self: ContractState, name: ByteArray, symbol: ByteArray, base_uri: ByteArray 98 | ) { 99 | self.ownable.initializer(get_caller_address()); 100 | self.erc721.initializer(name, symbol, base_uri); 101 | self.erc5643.initializer(); 102 | } 103 | 104 | #[abi(embed_v0)] 105 | impl ERC5643SubscriptionNftImpl of super::IERC5643SubscriptionNft { 106 | fn mint(ref self: ContractState, to: ContractAddress, token_id: u256) { 107 | self.ownable.assert_only_owner(); 108 | self.erc721.mint(to, token_id); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /experimental/erc_5643_subscription_nft/tests/erc5643.cairo: -------------------------------------------------------------------------------- 1 | use core::panic_with_felt252; 2 | use snforge_std::{ 3 | start_cheat_caller_address, start_cheat_block_timestamp, spy_events, EventSpyAssertionsTrait 4 | }; 5 | use openzeppelin_testing::constants::{OWNER, TOKEN_ID, FAILURE}; 6 | use openzeppelin_token::erc721::ERC721Component; 7 | use erc_5643_subscription_nft::erc5643::interface::IERC5643_ID; 8 | use erc_5643_subscription_nft::erc5643::erc5643::ERC5643Component; 9 | use erc_5643_subscription_nft::presets::erc5643_subscription_nft::{ 10 | IERC5643SubscriptionNftMixinDispatcherTrait, IERC5643SubscriptionNftMixinSafeDispatcherTrait 11 | }; 12 | use super::utils::ERC5643TestTrait; 13 | 14 | #[test] 15 | fn test_supports_interface_id() { 16 | let erc5643_test = ERC5643TestTrait::setup(); 17 | assert_eq!(erc5643_test.erc5643_subscription_nft.supports_interface(IERC5643_ID), true); 18 | } 19 | 20 | #[test] 21 | fn test_renewal_valid() { 22 | let erc5643_test = ERC5643TestTrait::setup(); 23 | start_cheat_block_timestamp(erc5643_test.erc5643_subscription_nft_address, 1000); 24 | start_cheat_caller_address(erc5643_test.erc5643_subscription_nft_address, OWNER()); 25 | let mut spy = spy_events(); 26 | erc5643_test.erc5643_subscription_nft.renew_subscription(TOKEN_ID, 2000); 27 | spy 28 | .assert_emitted( 29 | @array![ 30 | ( 31 | erc5643_test.erc5643_subscription_nft_address, 32 | ERC5643Component::Event::SubscriptionUpdate( 33 | ERC5643Component::SubscriptionUpdate { 34 | token_id: TOKEN_ID, expiration: 3000, 35 | } 36 | ) 37 | ) 38 | ] 39 | ); 40 | } 41 | 42 | #[test] 43 | fn test_renewal_not_owner() { 44 | let erc5643_test = ERC5643TestTrait::setup(); 45 | match erc5643_test.erc5643_subscription_nft_safe.renew_subscription(TOKEN_ID, 2000) { 46 | Result::Ok(_) => panic_with_felt252(FAILURE), 47 | Result::Err(panic_data) => { 48 | assert_eq!(*panic_data.at(0), ERC721Component::Errors::UNAUTHORIZED); 49 | } 50 | } 51 | } 52 | 53 | #[test] 54 | fn test_cancel_valid() { 55 | let erc5643_test = ERC5643TestTrait::setup(); 56 | start_cheat_caller_address(erc5643_test.erc5643_subscription_nft_address, OWNER()); 57 | let mut spy = spy_events(); 58 | erc5643_test.erc5643_subscription_nft.cancel_subscription(TOKEN_ID); 59 | spy 60 | .assert_emitted( 61 | @array![ 62 | ( 63 | erc5643_test.erc5643_subscription_nft_address, 64 | ERC5643Component::Event::SubscriptionUpdate( 65 | ERC5643Component::SubscriptionUpdate { token_id: TOKEN_ID, expiration: 0, } 66 | ) 67 | ) 68 | ] 69 | ); 70 | } 71 | 72 | #[test] 73 | fn test_cancel_not_owner() { 74 | let erc5643_test = ERC5643TestTrait::setup(); 75 | match erc5643_test.erc5643_subscription_nft_safe.cancel_subscription(TOKEN_ID) { 76 | Result::Ok(_) => panic_with_felt252(FAILURE), 77 | Result::Err(panic_data) => { 78 | assert_eq!(*panic_data.at(0), ERC721Component::Errors::UNAUTHORIZED); 79 | } 80 | } 81 | } 82 | 83 | #[test] 84 | fn test_expires_at() { 85 | let erc5643_test = ERC5643TestTrait::setup(); 86 | start_cheat_block_timestamp(erc5643_test.erc5643_subscription_nft_address, 1000); 87 | assert_eq!(erc5643_test.erc5643_subscription_nft.expires_at(TOKEN_ID), 0); 88 | start_cheat_caller_address(erc5643_test.erc5643_subscription_nft_address, OWNER()); 89 | erc5643_test.erc5643_subscription_nft.renew_subscription(TOKEN_ID, 2000); 90 | assert_eq!(erc5643_test.erc5643_subscription_nft.expires_at(TOKEN_ID), 3000); 91 | erc5643_test.erc5643_subscription_nft.cancel_subscription(TOKEN_ID); 92 | assert_eq!(erc5643_test.erc5643_subscription_nft.expires_at(TOKEN_ID), 0); 93 | } 94 | 95 | #[test] 96 | fn test_expired_subscription() { 97 | let erc5643_test = ERC5643TestTrait::setup(); 98 | start_cheat_block_timestamp(erc5643_test.erc5643_subscription_nft_address, 1000); 99 | start_cheat_caller_address(erc5643_test.erc5643_subscription_nft_address, OWNER()); 100 | erc5643_test.erc5643_subscription_nft.renew_subscription(TOKEN_ID, 2000); 101 | start_cheat_block_timestamp(erc5643_test.erc5643_subscription_nft_address, 4000); 102 | erc5643_test.erc5643_subscription_nft.renew_subscription(TOKEN_ID, 2000); 103 | assert_eq!(erc5643_test.erc5643_subscription_nft.expires_at(TOKEN_ID), 6000); 104 | } 105 | -------------------------------------------------------------------------------- /marketplace/src/execution_manager.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | trait IExecutionManager { 5 | fn initializer(ref self: TState, owner: ContractAddress); 6 | fn add_strategy(ref self: TState, strategy: ContractAddress); 7 | fn remove_strategy(ref self: TState, strategy: ContractAddress); 8 | fn is_strategy_whitelisted(self: @TState, strategy: ContractAddress) -> bool; 9 | fn get_whitelisted_strategies_count(self: @TState) -> usize; 10 | fn get_whitelisted_strategy(self: @TState, index: usize) -> ContractAddress; 11 | } 12 | 13 | #[starknet::contract] 14 | mod ExecutionManager { 15 | use starknet::{ContractAddress, contract_address_const, get_block_timestamp}; 16 | 17 | use marketplace::{DebugContractAddress, DisplayContractAddress}; 18 | 19 | use openzeppelin::access::ownable::OwnableComponent; 20 | component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); 21 | 22 | #[abi(embed_v0)] 23 | impl OwnableImpl = OwnableComponent::OwnableImpl; 24 | 25 | impl OwnableInternalImpl = OwnableComponent::InternalImpl; 26 | 27 | #[storage] 28 | struct Storage { 29 | initialized: bool, 30 | whitelisted_strategies_count: usize, 31 | whitelisted_strategies: LegacyMap::, 32 | whitelisted_strategies_index: LegacyMap::, 33 | #[substorage(v0)] 34 | ownable: OwnableComponent::Storage 35 | } 36 | 37 | #[event] 38 | #[derive(Drop, starknet::Event)] 39 | enum Event { 40 | StrategyRemoved: StrategyRemoved, 41 | StrategyWhitelisted: StrategyWhitelisted, 42 | OwnableEvent: OwnableComponent::Event, 43 | } 44 | 45 | #[derive(Drop, starknet::Event)] 46 | struct StrategyRemoved { 47 | strategy: ContractAddress, 48 | timestamp: u64 49 | } 50 | 51 | #[derive(Drop, starknet::Event)] 52 | struct StrategyWhitelisted { 53 | strategy: ContractAddress, 54 | timestamp: u64 55 | } 56 | 57 | #[abi(embed_v0)] 58 | impl ExecutionManagerImpl of super::IExecutionManager { 59 | fn initializer(ref self: ContractState, owner: ContractAddress) { 60 | assert!(!self.initialized.read(), "ExecutionManager: already initialized"); 61 | self.initialized.write(true); 62 | self.ownable.initializer(owner) 63 | } 64 | 65 | fn add_strategy(ref self: ContractState, strategy: ContractAddress) { 66 | self.ownable.assert_only_owner(); 67 | assert!( 68 | self.whitelisted_strategies_index.read(strategy).is_zero(), 69 | "ExecutionManager: strategy {} already whitelisted", 70 | strategy 71 | ); 72 | let new_index = self.whitelisted_strategies_count.read() + 1; 73 | self.whitelisted_strategies.write(new_index, strategy); 74 | self.whitelisted_strategies_index.write(strategy, new_index); 75 | self.whitelisted_strategies_count.write(new_index); 76 | 77 | self.emit(StrategyWhitelisted { strategy, timestamp: get_block_timestamp() }); 78 | } 79 | 80 | fn remove_strategy(ref self: ContractState, strategy: ContractAddress) { 81 | self.ownable.assert_only_owner(); 82 | let index = self.whitelisted_strategies_index.read(strategy); 83 | assert!(!index.is_zero(), "ExecutionManager: strategy {} not whitelisted", strategy); 84 | let count = self.whitelisted_strategies_count.read(); 85 | 86 | let strategy_at_last_index = self.whitelisted_strategies.read(count); 87 | self.whitelisted_strategies.write(index, strategy_at_last_index); 88 | self.whitelisted_strategies.write(count, contract_address_const::<0>()); 89 | self.whitelisted_strategies_index.write(strategy, 0); 90 | self.whitelisted_strategies_count.write(count - 1); 91 | 92 | self.emit(StrategyRemoved { strategy, timestamp: get_block_timestamp() }); 93 | } 94 | 95 | fn is_strategy_whitelisted(self: @ContractState, strategy: ContractAddress) -> bool { 96 | !self.whitelisted_strategies_index.read(strategy).is_zero() 97 | } 98 | 99 | fn get_whitelisted_strategies_count(self: @ContractState) -> usize { 100 | self.whitelisted_strategies_count.read() 101 | } 102 | 103 | fn get_whitelisted_strategy(self: @ContractState, index: usize) -> ContractAddress { 104 | self.whitelisted_strategies.read(index) 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /marketplace/src/strategy_standard_sale_for_fixed_price.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use starknet::class_hash::ClassHash; 3 | use marketplace::utils::order_types::{TakerOrder, MakerOrder}; 4 | 5 | #[starknet::interface] 6 | trait IStrategyStandardSaleForFixedPrice { 7 | fn initializer(ref self: TState, fee: u128, owner: ContractAddress); 8 | fn update_protocol_fee(ref self: TState, fee: u128); 9 | fn protocol_fee(self: @TState) -> u128; 10 | fn can_execute_taker_ask( 11 | self: @TState, taker_ask: TakerOrder, maker_bid: MakerOrder, extra_params: Span 12 | ) -> (bool, u256, u128); 13 | fn can_execute_taker_bid( 14 | self: @TState, taker_bid: TakerOrder, maker_ask: MakerOrder 15 | ) -> (bool, u256, u128); 16 | fn upgrade(ref self: TState, impl_hash: ClassHash); 17 | } 18 | 19 | #[starknet::contract] 20 | mod StrategyStandardSaleForFixedPrice { 21 | use starknet::{ContractAddress, contract_address_const}; 22 | use starknet::class_hash::ClassHash; 23 | use starknet::get_block_timestamp; 24 | use openzeppelin::upgrades::upgradeable::UpgradeableComponent::InternalTrait; 25 | use openzeppelin::upgrades::UpgradeableComponent; 26 | use openzeppelin::access::ownable::OwnableComponent; 27 | component!(path: OwnableComponent, storage: ownable, event: OwnableEvent); 28 | component!(path: UpgradeableComponent, storage: upgradable, event: UpgradeableEvent); 29 | 30 | #[abi(embed_v0)] 31 | impl OwnableImpl = OwnableComponent::OwnableImpl; 32 | 33 | impl OwnableInternalImpl = OwnableComponent::InternalImpl; 34 | 35 | use marketplace::utils::order_types::{TakerOrder, MakerOrder}; 36 | 37 | #[storage] 38 | struct Storage { 39 | protocol_fee: u128, 40 | #[substorage(v0)] 41 | ownable: OwnableComponent::Storage, 42 | #[substorage(v0)] 43 | upgradable: UpgradeableComponent::Storage, 44 | } 45 | 46 | #[event] 47 | #[derive(Drop, starknet::Event)] 48 | enum Event { 49 | #[flat] 50 | OwnableEvent: OwnableComponent::Event, 51 | #[flat] 52 | UpgradeableEvent: UpgradeableComponent::Event, 53 | } 54 | 55 | #[abi(embed_v0)] 56 | impl StrategyStandardSaleForFixedPriceImpl of super::IStrategyStandardSaleForFixedPrice< 57 | ContractState 58 | > { 59 | fn initializer(ref self: ContractState, fee: u128, owner: ContractAddress) { 60 | self.ownable.initializer(owner); 61 | self.protocol_fee.write(fee); 62 | } 63 | 64 | fn update_protocol_fee(ref self: ContractState, fee: u128) { 65 | self.ownable.assert_only_owner(); 66 | self.protocol_fee.write(fee); 67 | } 68 | 69 | fn protocol_fee(self: @ContractState) -> u128 { 70 | self.protocol_fee.read() 71 | } 72 | 73 | fn can_execute_taker_ask( 74 | self: @ContractState, 75 | taker_ask: TakerOrder, 76 | maker_bid: MakerOrder, 77 | extra_params: Span 78 | ) -> (bool, u256, u128) { 79 | let price_match: bool = maker_bid.price == taker_ask.price; 80 | let token_id_match: bool = maker_bid.token_id == taker_ask.token_id; 81 | let start_time_valid: bool = maker_bid.start_time < get_block_timestamp(); 82 | let end_time_valid: bool = maker_bid.end_time > get_block_timestamp(); 83 | if (price_match && token_id_match && start_time_valid && end_time_valid) { 84 | return (true, maker_bid.token_id, maker_bid.amount); 85 | } else { 86 | return (false, maker_bid.token_id, maker_bid.amount); 87 | } 88 | } 89 | fn can_execute_taker_bid( 90 | self: @ContractState, taker_bid: TakerOrder, maker_ask: MakerOrder 91 | ) -> (bool, u256, u128) { 92 | let price_match: bool = maker_ask.price == taker_bid.price; 93 | let token_id_match: bool = maker_ask.token_id == taker_bid.token_id; 94 | let start_time_valid: bool = maker_ask.start_time < get_block_timestamp(); 95 | let end_time_valid: bool = maker_ask.end_time > get_block_timestamp(); 96 | if (price_match && token_id_match && start_time_valid && end_time_valid) { 97 | return (true, maker_ask.token_id, maker_ask.amount); 98 | } else { 99 | return (false, maker_ask.token_id, maker_ask.amount); 100 | } 101 | } 102 | 103 | fn upgrade(ref self: ContractState, impl_hash: ClassHash) { 104 | self.ownable.assert_only_owner(); 105 | self.upgradable._upgrade(impl_hash); 106 | } 107 | } 108 | } 109 | --------------------------------------------------------------------------------