diff --git a/contracts/BalanceTrackerFixedPriceBase.sol b/contracts/BalanceTrackerFixedPriceBase.sol index 9bc5c78..6755b49 100644 --- a/contracts/BalanceTrackerFixedPriceBase.sol +++ b/contracts/BalanceTrackerFixedPriceBase.sol @@ -82,11 +82,73 @@ abstract contract BalanceTrackerFixedPriceBase { buyBackBurner = _buyBackBurner; } + /// @dev Drains specified amount. + function _drain(uint256 amount) internal virtual; + + /// @dev Gets native token value or restricts receiving one. + /// @return Received value. function _getOrRestrictNativeValue() internal virtual returns (uint256); - function _getRequiredFunds(address requester, uint256 balanceDiff) internal virtual returns (uint256); + /// @dev Gets required token funds. + /// @param requester Requester address. + /// @param amount Token amount. + /// @return Received amount. + function _getRequiredFunds(address requester, uint256 amount) internal virtual returns (uint256); + + /// @dev Process mech payment. + /// @param mech Mech address. + /// @return mechPayment Mech payment. + /// @return marketplaceFee Marketplace fee. + function _processPayment(address mech) internal returns (uint256 mechPayment, uint256 marketplaceFee) { + // Reentrancy guard + if (_locked > 1) { + revert ReentrancyGuard(); + } + _locked = 2; + + // Get mech balance + uint256 balance = mapMechBalances[mech]; + // If balance is 1, the marketplace fee is still 1, and thus mech payment will be zero + if (balance < 2) { + revert ZeroValue(); + } + + // Calculate mech payment and marketplace fee + uint256 fee = IMechMarketplace(mechMarketplace).fee(); + + // If requested balance is too small, charge the minimal fee + // ceil(a, b) = (a + b - 1) / b + // This formula will always get at least a fee of 1 + marketplaceFee = (balance * fee + (MAX_FEE_FACTOR - 1)) / MAX_FEE_FACTOR; + + // Calculate mech payment + mechPayment = balance - marketplaceFee; + + // Check for zero value, although this must never happen + if (marketplaceFee == 0 || mechPayment == 0) { + revert ZeroValue(); + } + + // Adjust marketplace fee + collectedFees += marketplaceFee; + + // Clear balances + mapMechBalances[mech] = 0; + + // Process withdraw + _withdraw(mech, mechPayment); + + _locked = 1; + } + + /// @dev Withdraws funds. + /// @param account Account address. + /// @param amount Token amount. + function _withdraw(address account, uint256 amount) internal virtual; - // Check and record delivery rate + /// @dev Checks and records delivery rate. + /// @param requester Requester address. + /// @param maxDeliveryRate Request max delivery rate. function checkAndRecordDeliveryRate( address requester, uint256 maxDeliveryRate, @@ -164,8 +226,6 @@ abstract contract BalanceTrackerFixedPriceBase { emit MechPaymentCalculated(mech, requestId, actualDeliveryRate, rateDiff); } - function _drain(uint256 amount) internal virtual; - /// @dev Drains collected fees by sending them to a Buy back burner contract. function drain() external { // Reentrancy guard @@ -189,8 +249,6 @@ abstract contract BalanceTrackerFixedPriceBase { _locked = 1; } - function _withdraw(address mech, uint256 balance) internal virtual; - /// @dev Processes mech payment by mech service multisig. /// @param mech Mech address. /// @return Mech payment. @@ -211,52 +269,6 @@ abstract contract BalanceTrackerFixedPriceBase { return _processPayment(msg.sender); } - /// @dev Process mech payment. - /// @param mech Mech address. - /// @return mechPayment Mech payment. - /// @return marketplaceFee Marketplace fee. - function _processPayment(address mech) internal returns (uint256 mechPayment, uint256 marketplaceFee) { - // Reentrancy guard - if (_locked > 1) { - revert ReentrancyGuard(); - } - _locked = 2; - - // Get mech balance - uint256 balance = mapMechBalances[mech]; - // If balance is 1, the marketplace fee is still 1, and thus mech payment will be zero - if (balance < 2) { - revert ZeroValue(); - } - - // Calculate mech payment and marketplace fee - uint256 fee = IMechMarketplace(mechMarketplace).fee(); - - // If requested balance is too small, charge the minimal fee - // ceil(a, b) = (a + b - 1) / b - // This formula will always get at least a fee of 1 - marketplaceFee = (balance * fee + (MAX_FEE_FACTOR - 1)) / MAX_FEE_FACTOR; - - // Calculate mech payment - mechPayment = balance - marketplaceFee; - - // Check for zero value, although this must never happen - if (marketplaceFee == 0 || mechPayment == 0) { - revert ZeroValue(); - } - - // Adjust marketplace fee - collectedFees += marketplaceFee; - - // Clear balances - mapMechBalances[mech] = 0; - - // Process withdraw - _withdraw(mech, mechPayment); - - _locked = 1; - } - /// @dev Withdraws funds for a specific requester account. function withdraw() external { // Reentrancy guard diff --git a/contracts/interfaces/IBalanceTracker.sol b/contracts/interfaces/IBalanceTracker.sol index 624175d..ebe5b4a 100644 --- a/contracts/interfaces/IBalanceTracker.sol +++ b/contracts/interfaces/IBalanceTracker.sol @@ -3,7 +3,9 @@ pragma solidity ^0.8.28; /// @dev Escrow interface interface IBalanceTracker { - // Check and record delivery rate + /// @dev Checks and records delivery rate. + /// @param requester Requester address. + /// @param maxDeliveryRate Request max delivery rate. /// @param paymentData Additional payment-related request data, if applicable. function checkAndRecordDeliveryRate(address requester, uint256 maxDeliveryRate, bytes memory paymentData) external payable; diff --git a/contracts/BalanceTrackerFixedPriceNative.sol b/contracts/mechs/native/BalanceTrackerFixedPriceNative.sol similarity index 81% rename from contracts/BalanceTrackerFixedPriceNative.sol rename to contracts/mechs/native/BalanceTrackerFixedPriceNative.sol index 47be330..c1fc543 100644 --- a/contracts/BalanceTrackerFixedPriceNative.sol +++ b/contracts/mechs/native/BalanceTrackerFixedPriceNative.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.28; -import {BalanceTrackerFixedPriceBase, ZeroAddress, InsufficientBalance, TransferFailed} from "./BalanceTrackerFixedPriceBase.sol"; -import {IMech} from "./interfaces/IMech.sol"; +import {BalanceTrackerFixedPriceBase, ZeroAddress, InsufficientBalance, TransferFailed} from "../../BalanceTrackerFixedPriceBase.sol"; +import {IMech} from "../../interfaces/IMech.sol"; interface IToken { /// @dev Transfers the token amount. @@ -35,6 +35,19 @@ contract BalanceTrackerFixedPriceNative is BalanceTrackerFixedPriceBase { wrappedNativeToken = _wrappedNativeToken; } + /// @dev Drains specified amount. + /// @param amount Token amount. + function _drain(uint256 amount) internal virtual override { + // Wrap native tokens + _wrap(amount); + // Transfer to Buy back burner + IToken(wrappedNativeToken).transfer(buyBackBurner, amount); + + emit Drained(wrappedNativeToken, amount); + } + + /// @dev Gets native token value or restricts receiving one. + /// @return Received value. function _getOrRestrictNativeValue() internal virtual override returns (uint256) { // Update balance with native value if (msg.value > 0) { @@ -44,23 +57,15 @@ contract BalanceTrackerFixedPriceNative is BalanceTrackerFixedPriceBase { return msg.value; } + /// @dev Gets required token funds. + /// @return Received amount. function _getRequiredFunds(address, uint256) internal virtual override returns (uint256) { return 0; } - function _wrap(uint256 amount) internal virtual { - IWrappedToken(wrappedNativeToken).deposit{value: amount}(); - } - - function _drain(uint256 amount) internal virtual override { - // Wrap native tokens - _wrap(amount); - // Transfer to Buy back burner - IToken(wrappedNativeToken).transfer(buyBackBurner, amount); - - emit Drained(wrappedNativeToken, amount); - } - + /// @dev Withdraws funds. + /// @param account Account address. + /// @param amount Token amount. function _withdraw(address account, uint256 amount) internal virtual override { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = account.call{value: amount}(""); @@ -73,7 +78,13 @@ contract BalanceTrackerFixedPriceNative is BalanceTrackerFixedPriceBase { emit Withdraw(msg.sender, address(0), amount); } - // Deposits funds for requester. + /// @dev Wraps native token. + /// @param amount Token amount. + function _wrap(uint256 amount) internal virtual { + IWrappedToken(wrappedNativeToken).deposit{value: amount}(); + } + + /// @dev Deposits funds for requester. receive() external payable { // Update account balances mapRequesterBalances[msg.sender] += msg.value; diff --git a/contracts/MechFactoryFixedPriceNative.sol b/contracts/mechs/native/MechFactoryFixedPriceNative.sol similarity index 100% rename from contracts/MechFactoryFixedPriceNative.sol rename to contracts/mechs/native/MechFactoryFixedPriceNative.sol diff --git a/contracts/MechFixedPriceNative.sol b/contracts/mechs/native/MechFixedPriceNative.sol similarity index 97% rename from contracts/MechFixedPriceNative.sol rename to contracts/mechs/native/MechFixedPriceNative.sol index 963f074..a87f6b5 100644 --- a/contracts/MechFixedPriceNative.sol +++ b/contracts/mechs/native/MechFixedPriceNative.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.28; -import {OlasMech} from "./OlasMech.sol"; +import {OlasMech} from "../../OlasMech.sol"; /// @title MechFixedPriceNative - Smart contract for OlasMech that accepts a fixed price payment for services in native token. contract MechFixedPriceNative is OlasMech { diff --git a/contracts/integrations/nevermined/BalanceTrackerNvmSubscription.sol b/contracts/mechs/nevermined/BalanceTrackerNvmSubscription.sol similarity index 97% rename from contracts/integrations/nevermined/BalanceTrackerNvmSubscription.sol rename to contracts/mechs/nevermined/BalanceTrackerNvmSubscription.sol index a85946a..de6e22b 100644 --- a/contracts/integrations/nevermined/BalanceTrackerNvmSubscription.sol +++ b/contracts/mechs/nevermined/BalanceTrackerNvmSubscription.sol @@ -86,7 +86,9 @@ contract BalanceTrackerNvmSubscription { subscriptionTokenId = _subscriptionTokenId; } - // Check and record delivery rate + /// @dev Checks and records delivery rate. + /// @param requester Requester address. + /// @param maxDeliveryRate Request max delivery rate. function checkAndRecordDeliveryRate( address requester, uint256 maxDeliveryRate, diff --git a/contracts/integrations/nevermined/MechFactoryNvmSubscription.sol b/contracts/mechs/nevermined/MechFactoryNvmSubscription.sol similarity index 100% rename from contracts/integrations/nevermined/MechFactoryNvmSubscription.sol rename to contracts/mechs/nevermined/MechFactoryNvmSubscription.sol diff --git a/contracts/integrations/nevermined/MechNvmSubscription.sol b/contracts/mechs/nevermined/MechNvmSubscription.sol similarity index 100% rename from contracts/integrations/nevermined/MechNvmSubscription.sol rename to contracts/mechs/nevermined/MechNvmSubscription.sol diff --git a/contracts/BalanceTrackerFixedPriceToken.sol b/contracts/mechs/token/BalanceTrackerFixedPriceToken.sol similarity index 76% rename from contracts/BalanceTrackerFixedPriceToken.sol rename to contracts/mechs/token/BalanceTrackerFixedPriceToken.sol index f9536c8..88e8b30 100644 --- a/contracts/BalanceTrackerFixedPriceToken.sol +++ b/contracts/mechs/token/BalanceTrackerFixedPriceToken.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.28; -import {BalanceTrackerFixedPriceBase, ZeroAddress, NoDepositAllowed, TransferFailed} from "./BalanceTrackerFixedPriceBase.sol"; -import {IMech} from "./interfaces/IMech.sol"; +import {BalanceTrackerFixedPriceBase, ZeroAddress, NoDepositAllowed, TransferFailed} from "../../BalanceTrackerFixedPriceBase.sol"; +import {IMech} from "../../interfaces/IMech.sol"; interface IToken { /// @dev Transfers the token amount. @@ -43,6 +43,17 @@ contract BalanceTrackerFixedPriceToken is BalanceTrackerFixedPriceBase { olas = _olas; } + /// @dev Drains specified amount. + /// @param amount Token amount. + function _drain(uint256 amount) internal virtual override { + // Transfer to Buy back burner + IToken(olas).transfer(buyBackBurner, amount); + + emit Drained(olas, amount); + } + + /// @dev Gets native token value or restricts receiving one. + /// @return Received value. function _getOrRestrictNativeValue() internal virtual override returns (uint256) { // Check for msg.value if (msg.value > 0) { @@ -52,30 +63,30 @@ contract BalanceTrackerFixedPriceToken is BalanceTrackerFixedPriceBase { return 0; } - function _getRequiredFunds(address requester, uint256 balanceDiff) internal virtual override returns (uint256) { + /// @dev Gets required token funds. + /// @param requester Requester address. + /// @param amount Token amount. + /// @return Received amount. + function _getRequiredFunds(address requester, uint256 amount) internal virtual override returns (uint256) { uint256 balanceBefore = IToken(olas).balanceOf(address(this)); // Get tokens from requester - IToken(olas).transferFrom(requester, address(this), balanceDiff); + IToken(olas).transferFrom(requester, address(this), amount); uint256 balanceAfter = IToken(olas).balanceOf(address(this)); // Check the balance uint256 diff = balanceAfter - balanceBefore; - if (diff != balanceDiff) { - revert TransferFailed(olas, requester, address(this), balanceDiff); + if (diff != amount) { + revert TransferFailed(olas, requester, address(this), amount); } - emit Deposit(msg.sender, olas, balanceDiff); - - return balanceDiff; - } - - function _drain(uint256 amount) internal virtual override { - // Transfer to Buy back burner - IToken(olas).transfer(buyBackBurner, amount); + emit Deposit(msg.sender, olas, amount); - emit Drained(olas, amount); + return amount; } + /// @dev Withdraws funds. + /// @param account Account address. + /// @param amount Token amount. function _withdraw(address account, uint256 amount) internal virtual override { bool success = IToken(olas).transfer(account, amount); @@ -87,7 +98,8 @@ contract BalanceTrackerFixedPriceToken is BalanceTrackerFixedPriceBase { emit Withdraw(msg.sender, olas, amount); } - // Deposits token funds for requester. + /// @dev Deposits token funds for requester. + /// @param amount Token amount. function deposit(uint256 amount) external { IToken(olas).transferFrom(msg.sender, address(this), amount); diff --git a/contracts/MechFactoryFixedPriceToken.sol b/contracts/mechs/token/MechFactoryFixedPriceToken.sol similarity index 100% rename from contracts/MechFactoryFixedPriceToken.sol rename to contracts/mechs/token/MechFactoryFixedPriceToken.sol diff --git a/contracts/MechFixedPriceToken.sol b/contracts/mechs/token/MechFixedPriceToken.sol similarity index 97% rename from contracts/MechFixedPriceToken.sol rename to contracts/mechs/token/MechFixedPriceToken.sol index 6144d21..a94ed0d 100644 --- a/contracts/MechFixedPriceToken.sol +++ b/contracts/mechs/token/MechFixedPriceToken.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.28; -import {OlasMech} from "./OlasMech.sol"; +import {OlasMech} from "../../OlasMech.sol"; /// @title MechFixedPriceToken - Smart contract for OlasMech that accepts a fixed price payment for services in native token. contract MechFixedPriceToken is OlasMech { diff --git a/contracts/KarmaProxy.sol b/contracts/proxies/KarmaProxy.sol similarity index 100% rename from contracts/KarmaProxy.sol rename to contracts/proxies/KarmaProxy.sol diff --git a/contracts/MechMarketplaceProxy.sol b/contracts/proxies/MechMarketplaceProxy.sol similarity index 100% rename from contracts/MechMarketplaceProxy.sol rename to contracts/proxies/MechMarketplaceProxy.sol