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

chore: partial changes #61

Merged
merged 20 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
10 changes: 10 additions & 0 deletions contracts/BalanceTrackerFixedPriceBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ abstract contract BalanceTrackerFixedPriceBase {
// Get account balance
uint256 balance = mapRequesterBalances[requester];

// Update balance with native value
kupermind marked this conversation as resolved.
Show resolved Hide resolved
if (msg.value > 0) {
balance += msg.value;
emit Deposit(msg.sender, address(0), msg.value);
}

// Check the request delivery rate for a fixed price
if (balance < maxDeliveryRate) {
// Get balance difference
Expand All @@ -114,6 +120,10 @@ abstract contract BalanceTrackerFixedPriceBase {
balance += _getRequiredFunds(requester, balanceDiff);
}

if (balance < maxDeliveryRate) {
revert InsufficientBalance(balance, maxDeliveryRate);
}

// Adjust account balance
balance -= maxDeliveryRate;
mapRequesterBalances[requester] = balance;
Expand Down
7 changes: 2 additions & 5 deletions contracts/BalanceTrackerFixedPriceNative.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,8 @@ contract BalanceTrackerFixedPriceNative is BalanceTrackerFixedPriceBase {

function _checkNativeValue() internal virtual override {}

function _getRequiredFunds(address, uint256 balanceDiff) internal virtual override returns (uint256) {
if (msg.value < balanceDiff) {
revert InsufficientBalance(msg.value, balanceDiff);
}
return msg.value;
function _getRequiredFunds(address, uint256) internal virtual override returns (uint256) {
return 0;
kupermind marked this conversation as resolved.
Show resolved Hide resolved
}

function _wrap(uint256 amount) internal virtual {
Expand Down
2 changes: 2 additions & 0 deletions contracts/MechFactoryFixedPriceNative.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ contract MechFactoryFixedPriceNative {
uint256 serviceId,
bytes memory payload
) external returns (address mech) {
// TODO: restrict all factories to be called from marketplace only - makes it easier to monitor the system
kupermind marked this conversation as resolved.
Show resolved Hide resolved

// Check payload length
if (payload.length != 32) {
revert IncorrectDataLength(payload.length, 32);
Expand Down
122 changes: 30 additions & 92 deletions contracts/MechMarketplace.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {IBalanceTracker} from "./interfaces/IBalanceTracker.sol";
import {IKarma} from "./interfaces/IKarma.sol";
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.
Expand Down Expand Up @@ -69,8 +68,6 @@ contract MechMarketplace is IErrorsMarketplace {
uint256 public immutable chainId;
// Mech karma contract address
address public immutable karma;
// Staking factory contract address
address public immutable stakingFactory;
// Service registry contract address
address public immutable serviceRegistry;

Expand All @@ -84,12 +81,15 @@ contract MechMarketplace is IErrorsMarketplace {
uint256 public numUndeliveredRequests;
// Number of total requests
uint256 public numTotalRequests;
// Number of mechs
uint256 public numMechs;
// Reentrancy lock
uint256 internal _locked = 1;

// Contract owner
address public owner;

// TODO: Aren't we duplicating info hereand on mech re the address specific counts?
// Map of request counts for corresponding requester
mapping(address => uint256) public mapRequestCounts;
// Map of delivery counts for corresponding requester
Expand All @@ -108,26 +108,23 @@ contract MechMarketplace is IErrorsMarketplace {
mapping(uint8 => address) public mapPaymentTypeBalanceTrackers;
// Mapping of account nonces
mapping(address => uint256) public mapNonces;
// Set of mechs created by this marketplace
address[] public setMechs;
// Mapping of service ids to mechs
mapping(uint256 => address) public mapServiceIdMech;


/// @dev MechMarketplace constructor.
/// @param _serviceRegistry Service registry contract address.
/// @param _stakingFactory Staking factory contract address.
kupermind marked this conversation as resolved.
Show resolved Hide resolved
/// @param _karma Karma proxy contract address.
constructor(
address _serviceRegistry,
address _stakingFactory,
address _karma
) {
// Check for zero address
if (_serviceRegistry == address(0) || _stakingFactory == address(0) || _karma == address(0)) {
if (_serviceRegistry == address(0) || _karma == address(0)) {
revert ZeroAddress();
}

serviceRegistry = _serviceRegistry;
stakingFactory = _stakingFactory;
karma = _karma;

// Record chain Id
Expand Down Expand Up @@ -275,8 +272,9 @@ contract MechMarketplace is IErrorsMarketplace {

// Record factory that created a mech
mapAgentMechFactories[mech] = mechFactory;
// Add mech address into the global set
setMechs.push(mech);
Comment on lines -278 to -279
Copy link
Collaborator

@kupermind kupermind Dec 23, 2024

Choose a reason for hiding this comment

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

I would leave this in some form. For now there's no mech tracker created by MM, just events. numMechs then becomes meaningless.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We now have the mapping, don't also need a set. The numMechs is now tracked explicitly as a variable

// Add mapping
mapServiceIdMech[serviceId] = mech;
kupermind marked this conversation as resolved.
Show resolved Hide resolved
numMechs++;

emit CreateMech(mech, serviceId);
}
Expand Down Expand Up @@ -332,24 +330,17 @@ contract MechMarketplace is IErrorsMarketplace {
emit SetPaymentTypeBalanceTrackers(paymentTypes, balanceTrackers);
}

// TODO: leave optional fields or remove?
/// @dev Registers a request.
/// @notice The request is going to be registered for a specified priority mech.
/// @param data Self-descriptive opaque data-blob.
/// @param priorityMech Address of a priority mech.
/// @param priorityMechStakingInstance Address of a priority mech staking instance (optional).
/// @param priorityMechServiceId Priority mech service Id.
/// @param requesterStakingInstance Staking instance of a service whose multisig posts a request (optional).
/// @param requesterServiceId Corresponding service Id in the staking contract (optional).
/// @param requesterServiceId Requester service Id (optional).
/// @param responseTimeout Relative response time in sec.
/// @param paymentData Additional payment-related request data, if applicable.
/// @param paymentData Additional payment-related request data (optional).
/// @return requestId Request Id.
function request(
bytes memory data,
address priorityMech,
address priorityMechStakingInstance,
uint256 priorityMechServiceId,
kupermind marked this conversation as resolved.
Show resolved Hide resolved
address requesterStakingInstance,
uint256 requesterServiceId,
uint256 responseTimeout,
bytes memory paymentData
Expand All @@ -360,16 +351,6 @@ contract MechMarketplace is IErrorsMarketplace {
}
_locked = 2;

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

// Check that mech staking contract is different from requester one
if (priorityMechStakingInstance == requesterStakingInstance && priorityMechStakingInstance != address(0)) {
revert UnauthorizedAccount(priorityMechStakingInstance);
}

// responseTimeout bounds
if (responseTimeout < minResponseTimeout || responseTimeout > maxResponseTimeout) {
revert OutOfBounds(responseTimeout, minResponseTimeout, maxResponseTimeout);
Expand All @@ -385,10 +366,13 @@ contract MechMarketplace is IErrorsMarketplace {
}

// Check priority mech
checkMech(priorityMech, priorityMechStakingInstance, priorityMechServiceId);
address priorityMech = mapServiceIdMech[priorityMechServiceId];
if (priorityMech == address(0)) {
revert ZeroAddress();
}

// Check requester
checkRequester(msg.sender, requesterStakingInstance, requesterServiceId);
checkRequester(msg.sender, requesterServiceId);

// Get the request Id
requestId = getRequestId(msg.sender, data, mapNonces[msg.sender]);
Expand Down Expand Up @@ -437,12 +421,10 @@ contract MechMarketplace is IErrorsMarketplace {
/// @notice This function can only be called by the mech delivering the request.
/// @param requestId Request id.
/// @param requestData Self-descriptive opaque data-blob.
/// @param deliveryMechStakingInstance Delivery mech staking instance address (optional).
/// @param deliveryMechServiceId Mech service Id.
function deliverMarketplace(
uint256 requestId,
bytes memory requestData,
address deliveryMechStakingInstance,
uint256 deliveryMechServiceId
) external {
// Reentrancy guard
Expand All @@ -452,7 +434,7 @@ contract MechMarketplace is IErrorsMarketplace {
_locked = 2;

// Check delivery mech and get its service multisig
address mechServiceMultisig = checkMech(msg.sender, deliveryMechStakingInstance, deliveryMechServiceId);
address mechServiceMultisig = checkMech(msg.sender, deliveryMechServiceId);

// Get mech delivery info struct
MechDelivery storage mechDelivery = mapRequestIdDeliveries[requestId];
Expand All @@ -463,12 +445,6 @@ contract MechMarketplace is IErrorsMarketplace {
revert ZeroAddress();
}

// Check that the delivery mech is not a requester
kupermind marked this conversation as resolved.
Show resolved Hide resolved
address requester = mechDelivery.requester;
if (msg.sender == requester) {
revert UnauthorizedAccount(msg.sender);
}

// Check that the request is not already delivered
if (mechDelivery.deliveryMech != address(0)) {
revert AlreadyDelivered(requestId);
Expand Down Expand Up @@ -548,69 +524,41 @@ contract MechMarketplace is IErrorsMarketplace {
));
}

/// @dev Checks for service validity and optionally for service staking correctness.
/// @param stakingInstance Staking instance address.
/// @dev Checks for service validity.
/// @param serviceId Service Id.
/// @return multisig Service multisig address.
function checkServiceAndGetMultisig(
address stakingInstance,
uint256 serviceId
) public view returns (address multisig) {
// Check mech service Id
if (stakingInstance == address(0)) {
IServiceRegistry.ServiceState state;
(, multisig, , , , , state) = IServiceRegistry(serviceRegistry).mapServices(serviceId);
if (state != IServiceRegistry.ServiceState.Deployed) {
revert WrongServiceState(uint256(state), serviceId);
}
} else {
// Check staking instance
checkStakingInstance(stakingInstance, serviceId);

// Get the staked service info for the mech
IStaking.ServiceInfo memory serviceInfo = IStaking(stakingInstance).getServiceInfo(serviceId);
multisig = serviceInfo.multisig;
}
}

/// @dev Checks for staking instance contract validity.
/// @param stakingInstance Staking instance address.
/// @param serviceId Service Id.
function checkStakingInstance(address stakingInstance, uint256 serviceId) public view {
// Check that the mech staking instance is valid
if (!IStakingFactory(stakingFactory).verifyInstance(stakingInstance)) {
revert UnauthorizedAccount(stakingInstance);
}

// Check if the mech service is staked
IStaking.StakingState state = IStaking(stakingInstance).getStakingState(serviceId);
if (state != IStaking.StakingState.Staked) {
revert ServiceNotStaked(stakingInstance, serviceId);
IServiceRegistry.ServiceState state;
(, multisig, , , , , state) = IServiceRegistry(serviceRegistry).mapServices(serviceId);
if (state != IServiceRegistry.ServiceState.Deployed) {
revert WrongServiceState(uint256(state), serviceId);
}
}

/// @dev Checks for mech validity.
/// @dev mech Agent mech contract address.
/// @param mechStakingInstance Agent mech staking instance address.
/// @param mechServiceId Agent mech service Id.
/// @return multisig Service multisig address.
/// @return multisig
function checkMech(
kupermind marked this conversation as resolved.
Show resolved Hide resolved
address mech,
address mechStakingInstance,
uint256 mechServiceId
) public view returns (address multisig) {
// Check for zero value
if (mechServiceId == 0) {
revert ZeroValue();
}

uint256 mechServiceId = IMech(mech).tokenId();

// Check mech validity as it must be created and recorded via this marketplace
if (mapAgentMechFactories[mech] == address(0)) {
if (mapServiceIdMech[mechServiceId] == mech) {
revert UnauthorizedAccount(mech);
}
kupermind marked this conversation as resolved.
Show resolved Hide resolved

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

// Check that service multisig is the priority mech service multisig
if (!IMech(mech).isOperator(multisig)) {
Expand All @@ -619,25 +567,21 @@ contract MechMarketplace is IErrorsMarketplace {
}

/// @dev Checks for requester validity.
/// @notice Explicitly allows for EOAs without service id.
/// @dev requester Requester contract address.
/// @param requesterStakingInstance Requester staking instance address.
/// @param requesterServiceId Requester service Id.
function checkRequester(
address requester,
address requesterStakingInstance,
uint256 requesterServiceId
) public view {
// Check for requester service
if (requesterServiceId > 0) {
address multisig = checkServiceAndGetMultisig(requesterStakingInstance, requesterServiceId);
address multisig = checkServiceAndGetMultisig(requesterServiceId);

// Check staked service multisig
kupermind marked this conversation as resolved.
Show resolved Hide resolved
if (multisig != requester) {
revert OwnerOnly(requester, multisig);
}
} else if (requesterStakingInstance != address(0)) {
// Check for inconsistency between zero service Id and non-zero staking instance
revert ZeroValue();
}
}

Expand Down Expand Up @@ -696,11 +640,5 @@ contract MechMarketplace is IErrorsMarketplace {
function getMechDeliveryInfo(uint256 requestId) external view returns (MechDelivery memory) {
return mapRequestIdDeliveries[requestId];
}

/// @dev Gets global number of created mechs.
/// @return Number of mechs in a global set.
function getNumMechs() external view returns (uint256) {
return setMechs.length;
}
}

Loading
Loading