diff --git a/dagger/contracts/Readme.md b/dagger/contracts/Readme.md new file mode 100644 index 00000000..687b0acc --- /dev/null +++ b/dagger/contracts/Readme.md @@ -0,0 +1,181 @@ +Dagger Contracts in Nim +======================= + +Nim API for the [Dagger smart contracts][1]. + +Usage +----- + +For a global overview of the steps involved in starting and fulfilling a +storage contract, see [Dagger Contracts][1]. + +Smart contract +-------------- + +Connecting to the smart contract on an Ethereum node: + +```nim +import dagger/contracts +import ethers + +let address = # fill in address where the contract was deployed +let provider = JsonRpcProvider.new("ws://localhost:8545") +let storage = Storage.new(address, provider) +``` + +Setup client and host so that they can sign transactions; here we use the first +two accounts on the Ethereum node: + +```nim +let accounts = await provider.listAccounts() +let client = provider.getSigner(accounts[0]) +let host = provider.getSigner(accounts[1]) +``` + +Collateral +---------- + +Hosts need to put up collateral before participating in storage contracts. + +A host can learn about the amount of collateral that is required: +```nim +let collateralAmount = await storage.collateralAmount() +``` + +The host then needs to prepare a payment to the smart contract by calling the +`approve` method on the [ERC20 token][2]. Note that interaction with ERC20 +contracts is not part of this library. + +After preparing the payment, the host can deposit collateral: +```nim +await storage + .connect(host) + .deposit(collateralAmount) +``` + +When a host is not participating in storage offers or contracts, it can withdraw +its collateral: + +``` +await storage + .connect(host) + .withdraw() +``` + +Storage requests +---------------- + +Creating a request for storage: + +```nim +let request : StorageRequest = ( + client: # address of the client requesting storage + duration: # duration of the contract in seconds + size: # size in bytes + contentHash: # SHA256 hash of the content that's going to be stored + proofProbability: # require a storage proof roughly once every N periods + maxPrice: # maximum price the client is willing to pay + expiry: # expiration time of the request (in unix time) + nonce: # random nonce to differentiate between similar requests +) +``` + +When a client wants to submit this request to the network, it needs to pay the +maximum price to the smart contract in advance. The difference between the +maximum price and the offered price will be reimbursed later. To prepare, the +client needs to call the `approve` method on the [ERC20 token][2]. Note that +interaction with ERC20 contracts is not part of this library. + +Once the payment has been prepared, the client can submit the request to the +network: + +```nim +await storage + .connect(client) + .requestStorage(request) +``` + +Storage offers +-------------- + +Creating a storage offer: + +```nim +let offer: StorageOffer = ( + host: # address of the host that is offering storage + requestId: request.id, + price: # offered price (in number of tokens) + expiry: # expiration time of the offer (in unix time) +) +``` + +Hosts submits an offer: + +```nim +await storage + .connect(host) + .offerStorage(offer) +``` + +Client selects an offer: + +```nim +await storage + .connect(client) + .selectOffer(offer.id) +``` + +Starting and finishing a storage contract +----------------------------------------- + +The host whose offer got selected can start the storage contract once it +received the data that needs to be stored: + +```nim +await storage + .connect(host) + .startContract(offer.id) +``` + +Once the storage contract is finished, the host can release payment: + +```nim +await storage + .connect(host) + .finishContract(id) +``` + +Storage proofs +-------------- + +Time is divided into periods, and each period a storage proof may be required +from the host. The odds of requiring a storage proof are negotiated through the +storage request. For more details about the timing of storage proofs, please +refer to the [design document][3]. + +At the start of each period of time, the host can check whether a storage proof +is required: + +```nim +let isProofRequired = await storage.isProofRequired(offer.id) +``` + +If a proof is required, the host can submit it before the end of the period: + +```nim +await storage + .connect(host) + .submitProof(id, proof) +``` + +If a proof is not submitted, then a validator can mark a proof as missing: + +```nim +await storage + .connect(validator) + .markProofAsMissing(id, period) +``` + +[1]: https://github.com/status-im/dagger-contracts/ +[2]: https://ethereum.org/en/developers/docs/standards/tokens/erc-20/ +[3]: https://github.com/status-im/dagger-research/blob/main/design/storage-proof-timing.md