This repository contains three interrelated smart contracts that collectively manage tokenized shares of a fund, facilitating minting, redemption, and permission control:
lib.cairo
: An ERC-20 token contract representing shares in a fund.redemption.cairo
: Manages the redemption process for users selling their shares back to the fund.permission_manager.cairo
: Handles role-based access control across the contracts, using roles defined inroles.cairo
.
Purpose: Implements an ERC-20 token that symbolizes ownership shares in a fund.
Key Features:
- Minting Tokens: Tokens are minted to whitelisted users when they purchase shares.
- Transfer Restrictions: Enforces transfer limitations to comply with regulatory requirements, allowing transfers only between whitelisted addresses.
- Redemption Initiation: Provides a
redeem
function enabling users to initiate the redemption process by transferring tokens to theredemption.cairo
contract. - Role Management: Integrates with the
permission_manager.cairo
contract to verify roles likeMINTER
,BURNER
, andPAUSER
.
Purpose: Oversees the redemption of tokens when users wish to sell their fund shares back.
Workflow:
-
Initiation:
- Users call the
redeem
function inlib.cairo
, transferring their tokens to theredemption.cairo
contract. - The
redemption.cairo
contract logs the redemption request and sets its status toPending
.
- Users call the
-
Execution or Cancellation:
- An authorized external operator with the
REDEMPTION_EXECUTOR_ROLE
can:- Execute Redemption: Burns the tokens held in the
redemption.cairo
contract, finalizing the redemption. - Cancel Redemption: Transfers the tokens back to the user, canceling the redemption.
- Execute Redemption: Burns the tokens held in the
- An authorized external operator with the
Security Measures:
- Status Verification: Each redemption request has a
status (
Pending
,Executed
, orCanceled
) to prevent duplicate processing. - Unique Identifiers: Redemptions are tracked using unique hashes derived from redemption data to avoid collisions.
- Role Enforcement: Only operators with specific roles can execute or cancel redemptions.
Purpose: Manages roles and permissions across the token and redemption contracts.
Functionality:
- Role Definitions: Establishes roles such as
MINTER
,BURNER
,WHITELISTER
,WHITELISTED
,REDEMPTION_EXECUTOR
, andPAUSER
. - Role Assignment: Allows the contract owner or designated administrators to grant or revoke roles to addresses.
- Access Control: Enforces role-based permissions, ensuring that only authorized addresses can perform sensitive operations.
Integration:
- Both
lib.cairo
andredemption.cairo
consult thepermission_manager.cairo
contract to verify permissions before executing critical functions.
MINTER_ROLE
: Permission to mint new tokens.BURNER_ROLE
: Permission to burn tokens.WHITELISTER_ROLE
: Can assign theWHITELISTED_ROLE
to addresses.WHITELISTED_ROLE
: Allows an address to hold and transfer tokens.REDEMPTION_EXECUTOR_ROLE
: Authorized to execute or cancel redemptions.PAUSER_ROLE
: Can pause or unpause token transfers.
Install Scarb (NOTE: it is recommended to install Scarb with the asdf version manager:
scarb build
Install Starknet Foundry.
Build the contracts, then run:
snforge test
To generate a test coverage .lcov
file ,
install cairo-coverage
then run:
snforge test --coverage
To deploy contracts locally, you can use Starknet Devnet, which will also provide pre-funded account contract credentials to declare and deploy the smart contracts.
First, setup
sncast
by creating a local snfoundry.toml
file.
Then, declare each contract as follows:
sncast --profile <YOUR_SNFOUNDRY_PROFILE> declare --package starknet_contracts
--contract-name <CONTRACT_NAME> --fee-token strk
Once a contract is declared, use its class hash to deploy the contract:
sncast --profile <YOUR_SNFOUNDRY_PROFILE> deploy --class-hash <CONTRACT_CLASS_HASH>
--fee-token strk --constructor-calldata <CONSTRUCTOR_CALLDATA>
Constructor data needs to be serialized as explained in the Starknet Docs.
For example, the
(0x34ba56f92265f0868c57d3fe72ecab144fc96f97954bbbc4252cef8e8a979ba, Token, TK, 5)
parameters with type (ContractAddress, ByteArray, ByteArray, u8)
would be serialized as:
0x34ba56f92265f0868c57d3fe72ecab144fc96f97954bbbc4252cef8e8a979ba 0x0 0x546f6b656e 0x5 0x0 0x544b 0x2 0x5
.
The converter from Stark-utils might come in handy.
The functions exposed by the contract can be interacted with as follows - with the calldata serialization built in the same way as above:
sncast --profile account1 invoke --contract-address <CONTRACT_ADDRESS>
--function "<FUNCTION_NAME>" --calldata <FUNCTION_CALLDATA> --fee-token strk