From b2dafc88fe905e353b37ce7044cb6576500014ef Mon Sep 17 00:00:00 2001
From: erhant
Date: Wed, 18 Dec 2024 15:01:35 +0300
Subject: [PATCH] docs and abis updated
---
abis/Swan.json | 2 +-
abis/SwanAgent.json | 2 +-
abis/SwanArtifact.json | 2 +-
abis/parseAbi.js | 2 +-
docs/src/README.md | 49 +-
docs/src/SUMMARY.md | 10 +-
docs/src/src/README.md | 9 +-
docs/src/src/Swan.sol/constants.Swan.md | 16 +-
docs/src/src/Swan.sol/contract.Swan.md | 38 +-
.../src/SwanAgent.sol/contract.SwanAgent.md | 534 ++++++++++++++++++
.../contract.SwanAgentFactory.md | 22 +
.../SwanArtifact.sol/contract.SwanArtifact.md | 40 ++
.../contract.SwanArtifactFactory.md | 20 +
.../SwanManager.sol/abstract.SwanManager.md | 2 +-
.../struct.SwanMarketParameters.md | 5 +-
export-abis.sh | 1 +
test/contracts/WETH9.sol | 1 +
17 files changed, 702 insertions(+), 53 deletions(-)
create mode 100644 docs/src/src/SwanAgent.sol/contract.SwanAgent.md
create mode 100644 docs/src/src/SwanAgent.sol/contract.SwanAgentFactory.md
create mode 100644 docs/src/src/SwanArtifact.sol/contract.SwanArtifact.md
create mode 100644 docs/src/src/SwanArtifact.sol/contract.SwanArtifactFactory.md
diff --git a/abis/Swan.json b/abis/Swan.json
index 2da2ca3..a96b8ec 100644
--- a/abis/Swan.json
+++ b/abis/Swan.json
@@ -1123,4 +1123,4 @@
}
]
}
-]
+]
\ No newline at end of file
diff --git a/abis/SwanAgent.json b/abis/SwanAgent.json
index 805a942..761b408 100644
--- a/abis/SwanAgent.json
+++ b/abis/SwanAgent.json
@@ -621,4 +621,4 @@
}
]
}
-]
+]
\ No newline at end of file
diff --git a/abis/SwanArtifact.json b/abis/SwanArtifact.json
index aeb4bed..b94e0d5 100644
--- a/abis/SwanArtifact.json
+++ b/abis/SwanArtifact.json
@@ -563,4 +563,4 @@
}
]
}
-]
+]
\ No newline at end of file
diff --git a/abis/parseAbi.js b/abis/parseAbi.js
index e4e2cfe..dcb64f7 100644
--- a/abis/parseAbi.js
+++ b/abis/parseAbi.js
@@ -28,7 +28,7 @@ fs.readFile(filename, "utf8", (err, data) => {
process.exit(1);
}
- console.log("ABI extracted and written to abi.json");
+ console.log("ABI extracted and written to", filename);
});
} catch (parseErr) {
console.error(`Error parsing JSON: ${parseErr}`);
diff --git a/docs/src/README.md b/docs/src/README.md
index 2c88f81..88f7afe 100644
--- a/docs/src/README.md
+++ b/docs/src/README.md
@@ -11,11 +11,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
Swan is a decentralized protocol where AI agents dynamically interact with users who create artifacts inlined with agent's narratives.
## Installation
-Install everything with:
+First, make sure you have the requirements:
+
+- We are using [Foundry](https://book.getfoundry.sh/), so make sure you [install](https://book.getfoundry.sh/getting-started/installation) it first.
+- Upgradable contracts make use of [NodeJS](https://nodejs.org/en), so you should [install](https://nodejs.org/en/download/package-manager) that as well.
+
+Clone the repository:
+
+```sh
+git clone git@github.com:firstbatchxyz/swan-contracts.git
+```
+
+Install dependencies with:
```sh
forge install
@@ -27,12 +50,22 @@ Compile the contracts with:
forge clean && forge build
```
+### Upgradability
+
We are using [openzeppelin-foundry-upgrades](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades) library. To make sure upgrades are **safe**, you must do one of the following before you run `forge script` or `forge test` (as per their [docs](https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades?tab=readme-ov-file#before-running)):
- `forge clean` beforehand, e.g. `forge clean && forge test`
- include `--force` option when running, e.g. `forge test --force`
-To update Swan in case any library is updated, you can do:
+> Note that for some users this may fail (see [issue](https://github.com/firstbatchxyz/dria-oracle-contracts/issues/16)) due to a missing NPM package called `@openzeppelin/upgrades-core`. To fix it, do:
+>
+> ```sh
+> npm install @openzeppelin/upgrades-core@latest -g
+> ```
+
+### Updates
+
+To update contracts to the latest library versions, use:
```sh
forge update
@@ -150,20 +183,18 @@ forge clean && forge snapshot
You can see the snapshot `.gas-snapshot` file in the current directory.
-## Format
+## Documentation
-Format code with:
+We have auto-generated documentation under the [`docs`](./docs) folder, generated with the following command:
```sh
-forge fmt
+forge doc
```
-## Documentation
-
-We have auto-generated documentation under the [`docs`](./docs) folder, generated with the following command:
+We provide an MDBook template over it, which you can open via:
```sh
-forge doc
+cd docs && mdbook serve --open
```
## License
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
index 1f1917a..2ee1a3f 100644
--- a/docs/src/SUMMARY.md
+++ b/docs/src/SUMMARY.md
@@ -1,13 +1,11 @@
# Summary
- [Home](README.md)
# src
- - [❱ mock](src/mock/README.md)
- - [SwanV2](src/mock/SvanV2.sol/contract.SwanV2.md)
- - [AIAgentFactory](src/AIAgent.sol/contract.AIAgentFactory.md)
- - [AIAgent](src/AIAgent.sol/contract.AIAgent.md)
- - [ArtifactFactory](src/Artifact.sol/contract.ArtifactFactory.md)
- - [Artifact](src/Artifact.sol/contract.Artifact.md)
- [Swan](src/Swan.sol/contract.Swan.md)
- [Swan constants](src/Swan.sol/constants.Swan.md)
+ - [SwanAgentFactory](src/SwanAgent.sol/contract.SwanAgentFactory.md)
+ - [SwanAgent](src/SwanAgent.sol/contract.SwanAgent.md)
+ - [SwanArtifactFactory](src/SwanArtifact.sol/contract.SwanArtifactFactory.md)
+ - [SwanArtifact](src/SwanArtifact.sol/contract.SwanArtifact.md)
- [SwanMarketParameters](src/SwanManager.sol/struct.SwanMarketParameters.md)
- [SwanManager](src/SwanManager.sol/abstract.SwanManager.md)
diff --git a/docs/src/src/README.md b/docs/src/src/README.md
index f769760..e12172f 100644
--- a/docs/src/src/README.md
+++ b/docs/src/src/README.md
@@ -1,12 +1,11 @@
# Contents
-- [mock](/src/mock)
-- [AIAgentFactory](AIAgent.sol/contract.AIAgentFactory.md)
-- [AIAgent](AIAgent.sol/contract.AIAgent.md)
-- [ArtifactFactory](Artifact.sol/contract.ArtifactFactory.md)
-- [Artifact](Artifact.sol/contract.Artifact.md)
- [Swan](Swan.sol/contract.Swan.md)
- [Swan constants](Swan.sol/constants.Swan.md)
+- [SwanAgentFactory](SwanAgent.sol/contract.SwanAgentFactory.md)
+- [SwanAgent](SwanAgent.sol/contract.SwanAgent.md)
+- [SwanArtifactFactory](SwanArtifact.sol/contract.SwanArtifactFactory.md)
+- [SwanArtifact](SwanArtifact.sol/contract.SwanArtifact.md)
- [SwanMarketParameters](SwanManager.sol/struct.SwanMarketParameters.md)
- [SwanManager](SwanManager.sol/abstract.SwanManager.md)
diff --git a/docs/src/src/Swan.sol/constants.Swan.md b/docs/src/src/Swan.sol/constants.Swan.md
index 6b85ff3..2fbe3a3 100644
--- a/docs/src/src/Swan.sol/constants.Swan.md
+++ b/docs/src/src/Swan.sol/constants.Swan.md
@@ -1,20 +1,24 @@
# Constants
-[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/c9444a397017d961972cbbff400b67d973ffe956/src/Swan.sol)
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/Swan.sol)
+
+### SwanAgentPurchaseOracleProtocol
+*Protocol string for Swan Purchase CRONs, checked in the Oracle.*
-### SwanAIAgentPurchaseOracleProtocol
```solidity
-bytes32 constant SwanAIAgentPurchaseOracleProtocol = "swan-agent-purchase/0.1.0";
+bytes32 constant SwanAgentPurchaseOracleProtocol = "swan-agent-purchase/0.1.0";
```
-### SwanAIAgentStateOracleProtocol
+### SwanAgentStateOracleProtocol
+*Protocol string for Swan State CRONs, checked in the Oracle.*
+
```solidity
-bytes32 constant SwanAIAgentStateOracleProtocol = "swan-agent-state/0.1.0";
+bytes32 constant SwanAgentStateOracleProtocol = "swan-agent-state/0.1.0";
```
### BASIS_POINTS
-*Used to calculate the fee for the AI agent to be able to compute correct amount.*
+*Used to calculate the fee for the agent to be able to compute correct amount.*
```solidity
diff --git a/docs/src/src/Swan.sol/contract.Swan.md b/docs/src/src/Swan.sol/contract.Swan.md
index 5b49138..1c97fa6 100644
--- a/docs/src/src/Swan.sol/contract.Swan.md
+++ b/docs/src/src/Swan.sol/contract.Swan.md
@@ -1,5 +1,5 @@
# Swan
-[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/c9444a397017d961972cbbff400b67d973ffe956/src/Swan.sol)
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/Swan.sol)
**Inherits:**
[SwanManager](/src/SwanManager.sol/abstract.SwanManager.md), UUPSUpgradeable
@@ -7,11 +7,11 @@
## State Variables
### agentFactory
-Factory contract to deploy AI Agents.
+Factory contract to deploy Agents.
```solidity
-AIAgentFactory public agentFactory;
+SwanAgentFactory public agentFactory;
```
@@ -20,7 +20,7 @@ Factory contract to deploy Artifact tokens.
```solidity
-ArtifactFactory public artifactFactory;
+SwanArtifactFactory public artifactFactory;
```
@@ -109,21 +109,21 @@ function transferOwnership(address newOwner) public override onlyOwner;
### createAgent
-Creates a new AI agent.
+Creates a new agent.
-*Emits a `AIAgentCreated` event.*
+*Emits a `AgentCreated` event.*
```solidity
function createAgent(string calldata _name, string calldata _description, uint96 _feeRoyalty, uint256 _amountPerRound)
external
- returns (AIAgent);
+ returns (SwanAgent);
```
**Returns**
|Name|Type|Description|
|----|----|-----------|
-|``|`AIAgent`|address of the new AI agent.|
+|``|`SwanAgent`|address of the new agent.|
### list
@@ -159,7 +159,7 @@ function relist(address _artifact, address _agent, uint256 _price) external;
|Name|Type|Description|
|----|----|-----------|
|`_artifact`|`address`|address of the artifact.|
-|`_agent`|`address`|new AIAgent for the artifact.|
+|`_agent`|`address`|new agent for the artifact.|
|`_price`|`uint256`|new price of the token.|
@@ -185,7 +185,7 @@ function purchase(address _artifact) external;
### setFactories
-Set the factories for AI Agents and Artifacts.
+Set the factories for Agents and Artifacts.
*Only callable by owner.*
@@ -197,8 +197,8 @@ function setFactories(address _agentFactory, address _artifactFactory) external
|Name|Type|Description|
|----|----|-----------|
-|`_agentFactory`|`address`|new AIAgentFactory address|
-|`_artifactFactory`|`address`|new ArtifactFactory address|
+|`_agentFactory`|`address`|new SwanAgentFactory address|
+|`_artifactFactory`|`address`|new SwanArtifactFactory address|
### getListingPrice
@@ -255,16 +255,16 @@ An `agent` purchased an artifact.
event ArtifactSold(address indexed owner, address indexed agent, address indexed artifact, uint256 price);
```
-### AIAgentCreated
-A new AI agent is created.
+### AgentCreated
+A new agent is created.
-*`owner` is the owner of the AI agent.*
+*`owner` is the owner of the agent.*
-*`agent` is the address of the AI agent.*
+*`agent` is the address of the agent.*
```solidity
-event AIAgentCreated(address indexed owner, address indexed agent);
+event AgentCreated(address indexed owner, address indexed agent);
```
## Errors
@@ -317,13 +317,13 @@ Holds the listing information.
*`createdAt` is the timestamp of the artifact creation.*
-*`feeRoyalty` is the royalty fee of the AIAgent.*
+*`feeRoyalty` is the royalty fee of the agent.*
*`price` is the price of the artifact.*
*`seller` is the address of the creator of the artifact.*
-*`agent` is the address of the AIAgent.*
+*`agent` is the address of the agent.*
*`round` is the round in which the artifact is created.*
diff --git a/docs/src/src/SwanAgent.sol/contract.SwanAgent.md b/docs/src/src/SwanAgent.sol/contract.SwanAgent.md
new file mode 100644
index 0000000..17b1eba
--- /dev/null
+++ b/docs/src/src/SwanAgent.sol/contract.SwanAgent.md
@@ -0,0 +1,534 @@
+# SwanAgent
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/SwanAgent.sol)
+
+**Inherits:**
+Ownable
+
+Agent is responsible for buying the artifacts from Swan.
+
+
+## State Variables
+### swan
+Swan contract.
+
+
+```solidity
+Swan public immutable swan;
+```
+
+
+### createdAt
+Timestamp when the contract is deployed.
+
+
+```solidity
+uint256 public immutable createdAt;
+```
+
+
+### marketParameterIdx
+Holds the index of the Swan market parameters at the time of deployment.
+
+*When calculating the round, we will use this index to determine the start interval.*
+
+
+```solidity
+uint256 public immutable marketParameterIdx;
+```
+
+
+### name
+Agent name.
+
+
+```solidity
+string public name;
+```
+
+
+### description
+Agent description, can include backstory, behavior and objective together.
+
+
+```solidity
+string public description;
+```
+
+
+### state
+State of the agent.
+
+*Only updated by the oracle via `updateState`.*
+
+
+```solidity
+bytes public state;
+```
+
+
+### feeRoyalty
+Royalty fees for the agent.
+
+
+```solidity
+uint96 public feeRoyalty;
+```
+
+
+### amountPerRound
+The max amount of money the agent can spend per round.
+
+
+```solidity
+uint256 public amountPerRound;
+```
+
+
+### inventory
+The artifacts that the agent has.
+
+
+```solidity
+mapping(uint256 round => address[] artifacts) public inventory;
+```
+
+
+### spendings
+Amount of money spent on each round.
+
+
+```solidity
+mapping(uint256 round => uint256 spending) public spendings;
+```
+
+
+### oraclePurchaseRequests
+Oracle requests for each round about item purchases.
+
+*A taskId of 0 means no request has been made.*
+
+
+```solidity
+mapping(uint256 round => uint256 taskId) public oraclePurchaseRequests;
+```
+
+
+### oracleStateRequests
+Oracle requests for each round about agent state updates.
+
+*A taskId of 0 means no request has been made.*
+
+*A non-zero taskId means a request has been made, but not necessarily processed.*
+
+*To see if a task is completed, check `isOracleTaskProcessed`.*
+
+
+```solidity
+mapping(uint256 round => uint256 taskId) public oracleStateRequests;
+```
+
+
+### isOracleRequestProcessed
+Indicates whether a given task has been processed.
+
+*This is used to prevent double processing of the same task.*
+
+
+```solidity
+mapping(uint256 taskId => bool isProcessed) public isOracleRequestProcessed;
+```
+
+
+## Functions
+### onlyAuthorized
+
+Check if the caller is the owner, operator, or Swan.
+
+*Swan is an operator itself, so the first check handles that as well.*
+
+
+```solidity
+modifier onlyAuthorized();
+```
+
+### constructor
+
+Creates an agent.
+
+*`_feeRoyalty` should be between 1 and max agent fee in the swan market parameters.*
+
+*All tokens are approved to the oracle coordinator of operator.*
+
+
+```solidity
+constructor(
+ string memory _name,
+ string memory _description,
+ uint96 _feeRoyalty,
+ uint256 _amountPerRound,
+ address _operator,
+ address _owner
+) Ownable(_owner);
+```
+
+### minFundAmount
+
+The minimum amount of money that the agent must leave within the contract.
+
+*minFundAmount should be `amountPerRound + oracleFee` to be able to make requests.*
+
+
+```solidity
+function minFundAmount() public view returns (uint256);
+```
+
+### oracleResult
+
+Reads the best performing result for a given task id, and parses it as an array of addresses.
+
+
+```solidity
+function oracleResult(uint256 taskId) public view returns (bytes memory);
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`taskId`|`uint256`|task id to be read|
+
+
+### oracleStateRequest
+
+Calls the LLMOracleCoordinator & pays for the oracle fees to make a state update request.
+
+*Works only in `Withdraw` phase.*
+
+*Calling again in the same round will overwrite the previous request.
+The operator must check that there is no request in beforehand,
+so to not overwrite an existing request of the owner.*
+
+
+```solidity
+function oracleStateRequest(bytes calldata _input, bytes calldata _models) external onlyAuthorized;
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`_input`|`bytes`|input to the LLMOracleCoordinator.|
+|`_models`|`bytes`|models to be used for the oracle.|
+
+
+### oraclePurchaseRequest
+
+Calls the LLMOracleCoordinator & pays for the oracle fees to make a purchase request.
+
+*Works only in `Buy` phase.*
+
+*Calling again in the same round will overwrite the previous request.
+The operator must check that there is no request in beforehand,
+so to not overwrite an existing request of the owner.*
+
+
+```solidity
+function oraclePurchaseRequest(bytes calldata _input, bytes calldata _models) external onlyAuthorized;
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`_input`|`bytes`|input to the LLMOracleCoordinator.|
+|`_models`|`bytes`|models to be used for the oracle.|
+
+
+### updateState
+
+Function to update the AI agent state.
+
+*Works only in `Withdraw` phase.*
+
+*Can be called multiple times within a single round, although is not expected to be done so.*
+
+
+```solidity
+function updateState() external onlyAuthorized;
+```
+
+### purchase
+
+Function to buy the artifacts from the Swan.
+
+*Works only in `Buy` phase.*
+
+*Can be called multiple times within a single round, although is not expected to be done so.*
+
+*This is not expected to revert if the oracle works correctly.*
+
+
+```solidity
+function purchase() external onlyAuthorized;
+```
+
+### withdraw
+
+Function to withdraw the tokens from the contract.
+
+*If the current phase is `Withdraw` agent owner can withdraw any amount of tokens.*
+
+*If the current phase is not `Withdraw` agent owner has to leave at least `minFundAmount` in the contract.*
+
+
+```solidity
+function withdraw(uint96 _amount) public onlyAuthorized;
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`_amount`|`uint96`|amount to withdraw.|
+
+
+### treasury
+
+Alias to get the token balance of AI agent.
+
+
+```solidity
+function treasury() public view returns (uint256);
+```
+**Returns**
+
+|Name|Type|Description|
+|----|----|-----------|
+|``|`uint256`|token balance|
+
+
+### _checkRoundPhase
+
+Checks that we are in the given phase, and returns both round and phase.
+
+
+```solidity
+function _checkRoundPhase(Phase _phase) internal view returns (uint256, Phase);
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`_phase`|`Phase`|expected phase.|
+
+
+### _computeCycleTime
+
+Computes cycle time by using intervals from given market parameters.
+
+*Used in 'computePhase()' function.*
+
+
+```solidity
+function _computeCycleTime(SwanMarketParameters memory params) internal pure returns (uint256);
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`params`|`SwanMarketParameters`|Market parameters of the Swan.|
+
+**Returns**
+
+|Name|Type|Description|
+|----|----|-----------|
+|``|`uint256`|the total cycle time that is `listingInterval + buyInterval + withdrawInterval`.|
+
+
+### _computePhase
+
+Function to compute the current round, phase and time until next phase w.r.t given market parameters.
+
+
+```solidity
+function _computePhase(SwanMarketParameters memory params, uint256 elapsedTime)
+ internal
+ pure
+ returns (uint256, Phase, uint256);
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`params`|`SwanMarketParameters`|Market parameters of the Swan.|
+|`elapsedTime`|`uint256`|Time elapsed that computed in 'getRoundPhase()' according to the timestamps of each round.|
+
+**Returns**
+
+|Name|Type|Description|
+|----|----|-----------|
+|``|`uint256`|round, phase, time until next phase|
+|``|`Phase`||
+|``|`uint256`||
+
+
+### getRoundPhase
+
+Function to return the current round, elapsed round and the current phase according to the current time.
+
+*Each round is composed of three phases in order: Listing, Buy, Withdraw.*
+
+*Internally, it computes the intervals from market parameters at the creation of this AI agent, until now.*
+
+*If there are many parameter changes throughout the life of this AI agent, this may cost more GAS.*
+
+
+```solidity
+function getRoundPhase() public view returns (uint256, Phase, uint256);
+```
+**Returns**
+
+|Name|Type|Description|
+|----|----|-----------|
+|``|`uint256`|round, phase, time until next phase|
+|``|`Phase`||
+|``|`uint256`||
+
+
+### setFeeRoyalty
+
+Function to set feeRoyalty.
+
+*Only callable by the owner.*
+
+*Only callable in withdraw phase.*
+
+
+```solidity
+function setFeeRoyalty(uint96 newFeeRoyalty) public onlyOwner;
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`newFeeRoyalty`|`uint96`|must be between 1 and 100.|
+
+
+### setAmountPerRound
+
+Function to set the amountPerRound.
+
+*Only callable by the owner.*
+
+*Only callable in withdraw phase.*
+
+
+```solidity
+function setAmountPerRound(uint256 _amountPerRound) external onlyOwner;
+```
+**Parameters**
+
+|Name|Type|Description|
+|----|----|-----------|
+|`_amountPerRound`|`uint256`|new amountPerRound.|
+
+
+## Events
+### StateRequest
+Emitted when a state update request is made.
+
+
+```solidity
+event StateRequest(uint256 indexed taskId, uint256 indexed round);
+```
+
+### PurchaseRequest
+Emitted when a purchase request is made.
+
+
+```solidity
+event PurchaseRequest(uint256 indexed taskId, uint256 indexed round);
+```
+
+### Purchase
+Emitted when a purchase is made.
+
+
+```solidity
+event Purchase(uint256 indexed taskId, uint256 indexed round);
+```
+
+### StateUpdate
+Emitted when the state is updated.
+
+
+```solidity
+event StateUpdate(uint256 indexed taskId, uint256 indexed round);
+```
+
+## Errors
+### MinFundSubceeded
+The `value` is less than `minFundAmount`
+
+
+```solidity
+error MinFundSubceeded(uint256 value);
+```
+
+### InvalidFee
+Given fee is invalid, e.g. not within the range.
+
+
+```solidity
+error InvalidFee(uint256 fee);
+```
+
+### BuyLimitExceeded
+Price limit exceeded for this round
+
+
+```solidity
+error BuyLimitExceeded(uint256 have, uint256 want);
+```
+
+### InvalidPhase
+Invalid phase
+
+
+```solidity
+error InvalidPhase(Phase have, Phase want);
+```
+
+### Unauthorized
+Unauthorized caller.
+
+
+```solidity
+error Unauthorized(address caller);
+```
+
+### TaskNotRequested
+No task request has been made yet.
+
+
+```solidity
+error TaskNotRequested();
+```
+
+### TaskAlreadyProcessed
+The task was already processed, via `purchase` or `updateState`.
+
+
+```solidity
+error TaskAlreadyProcessed();
+```
+
+## Enums
+### Phase
+Phase of the purchase loop.
+
+
+```solidity
+enum Phase {
+ Listing,
+ Buy,
+ Withdraw
+}
+```
+
diff --git a/docs/src/src/SwanAgent.sol/contract.SwanAgentFactory.md b/docs/src/src/SwanAgent.sol/contract.SwanAgentFactory.md
new file mode 100644
index 0000000..5a5621f
--- /dev/null
+++ b/docs/src/src/SwanAgent.sol/contract.SwanAgentFactory.md
@@ -0,0 +1,22 @@
+# SwanAgentFactory
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/SwanAgent.sol)
+
+Factory contract to deploy Agent contracts.
+
+*This saves from contract space for Swan.*
+
+
+## Functions
+### deploy
+
+
+```solidity
+function deploy(
+ string memory _name,
+ string memory _description,
+ uint96 _feeRoyalty,
+ uint256 _amountPerRound,
+ address _owner
+) external returns (SwanAgent);
+```
+
diff --git a/docs/src/src/SwanArtifact.sol/contract.SwanArtifact.md b/docs/src/src/SwanArtifact.sol/contract.SwanArtifact.md
new file mode 100644
index 0000000..86f8551
--- /dev/null
+++ b/docs/src/src/SwanArtifact.sol/contract.SwanArtifact.md
@@ -0,0 +1,40 @@
+# SwanArtifact
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/SwanArtifact.sol)
+
+**Inherits:**
+ERC721, Ownable
+
+Artifact is an ERC721 token with a single token supply.
+
+
+## State Variables
+### createdAt
+Creation time of the token
+
+
+```solidity
+uint256 public createdAt;
+```
+
+
+### description
+Description of the token
+
+
+```solidity
+bytes public description;
+```
+
+
+## Functions
+### constructor
+
+Constructor sets properties of the token.
+
+
+```solidity
+constructor(string memory _name, string memory _symbol, bytes memory _description, address _owner, address _operator)
+ ERC721(_name, _symbol)
+ Ownable(_owner);
+```
+
diff --git a/docs/src/src/SwanArtifact.sol/contract.SwanArtifactFactory.md b/docs/src/src/SwanArtifact.sol/contract.SwanArtifactFactory.md
new file mode 100644
index 0000000..ce0db66
--- /dev/null
+++ b/docs/src/src/SwanArtifact.sol/contract.SwanArtifactFactory.md
@@ -0,0 +1,20 @@
+# SwanArtifactFactory
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/SwanArtifact.sol)
+
+Factory contract to deploy Artifact tokens.
+
+*This saves from contract space for Swan.*
+
+
+## Functions
+### deploy
+
+Deploys a new Artifact token.
+
+
+```solidity
+function deploy(string memory _name, string memory _symbol, bytes memory _description, address _owner)
+ external
+ returns (SwanArtifact);
+```
+
diff --git a/docs/src/src/SwanManager.sol/abstract.SwanManager.md b/docs/src/src/SwanManager.sol/abstract.SwanManager.md
index bd6ceb1..f7b1f23 100644
--- a/docs/src/src/SwanManager.sol/abstract.SwanManager.md
+++ b/docs/src/src/SwanManager.sol/abstract.SwanManager.md
@@ -1,5 +1,5 @@
# SwanManager
-[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/c9444a397017d961972cbbff400b67d973ffe956/src/SwanManager.sol)
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/SwanManager.sol)
**Inherits:**
OwnableUpgradeable
diff --git a/docs/src/src/SwanManager.sol/struct.SwanMarketParameters.md b/docs/src/src/SwanManager.sol/struct.SwanMarketParameters.md
index 98df9f9..903d2a9 100644
--- a/docs/src/src/SwanManager.sol/struct.SwanMarketParameters.md
+++ b/docs/src/src/SwanManager.sol/struct.SwanMarketParameters.md
@@ -1,10 +1,9 @@
# SwanMarketParameters
-[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/c9444a397017d961972cbbff400b67d973ffe956/src/SwanManager.sol)
+[Git Source](https://github.com/firstbatchxyz/swan-contracts/blob/d7951743b0ff97c2f6e978aeabb850c0310d76f3/src/SwanManager.sol)
Collection of market-related parameters.
-*Prevents stack-too-deep.
-TODO: use 256-bit tight-packing here*
+*Prevents stack-too-deep.*
```solidity
diff --git a/export-abis.sh b/export-abis.sh
index 9055e9b..44f2338 100755
--- a/export-abis.sh
+++ b/export-abis.sh
@@ -1,4 +1,5 @@
#!/bin/bash
+forge compile
cp ./out/Swan.sol/Swan.json ./abis/Swan.json
node ./abis/parseAbi.js ./abis/Swan.json
diff --git a/test/contracts/WETH9.sol b/test/contracts/WETH9.sol
index c729534..02f8229 100644
--- a/test/contracts/WETH9.sol
+++ b/test/contracts/WETH9.sol
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-3.0
// Copyright (C) 2015, 2016, 2017 Dapphub
// This program is free software: you can redistribute it and/or modify