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

refactor: creating mechs in marketplace #50

Merged
merged 7 commits into from
Dec 13, 2024
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
56 changes: 0 additions & 56 deletions contracts/AgentFactory.sol

This file was deleted.

39 changes: 0 additions & 39 deletions contracts/AgentMech.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

Check warning on line 2 in contracts/AgentMech.sol

View workflow job for this annotation

GitHub Actions / build

Found more than One contract per file. 2 contracts found!

import {IErrorsMech} from "./interfaces/IErrorsMech.sol";
import {IMechMarketplace} from "./interfaces/IMechMarketplace.sol";
Expand Down Expand Up @@ -47,7 +47,7 @@
}

function setUp(bytes memory initParams) public override {
require(readImmutable().length == 0, "Already initialized");

Check warning on line 50 in contracts/AgentMech.sol

View workflow job for this annotation

GitHub Actions / build

GC: Use Custom Errors instead of require statements
writeImmutable(initParams);
}

Expand Down Expand Up @@ -93,9 +93,9 @@
bytes32 public constant DOMAIN_SEPARATOR_TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
// Original domain separator value
bytes32 public immutable domainSeparator;

Check warning on line 96 in contracts/AgentMech.sol

View workflow job for this annotation

GitHub Actions / build

Immutable variables name are set to be in capitalized SNAKE_CASE
// Original chain Id
uint256 public immutable chainId;

Check warning on line 98 in contracts/AgentMech.sol

View workflow job for this annotation

GitHub Actions / build

Immutable variables name are set to be in capitalized SNAKE_CASE

// Minimum required price
uint256 public price;
Expand Down Expand Up @@ -288,23 +288,6 @@
emit Deliver(msg.sender, requestId, requestData);
}

/// @dev Registers a request without a marketplace.
/// @notice Interface provided for backwards compatibility only.
/// @param data Self-descriptive opaque data-blob.
/// @return requestId Request Id.
function request(bytes memory data) external payable returns (uint256 requestId) {
DavidMinarsch marked this conversation as resolved.
Show resolved Hide resolved
if (mechMarketplace != address(0)) {
revert MarketplaceExists(mechMarketplace);
}

// Get the local request Id
requestId = getRequestId(msg.sender, data, mapNonces[msg.sender]);
mapNonces[msg.sender]++;

// Perform a request
_request(msg.sender, data, requestId);
}

/// @dev Registers a request by a marketplace.
/// @notice This function is called by the marketplace contract since this mech was specified as a priority one.
/// @param account Requester account address.
Expand Down Expand Up @@ -342,28 +325,6 @@
emit RevokeRequest(account, requestId);
}

/// @dev Delivers a request without a marketplace.
/// @notice Interface provided for backwards compatibility only.
/// @param requestId Request id.
/// @param data Self-descriptive opaque data-blob.
function deliver(uint256 requestId, bytes memory data) external onlyOperator {
DavidMinarsch marked this conversation as resolved.
Show resolved Hide resolved
// Reentrancy guard
if (_locked > 1) {
revert ReentrancyGuard();
}
_locked = 2;

// Check for the marketplace existence
if (mechMarketplace != address(0)) {
revert MarketplaceExists(mechMarketplace);
}

// Request delivery
_deliver(requestId, data);

_locked = 1;
}

/// @dev Delivers a request by a marketplace.
/// @notice This function ultimately calls mech marketplace contract to finalize the delivery.
/// @param requestId Request id.
Expand Down
41 changes: 41 additions & 0 deletions contracts/MechFactoryBasic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

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

/// @title Mech Factory Basic - Periphery smart contract for managing basic mech creation
contract MechFactoryBasic {
event CreateBasicMech(address indexed mech, uint256 indexed serviceId, uint256 indexed price);

// Agent factory version number
string public constant VERSION = "0.1.0";

/// @dev Registers service as a mech.
/// @param mechMarketplace Mech marketplace address.
/// @param serviceRegistry Service registry address.
/// @param serviceId Service id.
/// @param payload Mech creation payload.
/// @return mech The created mech instance address.
function createMech(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically mech creation function as before, just depends on mech passed params to decode.

address mechMarketplace,
address serviceRegistry,
uint256 serviceId,
bytes memory payload
) external returns (address mech) {
// Check payload length
if (payload.length != 32) {
revert();
}

// Decode price
uint256 price = abi.decode(payload, (uint256));

// Get salt
bytes32 salt = keccak256(abi.encode(block.timestamp, msg.sender, serviceId));

// Service multisig is isOperator() for the mech
mech = address((new AgentMech){salt: salt}(serviceRegistry, serviceId, price, mechMarketplace));

emit CreateBasicMech(mech, serviceId, price);
}
}
39 changes: 34 additions & 5 deletions contracts/MechMarketplace.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import {IMech} from "./interfaces/IMech.sol";
import {IServiceRegistry} from "./interfaces/IServiceRegistry.sol";
import {IStaking, IStakingFactory} from "./interfaces/IStaking.sol";

interface IMechFactory {
/// @dev Registers service as a mech.
/// @param mechMarketplace Mech marketplace address.
/// @param serviceRegistry Service registry address.
/// @param serviceId Service id.
/// @param payload Mech creation payload.
/// @return mech The created mech instance address.
function createMech(address mechMarketplace, address serviceRegistry, uint256 serviceId, bytes memory payload)
external returns (address mech);
}

// Mech delivery info struct
struct MechDelivery {
// Priority mech address
Expand All @@ -21,10 +32,7 @@ struct MechDelivery {

/// @title Mech Marketplace - Marketplace for posting and delivering requests served by agent mechs
contract MechMarketplace is IErrorsMarketplace {
event OwnerUpdated(address indexed owner);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated events

event FactoryUpdated(address indexed factory);
event MinMaxResponseTimeoutUpdated(uint256 minResponseTimeout, uint256 maxResponseTimeout);
event MechRegistrationStatusChanged(address indexed mech, bool status);
event CreateMech(address indexed mech, uint256 indexed serviceId);
event MarketplaceRequest(address indexed requester, address indexed requestedMech, uint256 requestId, bytes data);
event MarketplaceDeliver(address indexed priorityMech, address indexed actualMech, address indexed requester,
uint256 requestId, bytes data);
Expand All @@ -37,7 +45,7 @@ contract MechMarketplace is IErrorsMarketplace {
}

// Contract version number
string public constant VERSION = "1.0.0";
string public constant VERSION = "1.1.0";
// Domain separator type hash
bytes32 public constant DOMAIN_SEPARATOR_TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
Expand Down Expand Up @@ -133,6 +141,21 @@ contract MechMarketplace is IErrorsMarketplace {
);
}

/// @dev Registers service as a mech.
/// @param serviceId Service id.
/// @param mechFactory Mech factory address.
/// @return mech The created mech instance address.
function create(uint256 serviceId, address mechFactory, bytes memory payload) external returns (address mech) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so pretty now <3

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the mechFactory defined on the marketplace?

mech = IMechFactory(mechFactory).createMech(address(this), serviceRegistry, serviceId, payload);

// This should never be the case
if (mech == address(0)) {
revert ZeroAddress();
}

emit CreateMech(mech, serviceId);
}

/// @dev Registers a request.
/// @notice The request is going to be registered for a specified priority agent mech.
/// @param data Self-descriptive opaque data-blob.
Expand Down Expand Up @@ -395,6 +418,12 @@ contract MechMarketplace is IErrorsMarketplace {
revert ZeroValue();
}

// Check marketplace address
address checkMarketplace = IMech(mech).mechMarketplace();
if (checkMarketplace != address(this)) {
revert UnauthorizedAccount(checkMarketplace);
}

// Check mech service Id and staking instance, if applicable
multisig = checkServiceAndGetMultisig(mechStakingInstance, mechServiceId);

Expand Down
67 changes: 0 additions & 67 deletions contracts/integrations/nevermined/AgentFactorySubscription.sol

This file was deleted.

44 changes: 44 additions & 0 deletions contracts/integrations/nevermined/MechFactorySubscription.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

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

/// @title Mech Factory Subscription - Periphery smart contract for managing subscription mech creation
contract MechFactorySubscription {
event CreateSubscriptionMech(address indexed mech, uint256 indexed serviceId, uint256 minCreditsPerRequest,
address indexed subscriptionNFT, uint256 subscriptionTokenId);

// Agent factory version number
string public constant VERSION = "0.1.0";

/// @dev Registers service as a mech.
/// @param mechMarketplace Mech marketplace address.
/// @param serviceRegistry Service registry address.
/// @param serviceId Service id.
/// @param payload Mech creation payload.
/// @return mech The created mech instance address.
function createMech(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically mech creation function as before, just depends on mech passed params to decode.

address mechMarketplace,
address serviceRegistry,
uint256 serviceId,
bytes memory payload
) external returns (address mech) {
// Check payload length
if (payload.length != 96) {
revert();
}

// Decode subscription parameters
(uint256 minCreditsPerRequest, address subscriptionNFT, uint256 subscriptionTokenId) =
abi.decode(payload, (uint256, address, uint256));

// Get salt
bytes32 salt = keccak256(abi.encode(block.timestamp, msg.sender, serviceId));

// Service multisig is isOperator() for the mech
mech = address((new AgentMechSubscription){salt: salt}(serviceRegistry, serviceId, minCreditsPerRequest,
subscriptionNFT, subscriptionTokenId, mechMarketplace));

emit CreateSubscriptionMech(mech, serviceId, minCreditsPerRequest, subscriptionNFT, subscriptionTokenId);
}
}
4 changes: 4 additions & 0 deletions contracts/interfaces/IMech.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ interface IMech {
/// @notice Only marketplace can call this function if the request is not delivered by the chosen priority mech.
/// @param requestId Request Id.
function revokeRequest(uint256 requestId) external;

/// @dev Gets mech marketplace address.
/// @return marketplace Mech Marketplace address.
function mechMarketplace() external view returns (address marketplace);
}
Loading