fix: approving tokens transfer when creating request (#385)

This commit is contained in:
Adam Uhlíř 2023-03-30 11:34:38 +02:00 committed by GitHub
parent d756bf9dc5
commit 3198db414d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 41 additions and 27 deletions

View File

@ -43,10 +43,6 @@ let config = await marketplace.config()
let collateral = config.collateral.initialAmount
```
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
@ -83,9 +79,7 @@ let request : StorageRequest = (
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.
maximum price and the offered price will be reimbursed later.
Once the payment has been prepared, the client can submit the request to the
network:
@ -152,7 +146,7 @@ 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].
refer to the [design document][2].
At the start of each period of time, the host can check whether a storage proof
is required:
@ -178,5 +172,4 @@ await storage
```
[1]: https://github.com/status-im/codex-contracts-eth/
[2]: https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
[3]: https://github.com/status-im/codex-research/blob/main/design/storage-proof-timing.md
[2]: https://github.com/status-im/codex-research/blob/main/design/storage-proof-timing.md

View File

@ -25,6 +25,12 @@ func new*(_: type OnChainMarket, contract: Marketplace): OnChainMarket =
signer: signer,
)
method approveFunds*(market: OnChainMarket, amount: UInt256) {.async.} =
let tokenAddress = await market.contract.token()
let token = Erc20Token.new(tokenAddress, market.signer)
await token.approve(market.contract.address(), amount)
method getSigner*(market: OnChainMarket): Future[Address] {.async.} =
return await market.signer.getAddress()

View File

@ -1,4 +1,5 @@
import pkg/ethers
import pkg/ethers/erc20
import pkg/json_rpc/rpcclient
import pkg/stint
import pkg/chronos
@ -8,6 +9,7 @@ import ./config
export stint
export ethers
export erc20
export config
type
@ -31,6 +33,7 @@ type
proc config*(marketplace: Marketplace): MarketplaceConfig {.contract, view.}
proc token*(marketplace: Marketplace): Address {.contract, view.}
proc slashMisses*(marketplace: Marketplace): UInt256 {.contract, view.}
proc slashPercentage*(marketplace: Marketplace): UInt256 {.contract, view.}
proc minCollateralThreshold*(marketplace: Marketplace): UInt256 {.contract, view.}

View File

@ -1,10 +0,0 @@
import pkg/chronos
import pkg/stint
import pkg/ethers
type
TestToken* = ref object of Contract
proc mint*(token: TestToken, holder: Address, amount: UInt256) {.contract.}
proc approve*(token: TestToken, spender: Address, amount: UInt256) {.contract.}
proc balanceOf*(token: TestToken, account: Address): UInt256 {.contract, view.}

View File

@ -1,6 +1,7 @@
import pkg/chronos
import pkg/upraises
import pkg/questionable
import pkg/ethers/erc20
import ./contracts/requests
import ./clock
@ -18,6 +19,10 @@ 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")

View File

@ -10,6 +10,7 @@ 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))

View File

@ -28,10 +28,10 @@ Open a terminal and run:
Optionally, if you want to use the Marketplace blockchain functionality, you need to also include these flags: `--persistence --eth-account=<account>`, where `account` can be one following:
- `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266`
- `0x70997970C51812dc3A010C7d01b50e0d17dc79C8`
- `0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC`
- `0x90F79bf6EB2c4f870365E785982E1f101E93b906`
- `0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65`
**For each node use a different account!**

View File

@ -80,6 +80,9 @@ 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

View File

@ -1,7 +1,7 @@
import pkg/chronos
import pkg/stint
import codex/contracts
import codex/contracts/testtoken
import ./token
import ../ethertest
ethersuite "Collateral":

View File

@ -2,11 +2,11 @@ import std/json
import pkg/chronos
import pkg/ethers/testing
import codex/contracts
import codex/contracts/testtoken
import codex/storageproofs
import ../ethertest
import ./examples
import ./time
import ./token
ethersuite "Marketplace contracts":
let proof = exampleProof()

View File

@ -2,11 +2,11 @@ import std/options
import pkg/chronos
import pkg/stew/byteutils
import codex/contracts
import codex/contracts/testtoken
import codex/storageproofs
import ../ethertest
import ./examples
import ./time
import ./token
ethersuite "On-Chain Market":
let proof = exampleProof()

View File

@ -0,0 +1,9 @@
import pkg/chronos
import pkg/stint
import pkg/ethers
import pkg/ethers/erc20
type
TestToken* = ref object of Erc20Token
proc mint*(token: TestToken, holder: Address, amount: UInt256) {.contract.}

View File

@ -1,5 +1,6 @@
import pkg/ethers/erc20
import codex/contracts
import codex/contracts/testtoken
import ../contracts/token
proc mint*(signer: Signer, amount = 1_000_000.u256) {.async.} =
## Mints a considerable amount of tokens and approves them for transfer to
@ -7,10 +8,13 @@ proc mint*(signer: Signer, amount = 1_000_000.u256) {.async.} =
let token = TestToken.new(!deployment().address(TestToken), signer)
let marketplace = Marketplace.new(!deployment().address(Marketplace), signer)
await token.mint(await signer.getAddress(), amount)
await token.approve(marketplace.address, amount)
proc deposit*(signer: Signer) {.async.} =
## Deposits sufficient collateral into the Marketplace contract.
let marketplace = Marketplace.new(!deployment().address(Marketplace), signer)
let config = await marketplace.config()
let tokenAddress = await marketplace.token()
let token = Erc20Token.new(tokenAddress, signer)
await token.approve(marketplace.address, config.collateral.initialAmount)
await marketplace.deposit(config.collateral.initialAmount)

2
vendor/nim-ethers vendored

@ -1 +1 @@
Subproject commit 577e02b8a25198d6897c1f4871b5fd8e1f859e5a
Subproject commit 3c12a65769b9a223028df25f78abb6dde06fef35