Aptos Move smart contracts for the Summon ecosystem
This repository contains Aptos Move smart contracts for the Summon ecosystem, providing a comprehensive reward distribution system with treasury management, role-based access control, and secure signature verification.
- Dual Reward Types: Support for both Fungible Assets (FA) and NFTs (Token Objects) in a single reward.
- Flexible Distribution: Rewards can be distributed immediately upon minting or claimed later.
- Soulbound Option: Reward tokens can be soulbound (non-transferable) upon minting.
- Supply Management: Strict control over max supply and current supply of reward tokens.
- Asset Security: Secure storage for Fungible Assets used in rewards.
- Whitelisting: Only whitelisted tokens can be deposited and used for rewards.
- Treasury-Backed Rewards: Option to create rewards backed by treasury funds (
use_treasuryflag), ensuring solvency. - Withdrawal Controls: Managers can withdraw assets if needed.
- Role-Based Access: Granular permissions using
ADMIN,MANAGER,MINTER, andDEVroles. - Signature Verification: ECDSA signature verification for user minting, ensuring only authorized actions.
- Signer Whitelist: Only signatures from whitelisted public keys are accepted.
- Pausability: Global pause and per-token pause (mint/claim) capabilities.
| Role | ID | Responsibilities |
|---|---|---|
| ADMIN | 4 | Manage roles, global pause, whitelist treasury tokens, create reward tokens, increase supply. |
| MANAGER | 2 | Update token metadata, pause specific tokens, withdraw assets, admin claim operations. |
| MINTER | 3 | Execute admin minting operations (bypassing signature checks). |
| DEV | 1 | Manage whitelist signers for signature verification. |
Before creating rewards backed by the treasury, tokens must be whitelisted and deposited.
// 1. Whitelist a token (Admin only)
whitelist_token(admin, token_metadata_object);
// 2. Deposit tokens to treasury
deposit_to_treasury(depositor, token_metadata_object, amount);Admins create new reward tokens, defining the output (FA/NFTs) and supply.
create_reward_token(
admin,
token_id,
name, symbol, icon, project, // Metadata
max_supply,
token_uri,
fa_metadata_list, // List of FA tokens to reward
amount_per_claim_list, // Amount of each FA per claim
nft_objects, // List of NFTs to distribute
nfts_per_claim // How many NFTs per claim
);To increase the supply of an existing reward token, the underlying tokens must be whitelisted and sufficient funds must be in the treasury.
// 1. Ensure tokens are whitelisted and deposited to treasury
// 2. Increase supply
increase_reward_supply(admin, token_id, additional_supply);Users mint reward tokens using a valid signature from the backend.
// Mint and optionally auto-claim
mint(
user,
data, // Encoded data (contract addr, chain id, token ids)
nonce, // Unique nonce
signature, // ECDSA signature
is_claim_reward, // true = mint and claim immediately
is_soulbound // true = make reward token soulbound
);
// Claim separately (if not claimed during mint)
claim_reward(user, token_id);The contract provides extensive view functions for frontend and indexer integration:
-
User Status:
get_user_reward_balance(user, token_id): Check unclaimed balance.can_user_claim_reward(user, token_id): Quick check if claim is possible.get_user_claim_status(user, token_id): Detailed status (balance, paused state).get_user_reward_balances_batch(user, token_ids): Batch check for multiple tokens.
-
Token Info:
get_token_details(token_id): Supply and metadata.get_reward_info(token_id): Details on underlying rewards (FA/NFT counts).get_fa_rewards(token_id): Specific FA amounts per reward.
-
Treasury:
get_whitelisted_tokens(): List of allowed tokens.get_treasury_balance(token): Balance of a specific token.get_all_treasury_balances(): All treasury holdings.
-
System:
get_whitelist_signers(): List of authorized signers.is_paused(): Global pause status.has_role(address, role): Check permissions.
aptos move compileaptos move test- Initialize your account:
aptos init- Publish the module:
aptos move publish- Contract Address:
0x1db203613d13b4b80a3d47d10a4ccb43959f8a9c35e76427243e15c7ea0998f3 - Resource Account:
0xe5e7acd4b7cd1df9434e499cf2a6e7a0d132ae247d7aad2f5e3d742e8fa3ac85 - Network: Aptos Testnet
- Explorer: View on Aptos Explorer
- rewards: Main reward distribution and treasury management module
- mock_usdc: Test token (USDCsummon) for treasury testing
- mock_nft: Test NFT collection for treasury NFT whitelisting testing
- Module Address:
0x1db203613d13b4b80a3d47d10a4ccb43959f8a9c35e76427243e15c7ea0998f3(where the code lives) - Resource Account:
0xe5e7acd4b7cd1df9434e499cf2a6e7a0d132ae247d7aad2f5e3d742e8fa3ac85(where treasury funds are stored)
A test fungible asset token is available for testing treasury functionality:
- Token Name: USDC Summon
- Symbol: USDCs
- Decimals: 8
- Metadata Address:
0xfb0e5b86fb050d976e4fc38cbfd3817ece43de7abd910ede6bc9e02576c063a9
make init-mock-usdcmake get-mock-usdc-metadata
# Returns: 0xfb0e5b86fb050d976e4fc38cbfd3817ece43de7abd910ede6bc9e02576c063a9# Mint 100 USDC (remember: 8 decimals, so 10000000000 = 100 USDC)
make mint-mock-usdc TO=<your_address> AMOUNT=10000000000make whitelist-token TOKEN=0xfb0e5b86fb050d976e4fc38cbfd3817ece43de7abd910ede6bc9e02576c063a9Two ways to add funds:
Option A - Using deposit function (Recommended for scripts)
# Deposit 50 USDC to treasury
make deposit-to-treasury TOKEN=0xfb0e5b86fb050d976e4fc38cbfd3817ece43de7abd910ede6bc9e02576c063a9 AMOUNT=5000000000Option B - Direct transfer (Simpler for manual transfers)
# 1. Get the resource account address
make get-resource-account
# Output: 0x... (copy this address)
# 2. Transfer tokens directly to that address
# Use any wallet or CLI to send tokens to the resource account
# If the token is whitelisted, it's automatically counted in treasury!make get-treasury-balance TOKEN=0xfb0e5b86fb050d976e4fc38cbfd3817ece43de7abd910ede6bc9e02576c063a9
# Returns: (total_balance, reserved_amount)aptos move run \
--function-id 0x1db203613d13b4b80a3d47d10a4ccb43959f8a9c35e76427243e15c7ea0998f3::rewards::create_reward_token \
--args \
u64:1 \
string:"USDC Reward" \
string:"USDCR" \
string:"https://summon.xyz/icon.png" \
string:"https://summon.xyz" \
u64:50 \
string:"https://summon.xyz/metadata.json" \
"vector<address>:[0xfb0e5b86fb050d976e4fc38cbfd3817ece43de7abd910ede6bc9e02576c063a9]" \
"vector<u64>:[100000000]" \
"vector<address>:[]" \
u64:0 \
--profile summon_testnet --assume-yesThis creates a reward token where each claim distributes 1 USDC (100000000 with 8 decimals).
A test NFT collection is available for testing NFT whitelisting in treasury:
- Collection Name: Summon Test NFT
- Collection Address: Get with
make get-mock-nft-collection
make init-mock-nft# Get the resource account address first
make get-resource-account
# Output: 0xe5e7acd4b7cd1df9434e499cf2a6e7a0d132ae247d7aad2f5e3d742e8fa3ac85
# Mint NFTs directly to resource account
make mint-mock-nft TO=0xe5e7acd4b7cd1df9434e499cf2a6e7a0d132ae247d7aad2f5e3d742e8fa3ac85# Get the address of token #1
aptos move view --function-id 0x1db203613d13b4b80a3d47d10a4ccb43959f8a9c35e76427243e15c7ea0998f3::mock_nft::get_token_address \
--args u64:1 --profile summon_testnet# NFT must be owned by resource account before whitelisting
make whitelist-nft NFT=<nft_address>make get-all-treasury-balances
# Returns: addresses, balances, symbols, names, and types
# NFTs show type: "nft", tokens show type: "token"The project includes a comprehensive Makefile for easy interaction with the contracts.
make help # Show all available commands
make contract-info # Display contract informationmake compile # Compile contracts
make publish # Deploy to network
make clean # Clean build artifacts
make deploy-init # Full deployment workflowmake balance # Check account balance
make fund # Fund account from faucet
make account-info # Show account informationmake init-mock-usdc # Initialize USDCsummon
make mint-mock-usdc TO=<address> AMOUNT=<amount> # Mint USDC
make get-mock-usdc-metadata # Get metadata address
make get-resource-account # Get treasury resource account addressmake whitelist-token TOKEN=<address> # Whitelist token
make remove-token-from-whitelist TOKEN=<address> # Remove from whitelist
make deposit-to-treasury TOKEN=<address> AMOUNT=<amt> # Deposit to treasury
make increase-reward-supply TOKEN_ID=<id> ADDITIONAL_SUPPLY=<amount>
make reduce-reward-supply TOKEN_ID=<id> REDUCE_BY=<amount>make admin-mint TO=<address> TOKEN_ID=<id> SOULBOUND=<bool>
make admin-batch-mint TO=<address> TOKEN_IDS='[0,1,2]' SOULBOUND=<bool>make claim-reward TOKEN_ID=<id>
make admin-claim-reward TO=<address> TOKEN_ID=<id>
make batch-claim-reward TOKEN_IDS='[0,1,2]'make withdraw-fungible-assets TO=<addr> FA_METADATA=<addr> AMOUNT=<amt>
make withdraw-unreserved-treasury TO=<addr> TOKEN=<addr>
make withdraw-nfts TO=<addr> NFT_OBJECTS='[<addr>,...]'make set-pause PAUSED=<bool> # Pause entire contract
make pause-token-mint TOKEN_ID=<id> PAUSED=<bool> # Pause minting
make pause-claim-reward TOKEN_ID=<id> PAUSED=<bool> # Pause claiming
make update-token-uri TOKEN_ID=<id> URI='<uri>' # Update metadata URImake token-details TOKEN_ID=<id> # Get token details
make all-tokens # List all token IDs
make get-whitelisted-tokens # List treasury tokens
make is-token-whitelisted TOKEN=<address> # Check if whitelisted
make get-treasury-balance TOKEN=<address> # Get balance & reserved
make get-all-treasury-balances # All treasury balances
make get-reward-info TOKEN_ID=<id> # Reward distribution info
make get-fa-rewards TOKEN_ID=<id> # FA reward details
make get-user-reward-balance USER=<addr> TOKEN_ID=<id>
make get-user-claim-status USER=<addr> TOKEN_ID=<id>
make whitelist-signers # List authorized signers
make is-paused # Check pause status
make has-role ADDRESS=<addr> ROLE=<id> # Check permissions
make chain-id # Get chain IDmake grant-role ROLE=<id> TO=<address> # Grant role
make revoke-role ROLE=<id> TO=<address> # Revoke role
# Roles: DEV_ROLE=1, MANAGER_ROLE=2, MINTER_ROLE=3, ADMIN_ROLE=4make add-whitelist-signer PUBKEY=<hex> # Add signer
make remove-whitelist-signer PUBKEY=<hex> # Remove signerThe project uses Aptos CLI profiles for network configuration. Set the active profile in Makefile:
PROFILE := summon_testnetUpdate Move.toml to match your deployment:
[addresses]
# Testnet
rewards_module = "0x1db203613d13b4b80a3d47d10a4ccb43959f8a9c35e76427243e15c7ea0998f3"
summon = "0x1db203613d13b4b80a3d47d10a4ccb43959f8a9c35e76427243e15c7ea0998f3"Profile configuration in .aptos/config.yaml:
summon_testnet:
network: Testnet
account: 1db203613d13b4b80a3d47d10a4ccb43959f8a9c35e76427243e15c7ea0998f3
rest_url: "https://fullnode.testnet.aptoslabs.com"
faucet_url: "https://faucet.testnet.aptoslabs.com"Run Move unit tests:
make test
# or
aptos move testUse the test workflow commands:
make test-treasury-flow # Automated treasury testing
make test-mint-claim USER=<address>
make test-direct-transfer # Security test: direct transfer vs depositThis test verifies that simply transferring tokens directly to the contract does NOT automatically register them in the treasury:
make test-direct-transferExpected Result: ✅ Treasury balance should NOT change
- Direct transfers bypass treasury accounting
- Tokens are sent to the contract but not tracked by treasury
- Only
deposit_to_treasury()properly updates treasury state - This is correct behavior for security
Why this matters:
- Prevents unauthorized treasury balance manipulation
- Maintains accurate
reserved_amountstracking - Ensures only whitelisted tokens are properly accounted for
- Direct transfer tokens become "orphaned" and require manual recovery
See TEST_DIRECT_TRANSFER.md for detailed explanation.
- TREASURY_TESTING_GUIDE.md: Comprehensive guide for treasury testing scenarios
- MOCK_USDC_SETUP.md: Detailed setup instructions for mock USDC token
- Aptos CLI: v7.11.1 or higher (for Move 2.2 support)
- Move Compiler: Compatible with Aptos testnet/mainnet
# macOS (Homebrew)
brew install aptos
# or update
brew upgrade aptos
# Check version
aptos --version # Should be 7.11.1 or highersources/
├── rewards.move # Main rewards & treasury module
├── helpers/
│ └── multi_reward_setup.move # Helper for testing multi-reward creation
└── test/
├── mock_usdc.move # Mock USDC for treasury testing
└── test_*.move # Unit test files
- Whitelisting: Only approved tokens can be used in rewards
- Reserved Amounts: Tracks tokens allocated for pending rewards
- Safety Checks: Prevents withdrawal of reserved funds
- Supply Management: Automatically reserves/releases funds when supply changes
- Creation: Admin creates reward token with defined FA/NFT rewards
- Minting: Users/admins mint reward tokens (receipt tokens)
- Claiming: Users burn receipt token to receive actual rewards
- Distribution: FA/NFTs are transferred from treasury/contract to user
- Role-Based Access Control: Granular permissions for different operations
- Signature Verification: ECDSA signatures ensure authorized minting
- Pausability: Emergency stop mechanisms at global and per-token levels
- Treasury Protection: Reserved amounts cannot be withdrawn
Contributions are welcome! Please ensure:
- All tests pass:
make test - Code compiles:
make compile - Follow Move best practices and security guidelines
MIT
