From 131d003a0c98d53599ab1697bd5b64d150fd49d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Uhl=C3=AD=C5=99?= Date: Fri, 14 Apr 2023 11:04:17 +0200 Subject: [PATCH] feat: collateral per slot (#390) Co-authored-by: Eric Mastro --- codex/contracts/Readme.md | 27 ------------ codex/contracts/config.nim | 12 +++--- codex/contracts/market.nim | 12 +++++- codex/contracts/marketplace.nim | 4 -- codex/contracts/requests.nim | 4 +- codex/market.nim | 7 +--- codex/node.nim | 2 + codex/purchasing/states/pending.nim | 1 - codex/rest/api.nim | 9 ++-- codex/rest/json.nim | 6 ++- codex/sales/reservations.nim | 16 ++++--- codex/sales/states/downloading.nim | 1 + codex/sales/states/filling.nim | 4 +- openapi.yaml | 7 ++++ tests/codex/examples.nim | 3 +- tests/codex/helpers/mockmarket.nim | 14 +++---- tests/codex/sales/testreservations.nim | 10 ++--- tests/codex/sales/testsales.nim | 11 ++++- tests/contracts/testCollateral.nim | 32 -------------- tests/contracts/testContracts.nim | 17 ++++---- tests/contracts/testMarket.nim | 58 +++++++------------------- tests/contracts/token.nim | 9 ---- tests/examples.nim | 1 + tests/integration/codexclient.nim | 11 +++-- tests/integration/testIntegration.nim | 26 ++++++------ tests/integration/testproofs.nim | 13 +++--- tests/integration/tokens.nim | 22 ---------- tests/testContracts.nim | 1 - vendor/codex-contracts-eth | 2 +- vendor/questionable | 2 +- 30 files changed, 130 insertions(+), 214 deletions(-) delete mode 100644 tests/contracts/testCollateral.nim delete mode 100644 tests/contracts/token.nim delete mode 100644 tests/integration/tokens.nim diff --git a/codex/contracts/Readme.md b/codex/contracts/Readme.md index 96c96667..cae2a4cc 100644 --- a/codex/contracts/Readme.md +++ b/codex/contracts/Readme.md @@ -32,33 +32,6 @@ 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 config = await marketplace.config() -let collateral = config.collateral.initialAmount -``` - -After preparing the payment, the host can deposit collateral: -```nim -await storage - .connect(host) - .deposit(collateral) -``` - -When a host is not participating in storage offers or contracts, it can withdraw -its collateral: - -``` -await storage - .connect(host) - .withdraw() -``` - Storage requests ---------------- diff --git a/codex/contracts/config.nim b/codex/contracts/config.nim index ffec1d95..d97c7786 100644 --- a/codex/contracts/config.nim +++ b/codex/contracts/config.nim @@ -9,10 +9,10 @@ type collateral*: CollateralConfig proofs*: ProofConfig CollateralConfig* = object - initialAmount*: UInt256 # amount of collateral necessary to fill a slot - minimumAmount*: UInt256 # frees slot when collateral drops below this minimum - slashCriterion*: UInt256 # amount of proofs missed that lead to slashing - slashPercentage*: UInt256 # percentage of the collateral that is slashed + repairRewardPercentage*: uint8 # percentage of remaining collateral slot has after it has been freed + maxNumberOfSlashes*: uint8 # frees slot when the number of slashes reaches this value + slashCriterion*: uint16 # amount of proofs missed that lead to slashing + slashPercentage*: uint8 # percentage of the collateral that is slashed ProofConfig* = object period*: UInt256 # proofs requirements are calculated per period (in seconds) timeout*: UInt256 # mark proofs as missing before the timeout (in seconds) @@ -28,8 +28,8 @@ func fromTuple(_: type ProofConfig, tupl: tuple): ProofConfig = func fromTuple(_: type CollateralConfig, tupl: tuple): CollateralConfig = CollateralConfig( - initialAmount: tupl[0], - minimumAmount: tupl[1], + repairRewardPercentage: tupl[0], + maxNumberOfSlashes: tupl[1], slashCriterion: tupl[2], slashPercentage: tupl[3] ) diff --git a/codex/contracts/market.nim b/codex/contracts/market.nim index 2b1207ab..901cb55a 100644 --- a/codex/contracts/market.nim +++ b/codex/contracts/market.nim @@ -1,4 +1,5 @@ import std/strutils +import pkg/chronicles import pkg/ethers import pkg/ethers/testing import pkg/upraises @@ -8,6 +9,9 @@ import ./marketplace export market +logScope: + topics = "onchain market" + type OnChainMarket* = ref object of Market contract: Marketplace @@ -25,7 +29,8 @@ func new*(_: type OnChainMarket, contract: Marketplace): OnChainMarket = signer: signer, ) -method approveFunds*(market: OnChainMarket, amount: UInt256) {.async.} = +proc approveFunds(market: OnChainMarket, amount: UInt256) {.async.} = + notice "approving tokens", amount let tokenAddress = await market.contract.token() let token = Erc20Token.new(tokenAddress, market.signer) @@ -41,6 +46,7 @@ method mySlots*(market: OnChainMarket): Future[seq[SlotId]] {.async.} = return await market.contract.mySlots() method requestStorage(market: OnChainMarket, request: StorageRequest){.async.} = + await market.approveFunds(request.price()) await market.contract.requestStorage(request) method getRequest(market: OnChainMarket, @@ -93,7 +99,9 @@ method getActiveSlot*( method fillSlot(market: OnChainMarket, requestId: RequestId, slotIndex: UInt256, - proof: seq[byte]) {.async.} = + proof: seq[byte], + collateral: UInt256) {.async.} = + await market.approveFunds(collateral) await market.contract.fillSlot(requestId, slotIndex, proof) method withdrawFunds(market: OnChainMarket, diff --git a/codex/contracts/marketplace.nim b/codex/contracts/marketplace.nim index d578548d..2452ad5f 100644 --- a/codex/contracts/marketplace.nim +++ b/codex/contracts/marketplace.nim @@ -38,10 +38,6 @@ proc slashMisses*(marketplace: Marketplace): UInt256 {.contract, view.} proc slashPercentage*(marketplace: Marketplace): UInt256 {.contract, view.} proc minCollateralThreshold*(marketplace: Marketplace): UInt256 {.contract, view.} -proc deposit*(marketplace: Marketplace, amount: UInt256) {.contract.} -proc withdraw*(marketplace: Marketplace) {.contract.} -proc balanceOf*(marketplace: Marketplace, account: Address): UInt256 {.contract, view.} - proc requestStorage*(marketplace: Marketplace, request: StorageRequest) {.contract.} proc fillSlot*(marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256, proof: seq[byte]) {.contract.} proc withdrawFunds*(marketplace: Marketplace, requestId: RequestId) {.contract.} diff --git a/codex/contracts/requests.nim b/codex/contracts/requests.nim index 188a9032..1e8b94a2 100644 --- a/codex/contracts/requests.nim +++ b/codex/contracts/requests.nim @@ -19,6 +19,7 @@ type duration*: UInt256 proofProbability*: UInt256 reward*: UInt256 + collateral*: UInt256 maxSlotLoss*: uint64 StorageContent* = object cid*: string @@ -84,7 +85,8 @@ func fromTuple(_: type StorageAsk, tupl: tuple): StorageAsk = duration: tupl[2], proofProbability: tupl[3], reward: tupl[4], - maxSlotLoss: tupl[5] + collateral: tupl[5], + maxSlotLoss: tupl[6] ) func fromTuple(_: type StorageContent, tupl: tuple): StorageContent = diff --git a/codex/market.nim b/codex/market.nim index df8caf57..a0afde21 100644 --- a/codex/market.nim +++ b/codex/market.nim @@ -19,10 +19,6 @@ type OnRequestCancelled* = proc(requestId: RequestId) {.gcsafe, upraises:[].} OnRequestFailed* = proc(requestId: RequestId) {.gcsafe, upraises:[].} -method approveFunds*(market: Market, amount: UInt256) {.base, async.} = - ## This is generally needed for On-Chain ERC20 functionality to approve funds transfer to marketplace contract - raiseAssert("not implemented") - method getSigner*(market: Market): Future[Address] {.base, async.} = raiseAssert("not implemented") @@ -67,7 +63,8 @@ method getActiveSlot*( method fillSlot*(market: Market, requestId: RequestId, slotIndex: UInt256, - proof: seq[byte]) {.base, async.} = + proof: seq[byte], + collateral: UInt256) {.base, async.} = raiseAssert("not implemented") method withdrawFunds*(market: Market, diff --git a/codex/node.nim b/codex/node.nim index a77d1091..2e789243 100644 --- a/codex/node.nim +++ b/codex/node.nim @@ -244,6 +244,7 @@ proc requestStorage*(self: CodexNodeRef, nodes: uint, tolerance: uint, reward: UInt256, + collateral: UInt256, expiry = UInt256.none): Future[?!PurchaseId] {.async.} = ## Initiate a request for storage sequence, this might ## be a multistep procedure. @@ -288,6 +289,7 @@ proc requestStorage*(self: CodexNodeRef, duration: duration, proofProbability: proofProbability, reward: reward, + collateral: collateral, maxSlotLoss: tolerance ), content: StorageContent( diff --git a/codex/purchasing/states/pending.nim b/codex/purchasing/states/pending.nim index db2003c1..8ade593c 100644 --- a/codex/purchasing/states/pending.nim +++ b/codex/purchasing/states/pending.nim @@ -10,7 +10,6 @@ method enterAsync(state: PurchasePending) {.async.} = raiseAssert "invalid state" try: - await purchase.market.approveFunds(request.price()) await purchase.market.requestStorage(request) except CatchableError as error: state.switch(PurchaseErrored(error: error)) diff --git a/codex/rest/api.nim b/codex/rest/api.nim index 38e6fb6d..26cbd76f 100644 --- a/codex/rest/api.nim +++ b/codex/rest/api.nim @@ -140,6 +140,7 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter = ## expiry - timestamp, in seconds, when the request expires if the Request does not find requested amount of nodes to host the data ## nodes - minimal number of nodes the content should be stored on ## tolerance - allowed number of nodes that can be lost before pronouncing the content lost + ## colateral - requested collateral from hosts when they fill slot without cid =? cid.tryGet.catch, error: return RestApiResponse.error(Http400, error.msg) @@ -159,6 +160,7 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter = nodes, tolerance, params.reward, + params.collateral, params.expiry), error: return RestApiResponse.error(Http500, error.msg) @@ -269,9 +271,10 @@ proc initRestApi*(node: CodexNodeRef, conf: CodexConf): RestRouter = "/api/codex/v1/sales/availability") do () -> RestApiResponse: ## Add available storage to sell ## - ## size - size of available storage in bytes - ## duration - maximum time the storage should be sold for (in seconds) - ## minPrice - minimum price to be paid (in amount of tokens) + ## size - size of available storage in bytes + ## duration - maximum time the storage should be sold for (in seconds) + ## minPrice - minimum price to be paid (in amount of tokens) + ## maxCollateral - maximum collateral user is willing to pay per filled Slot (in amount of tokens) without contracts =? node.contracts.host: return RestApiResponse.error(Http503, "Sales unavailable") diff --git a/codex/rest/json.nim b/codex/rest/json.nim index c578ef9f..1a7941eb 100644 --- a/codex/rest/json.nim +++ b/codex/rest/json.nim @@ -10,6 +10,7 @@ type duration*: UInt256 proofProbability*: UInt256 reward*: UInt256 + collateral*: UInt256 expiry*: ?UInt256 nodes*: ?uint tolerance*: ?uint @@ -19,7 +20,8 @@ proc fromJson*(_: type Availability, bytes: seq[byte]): ?!Availability = let size = ?catch UInt256.fromHex(json["size"].getStr) let duration = ?catch UInt256.fromHex(json["duration"].getStr) let minPrice = ?catch UInt256.fromHex(json["minPrice"].getStr) - success Availability.init(size, duration, minPrice) + let maxCollateral = ?catch UInt256.fromHex(json["maxCollateral"].getStr) + success Availability.init(size, duration, minPrice, maxCollateral) proc fromJson*(_: type StorageRequestParams, bytes: seq[byte]): ?! StorageRequestParams = @@ -27,6 +29,7 @@ proc fromJson*(_: type StorageRequestParams, let duration = ?catch UInt256.fromHex(json["duration"].getStr) let proofProbability = ?catch UInt256.fromHex(json["proofProbability"].getStr) let reward = ?catch UInt256.fromHex(json["reward"].getStr) + let collateral = ?catch UInt256.fromHex(json["collateral"].getStr) let expiry = UInt256.fromHex(json["expiry"].getStr).catch.option let nodes = strutils.fromHex[uint](json["nodes"].getStr).catch.option let tolerance = strutils.fromHex[uint](json["tolerance"].getStr).catch.option @@ -34,6 +37,7 @@ proc fromJson*(_: type StorageRequestParams, duration: duration, proofProbability: proofProbability, reward: reward, + collateral: collateral, expiry: expiry, nodes: nodes, tolerance: tolerance diff --git a/codex/sales/reservations.nim b/codex/sales/reservations.nim index 5f8ddec5..91f21112 100644 --- a/codex/sales/reservations.nim +++ b/codex/sales/reservations.nim @@ -38,6 +38,7 @@ type size*: UInt256 duration*: UInt256 minPrice*: UInt256 + maxCollateral*: UInt256 used*: bool Reservations* = ref object repo: RepoStore @@ -67,11 +68,12 @@ proc init*( _: type Availability, size: UInt256, duration: UInt256, - minPrice: UInt256): Availability = + minPrice: UInt256, + maxCollateral: UInt256): Availability = var id: array[32, byte] doAssert randomBytes(id) == 32 - Availability(id: AvailabilityId(id), size: size, duration: duration, minPrice: minPrice) + Availability(id: AvailabilityId(id), size: size, duration: duration, minPrice: minPrice, maxCollateral: maxCollateral) func toArray*(id: AvailabilityId): array[32, byte] = array[32, byte](id) @@ -81,6 +83,7 @@ proc `==`*(x, y: Availability): bool = x.id == y.id and x.size == y.size and x.duration == y.duration and + x.maxCollateral == y.maxCollateral and x.minPrice == y.minPrice proc `$`*(id: AvailabilityId): string = id.toArray.toHex @@ -318,7 +321,7 @@ proc unused*(r: Reservations): Future[?!seq[Availability]] {.async.} = proc find*( self: Reservations, - size, duration, minPrice: UInt256, + size, duration, minPrice: UInt256, collateral: UInt256, used: bool): Future[?Availability] {.async.} = @@ -332,13 +335,15 @@ proc find*( if used == availability.used and size <= availability.size and duration <= availability.duration and + collateral <= availability.maxCollateral and minPrice >= availability.minPrice: trace "availability matched", used, availUsed = availability.used, size, availsize = availability.size, duration, availDuration = availability.duration, - minPrice, availMinPrice = availability.minPrice + minPrice, availMinPrice = availability.minPrice, + collateral, availMaxCollateral = availability.maxCollateral return some availability @@ -346,4 +351,5 @@ proc find*( used, availUsed = availability.used, size, availsize = availability.size, duration, availDuration = availability.duration, - minPrice, availMinPrice = availability.minPrice + minPrice, availMinPrice = availability.minPrice, + collateral, availMaxCollateral = availability.maxCollateral diff --git a/codex/sales/states/downloading.nim b/codex/sales/states/downloading.nim index d4e14729..b2b57958 100644 --- a/codex/sales/states/downloading.nim +++ b/codex/sales/states/downloading.nim @@ -50,6 +50,7 @@ method run*(state: SaleDownloading, machine: Machine): Future[?State] {.async.} request.ask.slotSize, request.ask.duration, request.ask.pricePerSlot, + request.ask.collateral, used = false): info "no availability found for request, ignoring", slotSize = request.ask.slotSize, diff --git a/codex/sales/states/filling.nim b/codex/sales/states/filling.nim index 9743c769..251b97e7 100644 --- a/codex/sales/states/filling.nim +++ b/codex/sales/states/filling.nim @@ -25,5 +25,7 @@ method onSlotFilled*(state: SaleFilling, requestId: RequestId, method run(state: SaleFilling, machine: Machine): Future[?State] {.async.} = let data = SalesAgent(machine).data let market = SalesAgent(machine).context.market + without (collateral =? data.request.?ask.?collateral): + raiseAssert "Request not set" - await market.fillSlot(data.requestId, data.slotIndex, state.proof) + await market.fillSlot(data.requestId, data.slotIndex, state.proof, collateral) diff --git a/openapi.yaml b/openapi.yaml index f8d31e1c..7576aa49 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -112,6 +112,9 @@ components: minPrice: type: string description: Minimum price to be paid (in amount of tokens) as hexadecimal string + maxCollateral: + type: string + description: Maximum collateral user is willing to pay per filled Slot (in amount of tokens) StorageRequestCreation: type: object @@ -119,6 +122,7 @@ components: - reward - duration - proofProbability + - collateral properties: duration: $ref: "#/components/schemas/Duration" @@ -134,6 +138,9 @@ components: type: number description: Additional number of nodes on top of the `nodes` property that can be lost before pronouncing the content lost default: 0 + collateral: + type: string + description: Hexadecimal encoded number that represents how much collateral is asked from hosts that wants to fill a slots StorageAsk: type: object diff --git a/tests/codex/examples.nim b/tests/codex/examples.nim index 756ddd63..fce8c46b 100644 --- a/tests/codex/examples.nim +++ b/tests/codex/examples.nim @@ -57,5 +57,6 @@ proc example*(_: type Availability): Availability = Availability.init( size = uint16.example.u256, duration = uint16.example.u256, - minPrice = uint64.example.u256 + minPrice = uint64.example.u256, + maxCollateral = uint16.example.u256 ) diff --git a/tests/codex/helpers/mockmarket.nim b/tests/codex/helpers/mockmarket.nim index 7df7c0fd..bd9495de 100644 --- a/tests/codex/helpers/mockmarket.nim +++ b/tests/codex/helpers/mockmarket.nim @@ -67,10 +67,10 @@ proc hash*(requestId: RequestId): Hash = proc new*(_: type MockMarket): MockMarket = let config = MarketplaceConfig( collateral: CollateralConfig( - initialAmount: 100.u256, - minimumAmount: 40.u256, - slashCriterion: 3.u256, - slashPercentage: 10.u256 + repairRewardPercentage: 10, + maxNumberOfSlashes: 5, + slashCriterion: 3, + slashPercentage: 10 ), proofs: ProofConfig( period: 10.u256, @@ -80,9 +80,6 @@ proc new*(_: type MockMarket): MockMarket = ) MockMarket(signer: Address.example, config: config) -method approveFunds*(market: MockMarket, amount: UInt256) {.async.} = - discard - method getSigner*(market: MockMarket): Future[Address] {.async.} = return market.signer @@ -182,7 +179,8 @@ proc fillSlot*(market: MockMarket, method fillSlot*(market: MockMarket, requestId: RequestId, slotIndex: UInt256, - proof: seq[byte]) {.async.} = + proof: seq[byte], + collateral: UInt256) {.async.} = market.fillSlot(requestId, slotIndex, proof, market.signer) method withdrawFunds*(market: MockMarket, diff --git a/tests/codex/sales/testreservations.nim b/tests/codex/sales/testreservations.nim index a85e4db9..3486e478 100644 --- a/tests/codex/sales/testreservations.nim +++ b/tests/codex/sales/testreservations.nim @@ -39,8 +39,8 @@ suite "Reservations module": check (await reservations.allAvailabilities()).len == 0 test "generates unique ids for storage availability": - let availability1 = Availability.init(1.u256, 2.u256, 3.u256) - let availability2 = Availability.init(1.u256, 2.u256, 3.u256) + let availability1 = Availability.init(1.u256, 2.u256, 3.u256, 4.u256) + let availability2 = Availability.init(1.u256, 2.u256, 3.u256, 4.u256) check availability1.id != availability2.id test "can reserve available storage": @@ -125,7 +125,7 @@ suite "Reservations module": check isOk await reservations.markUsed(availability.id) without available =? await reservations.find(availability.size, - availability.duration, availability.minPrice, used = true): + availability.duration, availability.minPrice, availability.maxCollateral, used = true): fail() @@ -133,13 +133,13 @@ suite "Reservations module": check isOk await reservations.reserve(availability) without available =? await reservations.find(availability.size, - availability.duration, availability.minPrice, used = false): + availability.duration, availability.minPrice, availability.maxCollateral, used = false): fail() test "non-existant availability cannot be found": check isNone (await reservations.find(availability.size, - availability.duration, availability.minPrice, used = false)) + availability.duration, availability.minPrice, availability.maxCollateral, used = false)) test "non-existant availability cannot be retrieved": let r = await reservations.get(availability.id) diff --git a/tests/codex/sales/testsales.nim b/tests/codex/sales/testsales.nim index 78df8997..eaa81122 100644 --- a/tests/codex/sales/testsales.nim +++ b/tests/codex/sales/testsales.nim @@ -38,7 +38,8 @@ suite "Sales": availability = Availability.init( size=100.u256, duration=60.u256, - minPrice=600.u256 + minPrice=600.u256, + maxCollateral=400.u256 ) request = StorageRequest( ask: StorageAsk( @@ -46,6 +47,7 @@ suite "Sales": slotSize: 100.u256, duration: 60.u256, reward: 10.u256, + collateral: 200.u256, ), content: StorageContent( cid: "some cid" @@ -134,6 +136,13 @@ suite "Sales": await market.requestStorage(request) check getAvailability().?used == success false + test "ignores request when asked collateral is too high": + var tooBigCollateral = request + tooBigCollateral.ask.collateral = availability.maxCollateral + 1 + check isOk await reservations.reserve(availability) + await market.requestStorage(tooBigCollateral) + check await wasIgnored() + test "retrieves and stores data locally": var storingRequest: StorageRequest var storingSlot: UInt256 diff --git a/tests/contracts/testCollateral.nim b/tests/contracts/testCollateral.nim deleted file mode 100644 index eab02081..00000000 --- a/tests/contracts/testCollateral.nim +++ /dev/null @@ -1,32 +0,0 @@ -import pkg/chronos -import pkg/stint -import codex/contracts -import ./token -import ../ethertest - -ethersuite "Collateral": - - let collateral = 100.u256 - - var marketplace: Marketplace - var token: TestToken - - setup: - let deployment = Deployment.init() - marketplace = Marketplace.new(!deployment.address(Marketplace), provider.getSigner()) - token = TestToken.new(!deployment.address(TestToken), provider.getSigner()) - await token.mint(accounts[0], 1000.u256) - - test "increases collateral": - await token.approve(marketplace.address, collateral) - await marketplace.deposit(collateral) - let balance = await marketplace.balanceOf(accounts[0]) - check balance == collateral - - test "withdraws collateral": - await token.approve(marketplace.address, collateral) - await marketplace.deposit(collateral) - let balanceBefore = await token.balanceOf(accounts[0]) - await marketplace.withdraw() - let balanceAfter = await token.balanceOf(accounts[0]) - check (balanceAfter - balanceBefore) == collateral diff --git a/tests/contracts/testContracts.nim b/tests/contracts/testContracts.nim index 3892e740..2900f3ed 100644 --- a/tests/contracts/testContracts.nim +++ b/tests/contracts/testContracts.nim @@ -1,20 +1,19 @@ import std/json import pkg/chronos import pkg/ethers/testing +import pkg/ethers/erc20 import codex/contracts import codex/storageproofs import ../ethertest import ./examples import ./time -import ./token ethersuite "Marketplace contracts": let proof = exampleProof() var client, host: Signer var marketplace: Marketplace - var token: TestToken - var collateral: UInt256 + var token: Erc20Token var periodicity: Periodicity var request: StorageRequest var slotId: SlotId @@ -29,13 +28,11 @@ ethersuite "Marketplace contracts": let deployment = Deployment.init() marketplace = Marketplace.new(!deployment.address(Marketplace), provider.getSigner()) - token = TestToken.new(!deployment.address(TestToken), provider.getSigner()) - await token.mint(await client.getAddress(), 1_000_000_000.u256) - await token.mint(await host.getAddress(), 1000_000_000.u256) + let tokenAddress = await marketplace.token() + token = Erc20Token.new(tokenAddress, provider.getSigner()) let config = await marketplace.config() - collateral = config.collateral.initialAmount periodicity = Periodicity(seconds: config.proofs.period) request = StorageRequest.example @@ -45,8 +42,7 @@ ethersuite "Marketplace contracts": await token.approve(marketplace.address, request.price) await marketplace.requestStorage(request) switchAccount(host) - await token.approve(marketplace.address, collateral) - await marketplace.deposit(collateral) + await token.approve(marketplace.address, request.ask.collateral) await marketplace.fillSlot(request.id, 0.u256, proof) slotId = request.slotId(0.u256) @@ -61,6 +57,7 @@ ethersuite "Marketplace contracts": proc startContract() {.async.} = for slotIndex in 1..