Skip to content

Commit

Permalink
chore(contracts/core): fillout inbox interface
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinhalliday committed Nov 5, 2024
1 parent cef8c92 commit 0763ad7
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 72 deletions.
95 changes: 25 additions & 70 deletions contracts/core/src/solve/Inbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ pragma solidity =0.8.24;
import { OwnableRoles } from "solady/src/auth/OwnableRoles.sol";
import { ReentrancyGuard } from "solady/src/utils/ReentrancyGuard.sol";
import { Initializable } from "solady/src/utils/Initializable.sol";
import { XAppBase } from "../pkg/XAppBase.sol";
import { IInbox } from "./interfaces/IInbox.sol";

import { SafeTransferLib } from "solady/src/utils/SafeTransferLib.sol";
import { IConversionRateOracle } from "../interfaces/IConversionRateOracle.sol";
import { IConversionRateOracle } from "src/interfaces/IConversionRateOracle.sol";
import { XAppBase } from "src/pkg/XAppBase.sol";
import { IInbox } from "./interfaces/IInbox.sol";
import { Solve } from "./Solve.sol";

/**
Expand All @@ -25,50 +24,6 @@ contract Inbox is OwnableRoles, ReentrancyGuard, Initializable, XAppBase, IInbox
error TransferFailed();
error RequestStateInvalid();

/**
* @notice Emitted when a request is created.
* @param id ID of the request.
* @param from Address of the user who created the request.
* @param call Details of the call to be executed on another chain.
* @param deposits Array of deposits backing the request.
*/
event Requested(bytes32 indexed id, address indexed from, Solve.Call call, Solve.Deposit[] deposits);

/**
* @notice Emitted when a request is accepted.
* @param id ID of the request.
* @param by Address of the solver who accepted the request.
*/
event Accepted(bytes32 indexed id, address indexed by);

/**
* @notice Emitted when a request is rejected.
* @param id ID of the request.
* @param by Address of the solver who rejected the request.
* @param reason Reason for rejecting the request.
*/
event Rejected(bytes32 indexed id, address indexed by, Solve.RejectReason indexed reason);

/**
* @notice Emitted when a request is cancelled.
* @param id ID of the request.
*/
event Reverted(bytes32 indexed id);

/**
* @notice Emitted when a request is fulfilled.
* @param id ID of the request.
* @param callHash Hash of the call executed on another chain.
* @param creditedTo Address of the recipient credited the funds by the solver.
*/
event Fulfilled(bytes32 indexed id, bytes32 indexed callHash, address indexed creditedTo);

/**
* @notice Emitted when a request is claimed.
* @param id ID of the request.
*/
event Claimed(bytes32 indexed id);

/**
* @notice Role for solvers.
* @dev _ROLE_0 evaluates to '1'.
Expand Down Expand Up @@ -114,28 +69,6 @@ contract Inbox is OwnableRoles, ReentrancyGuard, Initializable, XAppBase, IInbox
return _requests[id];
}

/**
* @notice Suggest the amount of native currency to send with a request.
* @param call Details of the call to be executed on another chain.
* @param gasLimit Maximum gas limit for the call.
* @param gasPrice Destination chain gas price in wei.
* @param fulfillFee Fee for the fulfill call, retrieved from the destination outbox.
*/
function suggestNativePayment(Solve.Call calldata call, uint64 gasLimit, uint64 gasPrice, uint256 fulfillFee)
external
view
returns (uint256)
{
IConversionRateOracle oracle = IConversionRateOracle(omni.feeOracle());

uint256 nativeValue = call.value * oracle.toNativeRate(call.destChainId) / oracle.CONVERSION_RATE_DENOM();
uint256 executionFee = omni.feeFor(call.destChainId, call.data, gasLimit);
uint256 acceptFee = 55_000 * gasPrice;
uint256 solveFee = 100_000 gwei; // TODO: determine solve fee

return nativeValue + executionFee + acceptFee + solveFee + fulfillFee;
}

/**
* @notice Open a request to execute a call on another chain, backed by deposits.
* Token deposits are transferred from msg.sender to this inbox.
Expand Down Expand Up @@ -249,6 +182,28 @@ contract Inbox is OwnableRoles, ReentrancyGuard, Initializable, XAppBase, IInbox
emit Claimed(id);
}

/**
* @notice Suggest the amount of native currency to send with a request.
* @param call Details of the call to be executed on another chain.
* @param gasLimit Maximum gas limit for the call.
* @param gasPrice Destination chain gas price in wei.
* @param fulfillFee Fee for the fulfill call, retrieved from the destination outbox.
*/
function suggestNativePayment(Solve.Call calldata call, uint64 gasLimit, uint64 gasPrice, uint256 fulfillFee)
external
view
returns (uint256)
{
IConversionRateOracle oracle = IConversionRateOracle(omni.feeOracle());

uint256 nativeValue = call.value * oracle.toNativeRate(call.destChainId) / oracle.CONVERSION_RATE_DENOM();
uint256 executionFee = omni.feeFor(call.destChainId, call.data, gasLimit);
uint256 acceptFee = 55_000 * gasPrice;
uint256 solveFee = 100_000 gwei; // TODO: determine solve fee

return nativeValue + executionFee + acceptFee + solveFee + fulfillFee;
}

/**
* @dev Transfer deposits to recipient. Used regardless of refund or claim.
*/
Expand Down
106 changes: 106 additions & 0 deletions contracts/core/src/solve/interfaces/IInbox.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,112 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity =0.8.24;

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

interface IInbox {
/**
* @notice Emitted when a request is created.
* @param id ID of the request.
* @param from Address of the user who created the request.
* @param call Details of the call to be executed on another chain.
* @param deposits Array of deposits backing the request.
*/
event Requested(bytes32 indexed id, address indexed from, Solve.Call call, Solve.Deposit[] deposits);

/**
* @notice Emitted when a request is accepted.
* @param id ID of the request.
* @param by Address of the solver who accepted the request.
*/
event Accepted(bytes32 indexed id, address indexed by);

/**
* @notice Emitted when a request is rejected.
* @param id ID of the request.
* @param by Address of the solver who rejected the request.
* @param reason Reason for rejecting the request.
*/
event Rejected(bytes32 indexed id, address indexed by, Solve.RejectReason indexed reason);

/**
* @notice Emitted when a request is cancelled.
* @param id ID of the request.
*/
event Reverted(bytes32 indexed id);

/**
* @notice Emitted when a request is fulfilled.
* @param id ID of the request.
* @param callHash Hash of the call executed on another chain.
* @param creditedTo Address of the recipient credited the funds by the solver.
*/
event Fulfilled(bytes32 indexed id, bytes32 indexed callHash, address indexed creditedTo);

/**
* @notice Emitted when a request is claimed.
* @param id ID of the request.
*/
event Claimed(bytes32 indexed id);

/**
* /**
* @notice Returns the request with the given ID.
*/
function getRequest(bytes32 id) external view returns (Solve.Request memory);

/**
* @notice Suggest the amount of native currency to send with a request.
* @param call Details of the call to be executed on another chain.
* @param gasLimit Maximum gas limit for the call.
* @param gasPrice Destination chain gas price in wei.
* @param fulfillFee Fee for the fulfill call, retrieved from the destination outbox.
*/
function suggestNativePayment(Solve.Call calldata call, uint64 gasLimit, uint64 gasPrice, uint256 fulfillFee)
external
view
returns (uint256);

/**
* @notice Open a request to execute a call on another chain, backed by deposits.
* Token deposits are transferred from msg.sender to this inbox.
* @param call Details of the call to be executed on another chain.
* @param deposits Array of deposits backing the request.
*/
function request(Solve.Call calldata call, Solve.TokenDeposit[] calldata deposits)
external
payable
returns (bytes32 id);

/**
* @notice Accept an open request.
* @dev Only a whitelisted solver can accept.
* @param id ID of the request.
*/
function accept(bytes32 id) external;

/**
* @notice Reject an open request.
* @dev Only a whitelisted solver can reject.
* @param id ID of the request.
*/
function reject(bytes32 id, Solve.RejectReason reason) external;

/**
* @notice Cancel an open or rejected request and refund deposits.
* @dev Only request initiator can cancel.
* @param id ID of the request.
*/
function cancel(bytes32 id) external;

/**
* @notice Fulfill a request.
* @dev Only callable by the outbox.
*/
function markFulfilled(bytes32 id, bytes32 callHash, address creditTo) external;

/**
* @notice Claim a fulfilled request.
* @param id ID of the request.
*/
function claim(bytes32 id) external;
}
4 changes: 2 additions & 2 deletions contracts/core/test/solve/Outbox_fulfill.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/trans
import { MockToken } from "test/utils/MockToken.sol";
import { MockVault } from "test/utils/MockVault.sol";
import { Outbox } from "src/solve/Outbox.sol";
import { Inbox } from "src/solve/Inbox.sol";
import { Inbox, IInbox } from "src/solve/Inbox.sol";
import { Solve } from "src/solve/Solve.sol";

import "test/xchain/common/Base.sol";
Expand Down Expand Up @@ -261,7 +261,7 @@ contract Outbox_fulfill_Test is Base {
vm.prank(relayer);
expectCalls(xsub.msgs);
vm.expectEmit(true, true, true, true, address(inbox));
emit Inbox.Fulfilled(bytes32(uint256(1)), callHash, solver);
emit IInbox.Fulfilled(bytes32(uint256(1)), callHash, solver);
vm.expectEmit(true, true, true, false, address(portal));
emit IOmniPortal.XReceipt(chainAId, ConfLevel.Finalized, uint64(1), 0, relayer, true, bytes(""));
portal.xsubmit(xsub);
Expand Down

0 comments on commit 0763ad7

Please sign in to comment.