How It Works
Lifecycle, permissions, and execution rules
Every alliance follows a strict finite-state model. You cannot perform actions from the wrong state even if UI still shows inputs.
State: Funding
Participants deposit ERC20 and coordinate acquisition governance until target is reached or deadline expires.
- Allowed: `deposit`, `cancelFunding`, `voteToAcquire`, `resetAcquisitionProposal`, `buyNFT`
- Blocked: sale voting and emergency withdrawal actions
- Key checks: participant role, allowance, remaining target, acquisition tuple consistency, quorum, deadlines
State: Acquired
Alliance holds NFT and governance actions are open.
- Allowed: `voteToSell`, `resetSaleProposal`, `executeSale`, `voteEmergencyWithdraw`, `emergencyWithdrawNFT`
- Blocked: `deposit`, `cancelFunding`
- Key checks: vote quorum, sale deadline, proposal consistency
State: Closed
Terminal state after sale execution, emergency withdrawal, or failed funding closure.
- Allowed conditionally: `withdrawRefund` only if funding failure path was activated
- `withdrawRefund` is available even when contract pause is active
- No transition back to Funding
Role model
- Participant: funding and governance actions.
- Owner: pause/unpause administration.
- Non-participant: read-only access.
Common action failures and meaning
- `alliance is not in Funding state`: current state is Acquired or Closed.
- `amount exceeds remaining target`: target already reached.
- `quorum not reached`: proposal has not accumulated enough weighted votes yet.
- `no acquisition proposal` or `acquisition expired`: buy/reset called outside active acquisition window.
- `unsupported token`: token transfer amount changed unexpectedly (fee/rebase/non-standard behavior).
- `only participant`: wallet is not in participant list.
- `seller not owner` or transfer failures: wrong seller/NFT approval context.
Operational best practices
- Always read state and remaining target before signing transactions.
- Use one test wallet per role during QA to avoid accidental cross-role confusion.
- Treat Hardhat restart as full chain reset and redeploy immediately.