From aee61bdb453cbf2eabb40ae16d8475c7b6049344 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Mon, 24 Feb 2025 17:11:00 +0100 Subject: [PATCH] marketplace: deploy vault and set it in the marketplace --- contracts/FuzzMarketplace.sol | 8 +++----- contracts/Marketplace.sol | 29 +++++++++++++++++------------ contracts/TestMarketplace.sol | 4 ++-- contracts/Vault.sol | 4 ++++ deploy/marketplace.js | 10 +++++----- deploy/vault.js | 13 +++++++++++++ test/Marketplace.test.js | 15 +++++++++++---- 7 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 deploy/vault.js diff --git a/contracts/FuzzMarketplace.sol b/contracts/FuzzMarketplace.sol index 3291e36..c13838c 100644 --- a/contracts/FuzzMarketplace.sol +++ b/contracts/FuzzMarketplace.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.28; import "./TestToken.sol"; import "./Marketplace.sol"; +import "./Vault.sol"; import "./TestVerifier.sol"; contract FuzzMarketplace is Marketplace { @@ -14,13 +15,10 @@ contract FuzzMarketplace is Marketplace { SlotReservationsConfig(20), 60 * 60 * 24 * 30 // 30 days ), - new TestToken(), + new Vault(new TestToken()), new TestVerifier() ) - // solhint-disable-next-line no-empty-blocks - { - - } + {} // Properties to be tested through fuzzing diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index c159c0d..650db34 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -5,6 +5,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "./Vault.sol"; import "./Configuration.sol"; import "./Requests.sol"; import "./Proofs.sol"; @@ -47,7 +48,7 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { using Requests for Request; using AskHelpers for Ask; - IERC20 private immutable _token; + Vault private immutable _vault; MarketplaceConfig private _config; mapping(RequestId => Request) private _requests; @@ -99,10 +100,10 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { constructor( MarketplaceConfig memory config, - IERC20 token_, + Vault vault_, IGroth16Verifier verifier ) SlotReservations(config.reservations) Proofs(config.proofs, verifier) { - _token = token_; + _vault = vault_; if (config.collateral.repairRewardPercentage > 100) revert Marketplace_RepairRewardPercentageTooHigh(); @@ -123,7 +124,11 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { } function token() public view returns (IERC20) { - return _token; + return _vault.getToken(); + } + + function vault() public view returns (Vault) { + return _vault; } function currentCollateral(SlotId slotId) public view returns (uint256) { @@ -172,7 +177,7 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { uint256 amount = request.maxPrice(); _requestContexts[id].fundsToReturnToClient = amount; _marketplaceTotals.received += amount; - _token.safeTransferFrom(msg.sender, address(this), amount); + token().safeTransferFrom(msg.sender, address(this), amount); emit StorageRequested(id, request.ask, _requestContexts[id].expiresAt); } @@ -232,7 +237,7 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { } else { collateralAmount = collateralPerSlot; } - _token.safeTransferFrom(msg.sender, address(this), collateralAmount); + token().safeTransferFrom(msg.sender, address(this), collateralAmount); _marketplaceTotals.received += collateralAmount; slot.currentCollateral = collateralPerSlot; // Even if he has collateral discounted, he is operating with full collateral @@ -358,7 +363,7 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { uint256 validatorRewardAmount = (slashedAmount * _config.collateral.validatorRewardPercentage) / 100; _marketplaceTotals.sent += validatorRewardAmount; - _token.safeTransfer(msg.sender, validatorRewardAmount); + token().safeTransfer(msg.sender, validatorRewardAmount); slot.currentCollateral -= slashedAmount; if (missingProofs(slotId) >= _config.collateral.maxNumberOfSlashes) { @@ -424,8 +429,8 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { uint256 collateralAmount = slot.currentCollateral; _marketplaceTotals.sent += (payoutAmount + collateralAmount); slot.state = SlotState.Paid; - _token.safeTransfer(rewardRecipient, payoutAmount); - _token.safeTransfer(collateralRecipient, collateralAmount); + token().safeTransfer(rewardRecipient, payoutAmount); + token().safeTransfer(collateralRecipient, collateralAmount); } /** @@ -454,8 +459,8 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { uint256 collateralAmount = slot.currentCollateral; _marketplaceTotals.sent += (payoutAmount + collateralAmount); slot.state = SlotState.Paid; - _token.safeTransfer(rewardRecipient, payoutAmount); - _token.safeTransfer(collateralRecipient, collateralAmount); + token().safeTransfer(rewardRecipient, payoutAmount); + token().safeTransfer(collateralRecipient, collateralAmount); } /** @@ -522,7 +527,7 @@ contract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian { uint256 amount = context.fundsToReturnToClient; _marketplaceTotals.sent += amount; - _token.safeTransfer(withdrawRecipient, amount); + token().safeTransfer(withdrawRecipient, amount); // We zero out the funds tracking in order to prevent double-spends context.fundsToReturnToClient = 0; diff --git a/contracts/TestMarketplace.sol b/contracts/TestMarketplace.sol index c18d369..cb840a0 100644 --- a/contracts/TestMarketplace.sol +++ b/contracts/TestMarketplace.sol @@ -7,10 +7,10 @@ import "./Marketplace.sol"; contract TestMarketplace is Marketplace { constructor( MarketplaceConfig memory config, - IERC20 token, + Vault vault, IGroth16Verifier verifier ) - Marketplace(config, token, verifier) // solhint-disable-next-line no-empty-blocks + Marketplace(config, vault, verifier) {} function forciblyFreeSlot(SlotId slotId) public { diff --git a/contracts/Vault.sol b/contracts/Vault.sol index 63667b8..8433a08 100644 --- a/contracts/Vault.sol +++ b/contracts/Vault.sol @@ -50,6 +50,10 @@ import "./vault/VaultBase.sol"; contract Vault is VaultBase, Pausable, Ownable { constructor(IERC20 token) VaultBase(token) Ownable(msg.sender) {} + function getToken() public view returns (IERC20) { + return _token; + } + /// Creates an account id that encodes the address of the account holder, and /// a discriminator. The discriminator can be used to create different /// accounts within a fund that all belong to the same account holder. diff --git a/deploy/marketplace.js b/deploy/marketplace.js index d1cb51d..4ace5da 100644 --- a/deploy/marketplace.js +++ b/deploy/marketplace.js @@ -9,12 +9,12 @@ async function mine256blocks({ network, ethers }) { // deploys a marketplace with a real Groth16 verifier async function deployMarketplace({ deployments, getNamedAccounts }) { - const token = await deployments.get("TestToken") + const vault = await deployments.get("Vault") const verifier = await deployments.get("Groth16Verifier") const zkeyHash = loadZkeyHash(network.name) let configuration = loadConfiguration(network.name) configuration.proofs.zkeyHash = zkeyHash - const args = [configuration, token.address, verifier.address] + const args = [configuration, vault.address, verifier.address] const { deployer: from } = await getNamedAccounts() const marketplace = await deployments.deploy("Marketplace", { args, from }) console.log("Deployed Marketplace with Groth16 Verifier at:") @@ -29,12 +29,12 @@ async function deployTestMarketplace({ getNamedAccounts, }) { if (network.tags.local) { - const token = await deployments.get("TestToken") + const vault = await deployments.get("Vault") const verifier = await deployments.get("TestVerifier") const zkeyHash = loadZkeyHash(network.name) let configuration = loadConfiguration(network.name) configuration.proofs.zkeyHash = zkeyHash - const args = [configuration, token.address, verifier.address] + const args = [configuration, vault.address, verifier.address] const { deployer: from } = await getNamedAccounts() const marketplace = await deployments.deploy("Marketplace", { args, from }) console.log("Deployed Marketplace with Test Verifier at:") @@ -50,4 +50,4 @@ module.exports = async (environment) => { } module.exports.tags = ["Marketplace"] -module.exports.dependencies = ["TestToken", "Verifier"] +module.exports.dependencies = ["Vault", "Verifier"] diff --git a/deploy/vault.js b/deploy/vault.js new file mode 100644 index 0000000..fed6c46 --- /dev/null +++ b/deploy/vault.js @@ -0,0 +1,13 @@ +async function deployVault({ deployments, getNamedAccounts }) { + const token = await deployments.get("TestToken") + const args = [token.address] + const { deployer: from } = await getNamedAccounts() + await deployments.deploy("Vault", { args, from }) +} + +module.exports = async (environment) => { + await deployVault(environment) +} + +module.exports.tags = ["Vault"] +module.exports.dependencies = ["TestToken"] diff --git a/test/Marketplace.test.js b/test/Marketplace.test.js index 9904a40..62364a1 100644 --- a/test/Marketplace.test.js +++ b/test/Marketplace.test.js @@ -43,7 +43,7 @@ const { arrayify } = require("ethers/lib/utils") const ACCOUNT_STARTING_BALANCE = 1_000_000_000_000_000 describe("Marketplace constructor", function () { - let Marketplace, token, verifier, config + let Marketplace, token, vault, verifier, config beforeEach(async function () { await snapshot() @@ -52,6 +52,9 @@ describe("Marketplace constructor", function () { const TestToken = await ethers.getContractFactory("TestToken") token = await TestToken.deploy() + const Vault = await ethers.getContractFactory("Vault") + vault = await Vault.deploy(token.address) + const TestVerifier = await ethers.getContractFactory("TestVerifier") verifier = await TestVerifier.deploy() @@ -68,7 +71,7 @@ describe("Marketplace constructor", function () { config.collateral[property] = 101 await expect( - Marketplace.deploy(config, token.address, verifier.address) + Marketplace.deploy(config, vault.address, verifier.address) ).to.be.revertedWith(expectedError) }) } @@ -87,7 +90,7 @@ describe("Marketplace constructor", function () { config.collateral.maxNumberOfSlashes = 101 await expect( - Marketplace.deploy(config, token.address, verifier.address) + Marketplace.deploy(config, vault.address, verifier.address) ).to.be.revertedWith("Marketplace_MaximumSlashingTooHigh") }) }) @@ -98,6 +101,7 @@ describe("Marketplace", function () { let marketplace let token + let vault let verifier let client, clientWithdrawRecipient, @@ -143,13 +147,16 @@ describe("Marketplace", function () { await token.mint(account.address, ACCOUNT_STARTING_BALANCE) } + const Vault = await ethers.getContractFactory("Vault") + vault = await Vault.deploy(token.address) + const TestVerifier = await ethers.getContractFactory("TestVerifier") verifier = await TestVerifier.deploy() const Marketplace = await ethers.getContractFactory("TestMarketplace") marketplace = await Marketplace.deploy( config, - token.address, + vault.address, verifier.address ) patchOverloads(marketplace)