Deploying a Subscription Contract
Subscription contracts are deployed by invoking the deploySubscription
function on
the factory contract for a given network. The function uses EIP-1167 to create a proxy then initializes
the contract with supplied parameters.
Deploy Parameters
Deployment involves configuring ERC721 metadata, a default tier (tier 1), reward settings, and curve 0 settings.
struct DeployParams {
/// @dev the client fee basis points
uint16 clientFeeBps;
/// @dev the client fee recipient
address clientFeeRecipient;
/// @dev An identifer to help track deployments via Deploy event. This should only be used in
/// conjunction with the expected owner account to prevent impersonation via front or back running.
bytes deployKey;
/// @dev the init parameters for the collection
InitParams initParams;
/// @dev the init parameters for the default tier (tier 1)
Tier tierParams;
/// @dev the reward parameters for the collection
RewardParams rewardParams;
/// @dev Initial reward curve params (curve 0)
CurveParams curveParams;
}
Native Token vs ERC-20
Subscription contracts support native tokens as well as ERC20 tokens. When minting occurs, the denominated token will be used to purchase time.
Subscription contracts do not support rebasing tokens! Do not use them as the denominated token.
Subscription contracts support fee taking tokens. The number of tokens transferred on mint will factor in the fee.
Immutable Parameters
Some parameters cannot change after deployment. Ensure these are set correctly before deploying.
Determined by Client
clientFeeBps
clientReferralShareBps
Determined by Creator
initParams.name
initParams.symbol
initParams.currencyAddress
rewardParams.slashGracePeriod
rewardParams.slashable
Factory Addresses
Chain | Factory |
---|---|
Base | 0xd79A71657a45F713817cB5366053a7629AF8Fe74 (opens in a new tab) |
Sepolia | 0x0e1869D738E67fE83323013F2C5e44DF1b788E35 (opens in a new tab) |
Deploying
Deploying occurs via the factory contract. The factory contracts are configured in the SDK for all supported networks.
import {
DeployParams, prepareDeployment
} from '@withfabric/protocol-sdks/stpv2';
const params: DeployParams = {
clientFeeBps: 100, // 1% of ingress tokens go to the clientFeeRecipient
clientReferralShareBps: 0, // The number of basis points to share with referrers when no referral code is used
clientFeeRecipient: '0x0', // The client fee recipient
deployKey: "0xbeef", // A unique identifier for the deployment (emitted as an event for indexers)
initParams: {
name: 'Test Sub', // The name of the subscription
symbol: 'FUN', // The symbol of the subscription
contractUri: 'https://example.com/contract', // The URI for the contract metadata (/${tokenId} is appended for tokenURI)
owner: zeroAddress, // The owner of the contract (if 0x0 at deploy, it will be set to msg.sender)
currencyAddress: zeroAddress, // The address of the ERC20 token to use for minting (0x0 for native token, ETH)
globalSupplyCap: 200n, // The maximum number of tokens that can be minted over all tiers
},
rewardParams: {
slashGracePeriod: 3600, // The number of seconds to extend a subscription by for slashing
slashable: false, // Whether rewards are slashable
},
curveParams: {
numPeriods: 20, // The number of periods in the curve
formulaBase: 2, // The base of the formula (2 ^ N periods)
periodSeconds: 3600, // The number of seconds in a period
startTimestamp: 0, // The start timestamp for the curve
minMultiplier: 1, // The minimum multiplier for the curve (0 means no new distribution after the curve ends)
},
tierParams: {
periodDurationSeconds: 3600, // The number of seconds in a period
maxSupply: 10, // The maximum number of tokens that can be minted in this tier
maxCommitmentSeconds: 7200, // The maximum number of seconds a commitment can be made for
startTimestamp: 0, // The start timestamp for the tier
endTimestamp: 0, // The end timestamp for the tier
paused: false, // Whether the tier is paused
transferrable: true, // Whether tokens are transferrable (soulbound)
initialMintPrice: 10000000000000n, // The initial mint price for the tier (cost to join)
pricePerPeriod: 1000000000n, // The price per period for the tier
rewardCurveId: 0, // The reward curve ID for the tier (for reward distribution)
rewardBasisPoints: 500, // The reward basis points for the tier (revshare with pool)
gate: {
gateType: 0, // The gate type (0 = none, 1 = ERC20, 2 = ERC721, 3 = 1155, 4 = STPv2)
contractAddress: zeroAddress, // The address of the gate contract
componentId: 0n, // The component ID for the gate (for 1155 or STPv2 [tier id])
balanceMin: 0n // The minimum balance required to pass the gate
}
}
};
// Prepare/simulate the deployment and return an async function that can be used to execute it
const deploy = await prepareDeployment(params);
// Execute the transaction
const { receipt, contractAddress } = await deploy();