Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: more tests and name fix #69

Merged
merged 2 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contracts/mechs/native/MechFactoryFixedPriceNative.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ error MarketplaceOnly(address sender, address marketplace);
/// @dev Provided zero address.
error ZeroAddress();

/// @title Mech Factory Basic - Periphery smart contract for managing basic mech creation
/// @title MechFactoryFixedPriceNative - Periphery smart contract for managing fixed price native token mech creation
contract MechFactoryFixedPriceNative {
event CreateFixedPriceMech(address indexed mech, uint256 indexed serviceId, uint256 maxDeliveryRate);

Expand Down
2 changes: 1 addition & 1 deletion contracts/mechs/token/MechFactoryFixedPriceToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ error MarketplaceOnly(address sender, address marketplace);
/// @dev Provided zero address.
error ZeroAddress();

/// @title Mech Factory Basic - Periphery smart contract for managing basic mech creation
/// @title MechFactoryFixedPriceToken - Periphery smart contract for managing fixed price token mech creation
contract MechFactoryFixedPriceToken {
event CreateFixedPriceMech(address indexed mech, uint256 indexed serviceId, uint256 maxDeliveryRate);

Expand Down
58 changes: 58 additions & 0 deletions contracts/test/MockMech.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

interface IMechMarketplace {
function deliverMarketplace(uint256 requestId, bytes memory requestData) external;
function request(bytes memory data, uint256 priorityMechServiceId, uint256 requesterServiceId,
uint256 responseTimeout, bytes memory paymentData) external payable returns (uint256);
}

contract MockMech {
address public immutable mechMarketplace;

uint256 public serviceId = 99;
bool public isNotSelf;

constructor(address _mechMarketplace) {
mechMarketplace = _mechMarketplace;
}

function setServiceId(uint256 _serviceId) external {
serviceId = _serviceId;
}

function setNotSelf(bool _isNotSelf) external {
isNotSelf = _isNotSelf;
}

function deliverMarketplace(uint256 requestId, bytes memory requestData) external {
IMechMarketplace(mechMarketplace).deliverMarketplace(requestId, requestData);
}

function request(
bytes memory data,
uint256 priorityMechServiceId,
uint256 requesterServiceId,
uint256 responseTimeout,
bytes memory paymentData
) external payable returns (uint256) {
return IMechMarketplace(mechMarketplace).request{value: msg.value}(data, priorityMechServiceId,
requesterServiceId, responseTimeout, paymentData);
}

function tokenId() external view returns (uint256) {
return serviceId;
}

function getOperator() external view returns (address) {
if (isNotSelf) {
return address(1);
}

return address(this);
}

function getFinalizedDeliveryRate(uint256) external returns (uint256) {
return 1;
}
}
67 changes: 67 additions & 0 deletions contracts/test/MockMechFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {MockMech} from "./MockMech.sol";

/// @dev Incorrect data length.
/// @param provided Provided data length.
/// @param expected Expected data length.
error IncorrectDataLength(uint256 provided, uint256 expected);

/// @dev Only `marketplace` has a privilege, but the `sender` was provided.
/// @param sender Sender address.
/// @param marketplace Required marketplace address.
error MarketplaceOnly(address sender, address marketplace);

/// @dev Provided zero address.
error ZeroAddress();

/// @title MockMechFactory - Periphery smart contract for managing mock mech creation
contract MockMechFactory {
event CreateMockMech(address indexed mech, uint256 maxDeliveryRate);

// Agent factory version number
string public constant VERSION = "0.1.0";
// Mech marketplace address
address public immutable mechMarketplace;

// Decode max delivery rate
uint256 public maxDeliveryRate = 1;

// Nonce
uint256 internal _nonce;

/// @dev MechFactoryFixedPriceNative constructor.
/// @param _mechMarketplace Mech marketplace address.
constructor(address _mechMarketplace) {
mechMarketplace = _mechMarketplace;
}

/// @dev Registers service as a mech.
/// @return mech The created mech instance address.
function createMech(
address,
uint256,
bytes memory
) external returns (address mech) {
// Check for marketplace access
if (msg.sender != mechMarketplace) {
revert MarketplaceOnly(msg.sender, mechMarketplace);
}

uint256 localNonce = _nonce;
// Get salt
bytes32 salt = keccak256(abi.encode(block.timestamp, msg.sender, localNonce));
_nonce = localNonce + 1;

// Service multisig is isOperator() for the mech
mech = address((new MockMech){salt: salt}(mechMarketplace));

// Check for zero address
if (mech == address(0)) {
revert ZeroAddress();
}

emit CreateMockMech(mech, maxDeliveryRate);
}
}
88 changes: 87 additions & 1 deletion test/MechMarketplace.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const { expect } = require("chai");
const { ethers } = require("hardhat");
const helpers = require("@nomicfoundation/hardhat-network-helpers");

describe("MechMarketplace", function () {
let MechMarketplace;
Expand All @@ -12,11 +13,15 @@ describe("MechMarketplace", function () {
let karma;
let mechFactoryFixedPrice;
let balanceTrackerFixedPriceNative;
let mockMech;
let mockMechFactory;
let signers;
let deployer;
const AddressZero = ethers.constants.AddressZero;
const maxDeliveryRate = 1000;
const fee = 10;
const data = "0x00";
const defaultRequestId = 1;
const minResponseTimeout = 10;
const maxResponseTimeout = 20;
const mechServiceId = 1;
Expand Down Expand Up @@ -97,6 +102,19 @@ describe("MechMarketplace", function () {
// Whitelist balance tracker
paymentTypeHash = await priorityMech.paymentType();
await mechMarketplace.setPaymentTypeBalanceTrackers([paymentTypeHash], [balanceTrackerFixedPriceNative.address]);

// Deploy mock mech
const MockMech = await ethers.getContractFactory("MockMech");
mockMech = await MockMech.deploy(mechMarketplace.address);
await mockMech.deployed();

// Deploy mock mech factory
const MockMechFactory = await ethers.getContractFactory("MockMechFactory");
mockMechFactory = await MockMechFactory.deploy(mechMarketplace.address);
await mockMechFactory.deployed();

// Whitelist mock mech factory
await mechMarketplace.setMechFactoryStatuses([mockMechFactory.address], [true]);
});

context("Initialization", async function () {
Expand Down Expand Up @@ -198,7 +216,7 @@ describe("MechMarketplace", function () {
mechMarketplace.create(mechServiceId, deployer.address, mechCreationData)
).to.be.revertedWithCustomError(mechMarketplace, "UnauthorizedAccount");

// Trying to set mech factory statuses and balance trackersnot by the owner
// Trying to set mech factory statuses and balance trackers not by the owner
await expect(
mechMarketplace.connect(signers[1]).setMechFactoryStatuses([AddressZero], [true])
).to.be.revertedWithCustomError(mechMarketplace, "OwnerOnly");
Expand Down Expand Up @@ -226,6 +244,72 @@ describe("MechMarketplace", function () {
mechMarketplace.setPaymentTypeBalanceTrackers([ethers.constants.HashZero], [deployer.address])
).to.be.revertedWithCustomError(mechMarketplace, "ZeroValue");
});

it("Try to deliver by a mock mech", async function () {
// Take a snapshot of the current state of the blockchain
const snapshot = await helpers.takeSnapshot();

// Trying to deliver by a random mech
await expect(
mockMech.deliverMarketplace(defaultRequestId, data)
).to.be.revertedWithCustomError(mechMarketplace, "UnauthorizedAccount");

// Create mock mech via the factory
let mockServiceId = await mockMech.tokenId();
let tx = await mechMarketplace.create(mockServiceId, mockMechFactory.address, data);
let res = await tx.wait();
// Get mech contract address from the event
const mechMockAddress = "0x" + res.logs[0].topics[1].slice(26);
// Get mech contract instance
const mechMock = await ethers.getContractAt("MockMech", mechMockAddress);

// Try to deliver a non-existent request
await expect(
mechMock.deliverMarketplace(defaultRequestId, data)
).to.be.revertedWithCustomError(mechMarketplace, "ZeroAddress");

// Request in priority mech
// Get request Id
const requestId = await mechMarketplace.getRequestId(mechMock.address, data, 0);

// Change mock service Id not to be within deployed ones (id-s 100+ in MockServiceRegistry)
mockServiceId = mockServiceId.add(1);
await mechMock.setServiceId(mockServiceId);

// Try to post a request from a requester service that is not deployed
await expect(
mechMock.request(data, mechServiceId, mockServiceId, minResponseTimeout, "0x", {value: maxDeliveryRate})
).to.be.revertedWithCustomError(mechMarketplace, "WrongServiceState");

// Change mock service Id to be back within deployed ones (0 to 99 in MockServiceRegistry)
mockServiceId = mockServiceId.sub(1);
await mechMock.setServiceId(mockServiceId);

// Try to post a request not by a correct requester multisig
await expect(
mechMock.request(data, mechServiceId, mockServiceId, minResponseTimeout, "0x", {value: maxDeliveryRate})
).to.be.revertedWithCustomError(mechMarketplace, "OwnerOnly");

// Pseudo-create and deploy requester service
await serviceRegistry.setServiceOwner(mockServiceId, mechMock.address);

// Post a request
await mechMock.request(data, mechServiceId, mockServiceId, minResponseTimeout, "0x", {value: maxDeliveryRate});

// Increase the time such that the request expires for a priority mech
await helpers.time.increase(maxResponseTimeout);

// Try to deliver directly via a marketplace
await mechMock.deliverMarketplace(requestId, data);

// Try to deliver the same request once again
await expect(
mechMock.deliverMarketplace(requestId, data)
).to.be.revertedWithCustomError(mechMarketplace, "AlreadyDelivered");

// Restore a previous state of blockchain
snapshot.restore();
});
});

context("Request checks", async function () {
Expand All @@ -240,6 +324,8 @@ describe("MechMarketplace", function () {
mechMarketplace.checkRequester(deployer.address, requesterServiceId)
).to.be.revertedWithCustomError(mechMarketplace, "OwnerOnly");

// Check requester
await mechMarketplace.checkRequester(signers[1].address, requesterServiceId);
});
});
});
Loading