Creating a Signals Board
Board creation is a two-phase process. First, deploy the board through the SignalsFactory with a complete BoardConfig. Then, optionally attach an incentives pool before the board opens. Acceptance criteria, locking parameters, and decay curves are immutable after deployment.
The board owner can be any address. Setting it to a DAO multisig or governor contract means ownership functions (accepting initiatives, closing the board) require a governance vote, enabling fully decentralized operation.
Deploy through the factory
SignalsFactory factory = SignalsFactory(FACTORY_ADDRESS);
address board = factory.create(config);The factory deploys a minimal proxy (EIP-1167) of the Signals implementation contract and calls initialize() with your config. This emits a BoardCreated event with the new board address.
Example: complete deployment
address board = factory.create(BoardConfig({
version: "0.3.2",
owner: 0xDAO_MULTISIG,
underlyingToken: 0xGOV_TOKEN,
opensAt: block.timestamp + 1 days,
closesAt: 0, // never closes
boardMetadata: Metadata({
title: "Community Priorities",
body: "Signal which initiatives matter most",
attachments: new string[](0)
}),
acceptanceCriteria: AcceptanceCriteria({
permissions: AcceptancePermissions.Permissionless,
thresholdOverride: ThresholdOverride.None,
thresholdPercentTotalSupplyWAD: 0.05e18,
minThreshold: 100_000e18
}),
proposerRequirements: ParticipantRequirements({
token: 0xGOV_TOKEN,
minBalance: 50_000e18,
minHoldingDuration: 0,
minLockAmount: 0
}),
supporterRequirements: ParticipantRequirements({
token: 0xGOV_TOKEN,
minBalance: 0,
minHoldingDuration: 0,
minLockAmount: 1e18
}),
lockingConfig: LockingConfig({
lockInterval: 1 days,
maxLockIntervals: 365,
releaseLockDuration: 0,
inactivityTimeout: 60 days
}),
decayConfig: DecayConfig({
curveType: DecayCurveType.Linear,
params: [0.5e18]
})
}));See Example Configurations for more complete configurations with rationale, or Parameters for the full parameter reference.
Post-deployment configuration
The owner can adjust timing and attach incentives before the board opens:
Signals board = Signals(boardAddress);
// Adjust open time (only before board opens)
board.setOpensAt(newOpenTime);
// Attach incentives pool (only before board opens, can only be set once)
board.setIncentivesPool(poolAddress, config);Once the board is open, the owner can extend or set a close time:
// Extend or set close time (only while board is open, must be in the future)
board.setClosesAt(newCloseTime);Attach your incentives pool before the board opens. This cannot be done after participation begins, and can only be set once.
Emergency controls
Both of these are owner-only and require the board to be open:
// Stop new activity, existing locks follow normal redemption rules
board.closeBoard();
// Immediately release all locked tokens regardless of state
board.cancelBoard();closeBoard() sets closesAt to the current timestamp. No new proposals or support, but tokens are redeemed normally. cancelBoard() does the same but additionally flags the board as cancelled, which bypasses all timelocks and allows immediate token withdrawal.
See Closing a Signals Board for details.
