### Setup Plume Contracts with Foundry
Source: https://github.com/plumenetwork/contracts/blob/main/smart-wallets/README.md
Installs the Foundry toolchain and necessary dependencies for developing Plume smart contracts. Assumes Foundry is not already installed.
```bash
$ foundryup
$ forge install
```
--------------------------------
### Static Analysis of Plume Contracts with Slither
Source: https://github.com/plumenetwork/contracts/blob/main/smart-wallets/README.md
Performs static analysis on the Plume smart contracts to identify potential vulnerabilities and issues. Requires Slither to be installed and a configuration file.
```bash
# Get list of issues
$ slither --config-file slither.config.json .
```
--------------------------------
### Install Forge Standard Library
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/README.md
Command to install the Forge Standard Library using the Forge package manager. This is a prerequisite for using its features in your Foundry projects.
```bash
forge install foundry-rs/forge-std
```
--------------------------------
### Plume Launch Steps for Spin and Raffle
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Solidity code snippets demonstrating the launch process for Spin and Raffle contracts. This includes configuring prizes, setting campaign start dates, and enabling the Spin functionality.
```solidity
// 1. Configure Raffle Prizes
raffle.addPrize(prizeId, prizeDetails);
// 2. Set Campaign Start Date (Spin)
spin.setCampaignStartDate(startTimestamp);
// 3. Enable Spin
spin.setEnabledSpin(true);
```
--------------------------------
### Compile Plume Smart Contracts using Foundry
Source: https://github.com/plumenetwork/contracts/blob/main/smart-wallets/README.md
Compiles all the smart contracts within the Plume project using the Foundry's forge compiler. This step is essential before testing or deploying.
```bash
$ forge compile
```
--------------------------------
### Test and Analyze Plume Contracts with Foundry
Source: https://github.com/plumenetwork/contracts/blob/main/smart-wallets/README.md
Executes all defined tests for the Plume smart contracts and generates a code coverage report. The `--ir-minimum` flag optimizes the coverage report for faster generation.
```bash
$ forge test
$ forge coverage --ir-minimum
```
--------------------------------
### Reward Calculation System: Checkpoint Creation Example
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
JavaScript code illustrating the creation of rate and commission checkpoints based on a simulated timeline. This demonstrates how changes in reward rates and commission percentages are recorded for accurate historical calculations.
```javascript
// Reward Rate Checkpoints
Checkpoint 0: {
timestamp: Jan 5,
rate: 100e18, // 100 tokens/day/staked token
cumulativeIndex: 0
}
Checkpoint 1: {
timestamp: Jan 15,
rate: 150e18,
cumulativeIndex: 1000e18 // Accumulated from previous segment
}
// Commission Checkpoints
Checkpoint 0: { timestamp: Jan 5, rate: 0.1e18 } // 10%
Checkpoint 1: { timestamp: Jan 15, rate: 0.15e18 } // 15%
Checkpoint 2: { timestamp: Jan 25, rate: 0.2e18 } // 20%
```
--------------------------------
### Deploy Plume Smart Wallet Contract with Foundry
Source: https://github.com/plumenetwork/contracts/blob/main/smart-wallets/README.md
Deploys the Smart Wallet contract using Foundry's scripting capabilities. It includes options for verification against Blockscout and legacy transaction format.
```bash
$ forge script script/DeploySmartWallet.s.sol --rpc-url $RPC_URL --broadcast \
--verify --verifier blockscout --verifier-url $VERIFIER_URL -g 500 --legacy
```
--------------------------------
### Reward Calculation System: Detailed Calculation Example Flowchart
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
A flowchart visualizing the detailed calculation process for rewards, starting from a user staking PLUME, through various rate and commission changes, to the final reward claim. It visually breaks down the segments and events affecting reward accrual.
```mermaid
flowchart LR
A[Jan 1
Stake 1000] --> B[Jan 5
Rate: 100/day
Comm: 10%]
B --> C[Jan 15
Rate: 150/day
Comm: 15%]
C --> D[Jan 25
Comm: 20%
Rate unchanged]
D --> E[Jan 30
Claim]
style A fill:#e1f5fe
style E fill:#c8e6c9
```
--------------------------------
### Forge Stdlib: Test Storage Slots and Values in Solidity
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/README.md
This example demonstrates how to use Forge's stdlib to interact with contract storage. It covers finding storage slots for public variables, mappings, structs, and hidden variables, as well as writing new values to these slots. It requires the Forge testing environment.
```solidity
import "forge-std/Test.sol";
contract TestContract is Test {
using stdStorage for StdStorage;
Storage test;
function setUp() public {
test = new Storage();
}
function testFindExists() public {
// Lets say we want to find the slot for the public
// variable `exists`. We just pass in the function selector
// to the `find` command
uint256 slot = stdstore.target(address(test)).sig("exists()").find();
assertEq(slot, 0);
}
function testWriteExists() public {
// Lets say we want to write to the slot for the public
// variable `exists`. We just pass in the function selector
// to the `checked_write` command
stdstore.target(address(test)).sig("exists()").checked_write(100);
assertEq(test.exists(), 100);
}
// It supports arbitrary storage layouts, like assembly based storage locations
function testFindHidden() public {
// `hidden` is a random hash of a bytes, iteration through slots would
// not find it. Our mechanism does
// Also, you can use the selector instead of a string
uint256 slot = stdstore.target(address(test)).sig(test.hidden.selector).find();
assertEq(slot, uint256(keccak256("my.random.var")));
}
// If targeting a mapping, you have to pass in the keys necessary to perform the find
// i.e.:
function testFindMapping() public {
uint256 slot = stdstore
.target(address(test))
.sig(test.map_addr.selector)
.with_key(address(this))
.find();
// in the `Storage` constructor, we wrote that this address' value was 1 in the map
// so when we load the slot, we expect it to be 1
assertEq(uint(vm.load(address(test), bytes32(slot))), 1);
}
// If the target is a struct, you can specify the field depth:
function testFindStruct() public {
// NOTE: see the depth parameter - 0 means 0th field, 1 means 1st field, etc.
uint256 slot_for_a_field = stdstore
.target(address(test))
.sig(test.basicStruct.selector)
.depth(0)
.find();
uint256 slot_for_b_field = stdstore
.target(address(test))
.sig(test.basicStruct.selector)
.depth(1)
.find();
assertEq(uint(vm.load(address(test), bytes32(slot_for_a_field))), 1);
assertEq(uint(vm.load(address(test), bytes32(slot_for_b_field))), 2);
}
}
// A complex storage contract
contract Storage {
struct UnpackedStruct {
uint256 a;
uint256 b;
}
constructor() {
map_addr[msg.sender] = 1;
}
uint256 public exists = 1;
mapping(address => uint256) public map_addr;
// mapping(address => Packed) public map_packed;
mapping(address => UnpackedStruct) public map_struct;
mapping(address => mapping(address => uint256)) public deep_map;
mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
UnpackedStruct public basicStruct = UnpackedStruct({
a: 1,
b: 2
});
function hidden() public view returns (bytes32 t) {
// an extremely hidden storage slot
bytes32 slot = keccak256("my.random.var");
assembly {
t := sload(slot)
}
}
}
```
--------------------------------
### Reward Calculation System: Timeline Gantt Chart
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
An example Gantt chart illustrating the reward calculation timeline, highlighting user activities like staking and reward claiming, alongside rate changes and commission updates. This visual aids in understanding the temporal aspects of reward accrual and distribution.
```mermaid
gantt
title Reward Calculation Timeline Example
dateFormat YYYY-MM-DD
axisFormat %m/%d
section User Activity
Stake 1000 PLUME :milestone, 2024-01-01, 0d
Claim Rewards :milestone, 2024-01-30, 0d
section Rate Changes
Rate: 100/day (10% comm) :active, 2024-01-05, 10d
Rate: 150/day (15% comm) :active, 2024-01-15, 10d
Rate: 150/day (20% comm) :active, 2024-01-25, 5d
```
--------------------------------
### Cancel Pending Spin in Raffle.sol
Source: https://github.com/plumenetwork/contracts/blob/main/plume/SPIN.md
A troubleshooting function to cancel a pending raffle spin or winner request. This is useful when a user's spin gets stuck in a pending state, preventing them from spinning again. This function requires the 'ADMIN_ROLE'.
```solidity
function cancelPendingSpin(uint256 prizeId) public
```
--------------------------------
### Initialize PlumeStaking System (Solidity)
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Initializes the PlumeStaking system and the AccessControlFacet after the Diamond proxy deployment. Requires owner address, minimum stake amount, cooldown period, maximum slashing vote duration, and maximum validator commission.
```solidity
// After Diamond deployment, initialize PlumeStaking
plumeStaking.initializePlume(initialOwner, minStake, cooldown, maxSlashVoteDuration, maxValidatorCommission)
// Initialize AccessControlFacet
accessControlFacet.initializeAccessControl()
```
--------------------------------
### Sales Contract Initialization
Source: https://github.com/plumenetwork/contracts/blob/main/arc/README.md
Initializes the sales contract by setting the administrative address and the token factory address.
```APIDOC
## POST /initialize
### Description
Initializes the sales contract, setting the admin and token factory addresses.
### Method
POST
### Endpoint
/initialize
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **admin** (address) - Required - The address of the contract administrator.
- **factory** (address) - Required - The address of the ArcTokenFactory contract.
### Request Example
```json
{
"admin": "0x1234567890abcdef1234567890abcdef12345678",
"factory": "0xabcdef1234567890abcdef1234567890abcdef12"
}
```
### Response
#### Success Response (200)
Indicates successful initialization.
#### Response Example
(No specific response body is defined for initialization success, typically a status code 200 or 204)
#### Error Responses
- **initializerFinished()**: If the initializer has already been called.
- **AddressZeroCannotBeUsed()**: If zero addresses are provided for admin or factory.
```
--------------------------------
### Plume Network Contract Build Instructions
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Commands to clean the project and build the Plume Network contracts using Forge. This process ensures a clean build environment and generates build information, utilizing the Intermediate Representation (IR).
```bash
forge clean && forge build --via-ir --build-info
```
--------------------------------
### Configuration Management
Source: https://github.com/plumenetwork/contracts/blob/main/arc/README.md
APIs for configuring core settings of the sales contract, including purchase tokens and storefront metadata.
```APIDOC
## PUT /setPurchaseToken
### Description
Sets the ERC20 token address that will be used for purchasing ArcTokens (e.g., USDC, DAI).
### Method
PUT
### Endpoint
/setPurchaseToken
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **purchaseTokenAddress** (address) - Required - The address of the ERC20 token contract to be used for purchases.
### Request Example
```json
{
"purchaseTokenAddress": "0xabcdef1234567890abcdef1234567890abcdef12"
}
```
### Response
#### Success Response (200)
Indicates the purchase token address has been successfully updated.
#### Response Example
(No specific response body is defined for success)
#### Error Responses
- **DEFAULT_ADMIN_ROLE**: Only users with the default admin role can call this function.
- **InvalidPurchaseTokenAddress()**: If the provided address is invalid or zero.
- **CannotChangePurchaseTokenWithActiveSales()**: If there are active token sales, the purchase token cannot be changed.
```
```APIDOC
## PUT /setTokenFactory
### Description
Sets the `ArcTokenFactory` address, which is used by the sales contract to verify that newly enabled tokens were indeed created by the official factory.
### Method
PUT
### Endpoint
/setTokenFactory
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **factoryAddress** (address) - Required - The address of the `ArcTokenFactory` contract.
### Request Example
```json
{
"factoryAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
```
### Response
#### Success Response (200)
Indicates the token factory address has been successfully updated.
#### Response Example
(No specific response body is defined for success)
#### Error Responses
- **DEFAULT_ADMIN_ROLE**: Only users with the default admin role can call this function.
- **AddressZeroCannotBeUsed()**: If the provided `factoryAddress` is the zero address.
```
```APIDOC
## POST /setStorefrontConfig
### Description
Configures metadata for an off-chain storefront associated with a specific token sale. This includes details like domain names.
### Method
POST
### Endpoint
/setStorefrontConfig
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **_tokenContract** (address) - Required - The contract address of the ArcToken for which to configure the storefront.
- **_domain** (string) - Required - The domain name for the storefront (e.g., "mycooltoken.com").
- **...** (additional fields may exist for other metadata)
### Request Example
```json
{
"_tokenContract": "0x1111111111111111111111111111111111111111",
"_domain": "mytokenstore.xyz"
}
```
### Response
#### Success Response (200)
Indicates the storefront configuration has been successfully set.
#### Response Example
(No specific response body is defined for success)
#### Error Responses
- **onlyTokenAdmin**: Only token admins can set storefront configurations.
- **DomainCannotBeEmpty()**: If the provided `_domain` is empty.
- **DomainAlreadyInUse(string domain)**: If the `_domain` is already associated with another token.
```
--------------------------------
### Solidity: Test Contract with Hoax and Prank
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/README.md
Demonstrates the usage of `hoax` and `startHoax` functions within a Solidity test contract. These functions are used to simulate specific `msg.sender` and `msg.value` conditions for testing.
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
// Inherit the stdCheats
contract StdCheatsTest is Test {
Bar test;
function setUp() public {
test = new Bar();
}
function testHoax() public {
// we call `hoax`, which gives the target address
// eth and then calls `prank`
hoax(address(1337));
test.bar{value: 100}(address(1337));
// overloaded to allow you to specify how much eth to
// initialize the address with
hoax(address(1337), 1);
test.bar{value: 1}(address(1337));
}
function testStartHoax() public {
// we call `startHoax`, which gives the target address
// eth and then calls `startPrank`
//
// it is also overloaded so that you can specify an eth amount
startHoax(address(1337));
test.bar{value: 100}(address(1337));
test.bar{value: 100}(address(1337));
vm.stopPrank();
test.bar(address(this));
}
}
contract Bar {
function bar(address expectedSender) public payable {
require(msg.sender == expectedSender, "!prank");
}
}
```
--------------------------------
### Solidity: Console Logging with console.sol (Hardhat Compatible)
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/README.md
Demonstrates the usage of `console.log` for debugging in Solidity, emphasizing compatibility with Hardhat. Note that `uint256` and `int256` types may not be properly decoded in Forge traces due to a known bug in `console.sol`.
```solidity
// import it indirectly via Test.sol
import "forge-std/Test.sol";
// or directly import it
import "forge-std/console.sol";
...
console.log(someValue);
```
--------------------------------
### Deploy Plume Spin and Raffle Contracts
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Deployment script for Spin and Raffle contracts on the Plume Network, including Supra whitelisting. This command sources environment variables and executes the deployment script using Forge, broadcasting the transaction to the network.
```bash
source .env && forge script script/DeploySpinRaffleContracts.s.sol \
--rpc-url https://rpc.plume.org \
--broadcast \
--via-ir
```
--------------------------------
### AccessControlFacet Initialization
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Solidity code for initializing the AccessControlFacet. This function must be called after the facet is deployed to set up roles and permissions, granting DEFAULT_ADMIN_ROLE and ADMIN_ROLE to the caller.
```Solidity
// Must be called after facet deployment
accessControlFacet.initializeAccessControl()
```
--------------------------------
### Deploy and Manage Asset Vaults in Smart Wallets (Solidity)
Source: https://context7.com/plumenetwork/contracts/llms.txt
This code demonstrates the creation and management of asset vaults associated with smart wallets. It shows how to compute a smart wallet's address, deploy its asset vault, retrieve the vault's address, and handle asset deposits and redemptions. It also covers approving tokens for vault usage and fulfilling deposit requests. Dependencies include ISmartWallet, IAssetVault, IERC20, and IAssetToken.
```solidity
// Smart wallet automatically exists for every EOA via proxy
address smartWallet = walletFactory.computeWalletAddress(msg.sender);
// Deploy asset vault for user
ISmartWallet(smartWallet).deployAssetVault();
// Get vault address
IAssetVault vault = ISmartWallet(smartWallet).getAssetVault();
console.log("Asset vault deployed at:", address(vault));
// Create deposit request to vault
uint256 depositAmount = 1000e6; // 1000 USDC
IERC20(usdcAddress).approve(address(vault), depositAmount);
IAssetVault(address(vault)).requestDeposit(
assetTokenAddress,
usdcAddress, // currency token
depositAmount,
msg.sender
);
// Asset token admin processes the deposit
uint256 depositId = 0;
IAssetToken(assetTokenAddress).fulfillDeposit(
msg.sender,
depositId
);
// Check vault balances
uint256 lockedAssets = ISmartWallet(smartWallet).getLockedAssetTokenBalance(
assetTokenAddress
);
console.log("Locked in vault:", lockedAssets);
// Request redemption
IAssetVault(address(vault)).requestRedeem(
assetTokenAddress,
100e18, // 100 asset tokens
msg.sender
);
```
--------------------------------
### Solidity: Console Logging with console2.sol
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/README.md
Shows how to use `console2.log` for debugging in Solidity tests. This method is recommended for use with Forge as it provides decoded logs in traces. It can be imported directly or indirectly via `Test.sol`.
```solidity
// import it indirectly via Test.sol
import "forge-std/Test.sol";
// or directly import it
import "forge-std/console2.sol";
...
console2.log(someValue);
```
--------------------------------
### Spin Contract Functions
Source: https://github.com/plumenetwork/contracts/blob/main/plume/SPIN.md
This section covers the key functions of the Spin contract, including initiating spins, handling oracle callbacks, managing user data, and administrative functions.
```APIDOC
## Spin Contract API
### `startSpin()`
**Description**: User-callable function to initiate a spin.
**Method**: `POST` (or relevant transaction method)
**Endpoint**: `/spin/startSpin` (Conceptual endpoint for transaction)
**Parameters**:
#### Query Parameters
- **`spinPrice`** (uint256) - Required - The price to initiate a spin.
#### Request Body
(Not applicable for this function, typically called with parameters)
### `handleRandomness(...)`
**Description**: Callback function for the Supra oracle. Processes the spin result and updates user state.
**Method**: Internal/Oracle Callback
**Endpoint**: N/A (Internal callback)
**Parameters**:
(Details depend on oracle integration)
### `spendRaffleTickets(...)`
**Description**: Allows the `Raffle` contract to deduct tickets from a user's balance.
**Method**: Internal/Contract-to-Contract Call
**Endpoint**: N/A (Internal call from Raffle contract)
**Parameters**:
(Details depend on Raffle contract interaction)
### `pause()` / `unpause()`
**Description**: Pauses or unpauses the `startSpin` functionality.
**Method**: `POST` (or relevant transaction method)
**Endpoint**: `/spin/pause`, `/spin/unpause` (Conceptual endpoints)
**Parameters**:
(None required)
### `adminWithdraw(...)`
**Description**: Allows admin to withdraw PLUME tokens from the contract balance.
**Method**: `POST` (or relevant transaction method)
**Endpoint**: `/spin/adminWithdraw` (Conceptual endpoint)
**Parameters**:
(Details depend on withdrawal mechanism)
### `cancelPendingSpin(address user)`
**Description**: Escape hatch to cancel a user's spin request stuck pending an oracle callback.
**Method**: `POST` (or relevant transaction method)
**Endpoint**: `/spin/cancelPendingSpin` (Conceptual endpoint)
**Parameters**:
#### Query Parameters
- **`user`** (address) - Required - The address of the user whose spin request to cancel.
### `set...()` functions
**Description**: A suite of functions for configuring contract parameters (e.g., `setSpinPrice`, `setRaffleContract`).
**Method**: `POST` (or relevant transaction method)
**Endpoint**: `/spin/setSpinPrice`, `/spin/setRaffleContract`, etc. (Conceptual endpoints)
**Parameters**:
(Vary depending on the specific set function)
### `currentStreak(address user)`
**Description**: View function to get a user's current consecutive daily spin streak.
**Method**: `GET` (or relevant view call)
**Endpoint**: `/spin/currentStreak` (Conceptual endpoint)
**Parameters**:
#### Query Parameters
- **`user`** (address) - Required - The address of the user.
### `getUserData(address user)`
**Description**: View function that returns a comprehensive struct of a user's spin-related data.
**Method**: `GET` (or relevant view call)
**Endpoint**: `/spin/getUserData` (Conceptual endpoint)
**Parameters**:
#### Query Parameters
- **`user`** (address) - Required - The address of the user.
### `getWeeklyJackpot()`
**Description**: View function to get the current week's jackpot prize and required streak.
**Method**: `GET` (or relevant view call)
**Endpoint**: `/spin/getWeeklyJackpot` (Conceptual endpoint)
**Parameters**:
(None required)
### Events
- `SpinRequested(uint256 indexed nonce, address indexed user)`
- `SpinCompleted(address indexed walletAddress, string rewardCategory, uint256 rewardAmount)`
- `RaffleTicketsSpent(address indexed walletAddress, uint256 ticketsUsed, uint256 remainingTickets)`
- `NotEnoughStreak(string message)`
- `JackpotAlreadyClaimed(string message)`
### Errors
- `AlreadySpunToday()`
- `CampaignNotStarted()`
- `InvalidNonce()`
- `SpinRequestPending(address user)`
```
--------------------------------
### Winner Selection Initiation in Raffle.sol
Source: https://github.com/plumenetwork/contracts/blob/main/plume/SPIN.md
Initiates the process for selecting a winner for a specified prize. This function requires the 'ADMIN_ROLE' to be called. It is designed to work with external oracles for secure random selection.
```solidity
function requestWinner(uint256 prizeId) public
```
--------------------------------
### Generate Cheatcodes with vm.py Script
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/CONTRIBUTING.md
This script generates cheatcodes for the Vm.sol file from a JSON configuration. It can automatically use the default cheatcodes.json or accept a custom JSON file path via the --from flag. Ensure this script is run when modifying native cheatcodes or adding new ones.
```shell
./scripts/vm.py --from path/to/cheatcodes.json
```
--------------------------------
### Token Information Retrieval
Source: https://github.com/plumenetwork/contracts/blob/main/arc/README.md
APIs for retrieving detailed information about enabled token sales and their configurations.
```APIDOC
## GET /getTokenInfo
### Description
Retrieves the sales status and details for a specific ArcToken, including whether it's enabled, its price, total supply for sale, and tokens already sold.
### Method
GET
### Endpoint
/getTokenInfo
### Parameters
#### Path Parameters
None
#### Query Parameters
- **_tokenContract** (address) - Required - The contract address of the ArcToken to query.
### Request Example
`GET /getTokenInfo?_tokenContract=0x1111111111111111111111111111111111111111`
### Response
#### Success Response (200)
Returns the sales status and details for the specified token.
- **isEnabled** (bool) - Whether the token sale is currently enabled.
- **price** (uint256) - The price per full ArcToken unit in the purchase token.
- **totalForSale** (uint256) - The total number of tokens made available for sale.
- **sold** (uint256) - The number of tokens already sold.
#### Response Example
```json
{
"isEnabled": true,
"price": 500000000000000000,
"totalForSale": 1000000000000000000,
"sold": 500000000000000000
}
```
```
```APIDOC
## GET /isEnabled
### Description
Checks if a specific ArcToken sale is currently enabled.
### Method
GET
### Endpoint
/isEnabled
### Parameters
#### Path Parameters
None
#### Query Parameters
- **_tokenContract** (address) - Required - The contract address of the ArcToken to check.
### Request Example
`GET /isEnabled?_tokenContract=0x1111111111111111111111111111111111111111`
### Response
#### Success Response (200)
Returns a boolean indicating if the token sale is enabled.
- **enabled** (bool) - `true` if the token sale is enabled, `false` otherwise.
#### Response Example
```json
{
"enabled": true
}
```
```
```APIDOC
## GET /getMaxNumberOfTokens
### Description
Returns the remaining number of tokens available for sale for a given ArcToken, expressed in base units.
### Method
GET
### Endpoint
/getMaxNumberOfTokens
### Parameters
#### Path Parameters
None
#### Query Parameters
- **_tokenContract** (address) - Required - The contract address of the ArcToken to query.
### Request Example
`GET /getMaxNumberOfTokens?_tokenContract=0x1111111111111111111111111111111111111111`
### Response
#### Success Response (200)
Returns the number of tokens still available for sale.
- **remainingTokens** (uint256) - The quantity of tokens remaining for sale.
#### Response Example
```json
{
"remainingTokens": 500000000000000000
}
```
```
```APIDOC
## GET /getTokenPrice
### Description
Returns the price per full `ArcToken` unit, denominated in the currently configured purchase token.
### Method
GET
### Endpoint
/getTokenPrice
### Parameters
#### Path Parameters
None
#### Query Parameters
- **_tokenContract** (address) - Required - The contract address of the ArcToken whose price is being queried.
### Request Example
`GET /getTokenPrice?_tokenContract=0x1111111111111111111111111111111111111111`
### Response
#### Success Response (200)
Returns the price of one unit of the ArcToken.
- **price** (uint256) - The price in the purchase token's smallest unit.
#### Response Example
```json
{
"price": 500000000000000000
}
```
```
```APIDOC
## GET /getStorefrontConfig
### Description
Retrieves the storefront configuration details associated with a specific ArcToken contract.
### Method
GET
### Endpoint
/getStorefrontConfig
### Parameters
#### Path Parameters
None
#### Query Parameters
- **_tokenContract** (address) - Required - The contract address of the ArcToken whose storefront configuration is requested.
### Request Example
`GET /getStorefrontConfig?_tokenContract=0x1111111111111111111111111111111111111111`
### Response
#### Success Response (200)
Returns the storefront configuration, including the associated domain.
- **domain** (string) - The domain name configured for the storefront.
- **...** (other configuration fields may be returned)
#### Response Example
```json
{
"domain": "mytokenstore.xyz"
}
```
#### Error Responses
- **NoConfigForDomain(string domain)**: If no storefront configuration exists for the specified token.
```
```APIDOC
## GET /getStorefrontConfigByDomain
### Description
Retrieves the storefront configuration details associated with a given domain name.
### Method
GET
### Endpoint
/getStorefrontConfigByDomain
### Parameters
#### Path Parameters
None
#### Query Parameters
- **_domain** (string) - Required - The domain name to look up.
### Request Example
`GET /getStorefrontConfigByDomain?_domain=mytokenstore.xyz`
### Response
#### Success Response (200)
Returns the storefront configuration associated with the domain.
- **tokenContract** (address) - The ArcToken contract address linked to this domain.
- **...** (other configuration fields may be returned)
#### Response Example
```json
{
"tokenContract": "0x1111111111111111111111111111111111111111"
}
```
#### Error Responses
- **NoConfigForDomain(string domain)**: If no storefront configuration exists for the specified domain.
```
```APIDOC
## GET /getAddressByDomain
### Description
Returns the `ArcToken` contract address that is associated with a given domain name.
### Method
GET
### Endpoint
/getAddressByDomain
### Parameters
#### Path Parameters
None
#### Query Parameters
- **_domain** (string) - Required - The domain name to look up.
### Request Example
`GET /getAddressByDomain?_domain=mytokenstore.xyz`
### Response
#### Success Response (200)
Returns the ArcToken contract address linked to the domain.
- **tokenContractAddress** (address) - The address of the ArcToken contract.
#### Response Example
```json
{
"tokenContractAddress": "0x1111111111111111111111111111111111111111"
}
```
#### Error Responses
- **NoConfigForDomain(string domain)**: If no mapping exists for the provided domain.
```
```APIDOC
## GET /purchaseToken
### Description
Returns the address of the ERC20 token currently configured for use in purchasing ArcTokens.
### Method
GET
### Endpoint
/purchaseToken
### Parameters
#### Path Parameters
None
#### Query Parameters
None
### Request Example
`GET /purchaseToken`
### Response
#### Success Response (200)
Returns the address of the purchase token.
- **purchaseTokenAddress** (address) - The address of the active purchase token.
#### Response Example
```json
{
"purchaseTokenAddress": "0xabcdef1234567890abcdef1234567890abcdef12"
}
```
#### Error Responses
- **PurchaseTokenNotSet()**: If no purchase token has been set yet.
```
```APIDOC
## GET /tokenFactory
### Description
Returns the address of the `ArcTokenFactory` contract that is currently configured for the sales contract.
### Method
GET
### Endpoint
/tokenFactory
### Parameters
#### Path Parameters
None
#### Query Parameters
None
### Request Example
`GET /tokenFactory`
### Response
#### Success Response (200)
Returns the address of the token factory.
- **tokenFactoryAddress** (address) - The address of the configured ArcTokenFactory.
#### Response Example
```json
{
"tokenFactoryAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
```
#### Error Responses
- **TokenFactoryNotSet()**: If no token factory has been configured.
```
--------------------------------
### Build with Specific Solidity Compiler Versions
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/CONTRIBUTING.md
Compiles the Foundry project using different specified Solidity compiler versions, while skipping tests. This verifies compatibility across various compiler targets.
```shell
forge build --skip test --use solc:0.6.2
forge build --skip test --use solc:0.6.12
forge build --skip test --use solc:0.7.0
forge build --skip test --use solc:0.7.6
forge build --skip test --use solc:0.8.0
```
--------------------------------
### Plume Network Environment Configuration
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Environment variables for configuring network settings, contract addresses, and Oracle details for Plume Network. This includes RPC URLs, private keys, proxy addresses for upgrades, and addresses for Supra Oracle services.
```dotenv
# Network
RPC_URL="https://rpc.plume.org"
PRIVATE_KEY=
# Contract Addresses (for upgrades)
SPIN_PROXY_ADDRESS=
RAFFLE_PROXY_ADDRESS=
# Supra Oracle
SUPRA_ROUTER_ADDRESS=0xE1062AC81e76ebd17b1e283CEed7B9E8B2F749A5
SUPRA_DEPOSIT_CONTRACT_ADDRESS=0x6DA36159Fe94877fF7cF226DBB164ef7f8919b9b
SUPRA_GENERATOR_CONTRACT_ADDRESS=0x8cC8bbE991d8B4371551B4e666Aa212f9D5f165e
# Utilities
DATETIME_ADDRESS=0x06a40Ec10d03998634d89d2e098F079D06A8FA83
BLOCKSCOUT_URL=https://explorer.plume.org/api?
```
--------------------------------
### Run Tests with Forge
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/CONTRIBUTING.md
Executes all tests within the Foundry project with verbose output. This is a crucial step to ensure code changes do not break existing functionality.
```shell
forge test -vvv
```
--------------------------------
### ManagementFacet System Parameter Configuration
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Functions to configure system-wide parameters and perform administrative tasks. This includes setting minimum stake, cooldown durations, slashing parameters, and managing validator records.
```Solidity
function setMinStakeAmount(uint256)
function setCooldownInterval(uint256)
function adminWithdraw(address, uint256, address)
function setMaxSlashVoteDuration(uint256)
function setMaxAllowedValidatorCommission(uint256)
function adminClearValidatorRecord(address, uint16)
function adminBatchClearValidatorRecords(address[], uint16)
function setMaxCommissionCheckpoints(uint16)
function setMaxValidatorPercentage(uint256)
function pruneCommissionCheckpoints(uint16, uint256)
function pruneRewardRateCheckpoints(uint16, address, uint256)
function addHistoricalRewardToken(address)
function removeHistoricalRewardToken(address)
```
--------------------------------
### Check Code Formatting with Forge
Source: https://github.com/plumenetwork/contracts/blob/main/arc/lib/forge-std/CONTRIBUTING.md
Ensures that the code adheres to Foundry's formatting standards. This command checks if the code is formatted correctly without making changes.
```shell
forge fmt --check
```
--------------------------------
### Configure Reward Tokens and Rates in PlumeStaking (Solidity)
Source: https://context7.com/plumenetwork/contracts/llms.txt
This snippet demonstrates how to manage reward tokens and their rates within the PlumeStaking contract. It covers adding new reward tokens, setting initial and maximum rates, updating rates for multiple tokens, removing tokens, setting the treasury address, and querying current reward information. Dependencies include the IRewardsFacet and IPlumeStaking interfaces.
```solidity
// Add new reward token (creates checkpoints for all validators)
IRewardsFacet(stakingDiamond).addRewardToken(
usdcAddress,
1e15, // initial rate: 1e15 tokens per second per staked token
5e15 // max rate: 5e15
);
// Set reward rates for multiple tokens
address[] memory tokens = [plumeAddress, usdcAddress];
uint256[] memory rates = [
2e15, // 2e15 PLUME per second per staked token
1.5e15 // 1.5e15 USDC per second per staked token
];
IRewardsFacet(stakingDiamond).setRewardRates(tokens, rates);
// Update max rate for a token
IRewardsFacet(stakingDiamond).setMaxRewardRate(usdcAddress, 10e15);
// Remove a reward token (creates final zero-rate checkpoint)
IRewardsFacet(stakingDiamond).removeRewardToken(oldTokenAddress);
// Set treasury address for reward distributions
IRewardsFacet(stakingDiamond).setTreasury(treasuryAddress);
// Get current reward configuration
IPlumeStaking.RewardInfo memory rewardInfo =
IRewardsFacet(stakingDiamond).tokenRewardInfo(usdcAddress);
console.log("Current rate:", rewardInfo.rate);
console.log("Max rate:", rewardInfo.maxRate);
```
--------------------------------
### Commission System Flow (Sequence Diagram)
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Visualizes the commission system's flow, from user staking and reward accrual to commission deduction, validator claims, and treasury distribution. It highlights the 7-day timelock for commission claims.
```Mermaid
sequenceDiagram
participant User
participant StakingContract
participant Validator
participant Treasury
User->>StakingContract: stake(validatorId)
Note over StakingContract: Rewards accrue over time
User->>StakingContract: claim()
StakingContract->>StakingContract: Calculate gross rewards
StakingContract->>StakingContract: Deduct commission
StakingContract->>StakingContract: Update validator accrued commission
StakingContract->>Treasury: distributeReward(user, netAmount)
Treasury->>User: Transfer net rewards
Validator->>StakingContract: requestCommissionClaim()
Note over StakingContract: 7-day timelock
Validator->>StakingContract: finalizeCommissionClaim()
StakingContract->>Treasury: distributeReward(validator, commission)
Treasury->>Validator: Transfer commission
```
--------------------------------
### Solidity: Create and Configure Arc Token with Sales
Source: https://context7.com/plumenetwork/contracts/llms.txt
Deploys and configures an Arc token, including setting up restriction modules, a purchase contract, and enabling token sales. This process involves deploying a RestrictionsRouter, ArcTokenFactory, and the Arc token itself, followed by configuring whitelist restrictions and enabling a token sale through a purchase contract. Dependencies include OpenZeppelin's ERC1967Proxy and various Arc token interfaces.
```solidity
// 1. Deploy RestrictionsRouter (one-time setup)
RestrictionsRouter router = new RestrictionsRouter();
ERC1967Proxy routerProxy = new ERC1967Proxy(
address(router),
abi.encodeWithSelector(RestrictionsRouter.initialize.selector, adminAddress)
);
// 2. Deploy ArcTokenFactory
ArcTokenFactory factory = new ArcTokenFactory();
ERC1967Proxy factoryProxy = new ERC1967Proxy(
address(factory),
abi.encodeWithSelector(ArcTokenFactory.initialize.selector, address(routerProxy))
);
// 3. Create new Arc token (deploys unique implementation + proxy + restriction modules)
address tokenProxy = IArcTokenFactory(address(factoryProxy)).createToken(
"Real Estate Fund I", // name
"aRE1", // symbol
1000000e18, // initial supply (1M tokens)
usdcAddress, // yield token (USDC)
treasuryAddress, // initial holder
18, // decimals
"ipfs://Qm.../metadata.json" // tokenURI
);
// 4. Configure whitelist restrictions for the token
address whitelistModule = ArcToken(tokenProxy).getRestrictionModule(
keccak256("TRANSFER_RESTRICTION_TYPE")
);
WhitelistRestrictions(whitelistModule).setTransfersAllowed(true);
WhitelistRestrictions(whitelistModule).batchAddToWhitelist([
buyerAddress1,
buyerAddress2,
purchaseContractAddress
]);
// 5. Deploy and configure purchase contract
ArcTokenPurchase purchase = new ArcTokenPurchase();
ERC1967Proxy purchaseProxy = new ERC1967Proxy(
address(purchase),
abi.encodeWithSelector(
ArcTokenPurchase.initialize.selector,
adminAddress,
address(factoryProxy)
)
);
IArcTokenPurchase(address(purchaseProxy)).setPurchaseToken(usdcAddress);
// 6. Enable token sale
IERC20(tokenProxy).transfer(address(purchaseProxy), 500000e18); // Transfer 500k tokens for sale
IArcTokenPurchase(address(purchaseProxy)).enableToken(
tokenProxy,
500000e18, // 500k tokens for sale
10e6 // price: 10 USDC (6 decimals) per token
);
```
--------------------------------
### Arc Token: Upgrade Token Implementations (Solidity)
Source: https://context7.com/plumenetwork/contracts/llms.txt
Explains the process of upgrading Arc Token implementations to a new version. This involves deploying a new implementation contract, whitelisting it in the factory, and then initiating the upgrade for a specific token proxy, ensuring state persistence.
```solidity
// Deploy new ArcToken implementation
ArcToken newImplementation = new ArcToken();
// Whitelist the new implementation in factory
bytes32 codeHash;
assembly {
codeHash := extcodehash(newImplementation)
}
IArcTokenFactory(address(factoryProxy)).whitelistImplementation(address(newImplementation));
// Upgrade a specific token to the new implementation
IArcTokenFactory(address(factoryProxy)).upgradeToken(
tokenProxy,
address(newImplementation)
);
// Verify upgrade
address currentImpl = IArcTokenFactory(address(factoryProxy)).getTokenImplementation(tokenProxy);
require(currentImpl == address(newImplementation), "Upgrade failed");
// Token continues operating with same state, new logic
uint256 balance = IERC20(tokenProxy).balanceOf(msg.sender);
console.log("Balance after upgrade:", balance);
```
--------------------------------
### ManagementFacet View Functions
Source: https://github.com/plumenetwork/contracts/blob/main/plume/README.md
Functions to retrieve current system parameter settings. These include the minimum stake amount and the unstaking cooldown duration.
```Solidity
function getMinStakeAmount() returns uint256
function getCooldownInterval() returns uint256
```
--------------------------------
### Execute Operations with Signatures for Gasless Transactions in Solidity
Source: https://context7.com/plumenetwork/contracts/llms.txt
This snippet outlines the process of creating signed operations off-chain using a user's private key and then executing these operations on-chain via a relayer using a smart wallet. It covers single operations, batch operations, and nonce checking.
```solidity
// User creates signed operation off-chain
bytes32 operationHash = keccak256(abi.encodePacked(
smartWallet,
targetContract,
value,
data,
nonce,
deadline
));
bytes32 ethSignedHash = keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
operationHash
));
(uint8 v, bytes32 r, bytes32 s) = vm.sign(userPrivateKey, ethSignedHash);
bytes memory signature = abi.encodePacked(r, s, v);
// Relayer executes operation with user's signature
ISmartWallet(smartWallet).executeWithSignature(
targetContract,
value,
data,
nonce,
deadline,
signature
);
// Batch operations
address[] memory targets = [contract1, contract2];
uint256[] memory values = [0, 0];
bytes[] memory datas = [data1, data2];
ISmartWallet(smartWallet).executeBatchWithSignature(
targets,
values,
datas,
nonce,
deadline,
signature
);
// Check nonce before signing
uint256 currentNonce = ISmartWallet(smartWallet).getNonce(msg.sender);
```