Skip to content

Commit

Permalink
Merge pull request #77 from base-org/jack/interface-updates
Browse files Browse the repository at this point in the history
Adjust Inbox & Outbox interfaces for improved efficiency
  • Loading branch information
jackchuma authored Feb 5, 2025
2 parents be1d48a + 40339ca commit f969d64
Show file tree
Hide file tree
Showing 18 changed files with 575 additions and 885 deletions.
38 changes: 18 additions & 20 deletions contracts/script/actions/SubmitRequest.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@
pragma solidity 0.8.24;

import {Script} from "forge-std/Script.sol";
import {CAIP2} from "openzeppelin-contracts/contracts/utils/CAIP2.sol";
import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol";

import {ERC7786Base} from "../../src/ERC7786Base.sol";
import {GlobalTypes} from "../../src/libraries/GlobalTypes.sol";
import {RIP7755Base} from "../../src/RIP7755Base.sol";
import {RIP7755Outbox} from "../../src/RIP7755Outbox.sol";
import {HelperConfig} from "../HelperConfig.s.sol";

contract SubmitRequest is Script, ERC7786Base {
using Strings for uint256;

HelperConfig public helperConfig;
contract SubmitRequest is Script, RIP7755Base {
using GlobalTypes for address;

bytes4 internal constant _REWARD_ATTRIBUTE_SELECTOR = 0xa362e5db; // reward(bytes32,uint256) rewardAsset, rewardAmount
bytes4 internal constant _DELAY_ATTRIBUTE_SELECTOR = 0x84f550e0; // delay(uint256,uint256) finalityDelaySeconds, expiry
bytes4 internal constant _L2_ORACLE_ATTRIBUTE_SELECTOR = 0x7ff7245a; // l2Oracle(address)
bytes32 private constant _NATIVE_ASSET = 0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;

HelperConfig public helperConfig;

constructor() {
helperConfig = new HelperConfig();
}
Expand All @@ -29,39 +31,35 @@ contract SubmitRequest is Script, ERC7786Base {

RIP7755Outbox outbox = RIP7755Outbox(outboxAddr);

(string memory destinationChain, Message[] memory messages, bytes[] memory attributes) =
(bytes32 destinationChain, bytes32 receiver, Call[] memory calls, bytes[] memory attributes) =
_initMessage(destinationChainId, duration);

vm.startBroadcast(config.deployerKey);
outbox.sendMessages{value: 0.0002 ether}(destinationChain, messages, attributes);
outbox.sendMessage{value: 0.0002 ether}(destinationChain, receiver, abi.encode(calls), attributes);
vm.stopBroadcast();
}

function _initMessage(uint256 destinationChainId, uint256 duration)
private
returns (string memory, Message[] memory, bytes[] memory)
returns (bytes32, bytes32, Call[] memory, bytes[] memory)
{
HelperConfig.NetworkConfig memory dstConfig = helperConfig.getConfig(destinationChainId);
// HelperConfig.NetworkConfig memory srcConfig = helperConfig.getConfig(block.chainid);

Message[] memory calls = new Message[](1);
bytes[] memory messageAttributes = new bytes[](1);
messageAttributes[0] = abi.encodeWithSelector(_VALUE_ATTRIBUTE_SELECTOR, 0.0001 ether);
calls[0] = Message({
receiver: Strings.toChecksumHexString(0x8C1a617BdB47342F9C17Ac8750E0b070c372C721),
payload: "",
attributes: messageAttributes
});
Call[] memory calls = new Call[](1);
calls[0] =
Call({to: 0x8C1a617BdB47342F9C17Ac8750E0b070c372C721.addressToBytes32(), data: "", value: 0.0001 ether});

string memory destinationChain = CAIP2.format("eip155", destinationChainId.toString());
bytes32 destinationChain = bytes32(destinationChainId);
bytes32 receiver = dstConfig.inbox.addressToBytes32();
bytes[] memory attributes = new bytes[](3);

attributes[0] = abi.encodeWithSelector(_REWARD_ATTRIBUTE_SELECTOR, _NATIVE_ASSET, 0.0002 ether);
attributes[1] = abi.encodeWithSelector(_DELAY_ATTRIBUTE_SELECTOR, duration, block.timestamp + 2 weeks);
attributes[2] = abi.encodeWithSelector(_L2_ORACLE_ATTRIBUTE_SELECTOR, dstConfig.l2Oracle);
// attributes[2] = abi.encodeWithSelector(_SHOYU_BASHI_ATTRIBUTE_SELECTOR, srcConfig.shoyuBashi);

return (destinationChain, calls, attributes);
return (destinationChain, receiver, calls, attributes);
}

// Including to block from coverage report
Expand Down
37 changes: 22 additions & 15 deletions contracts/script/actions/SubmitToInbox.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,40 @@
pragma solidity 0.8.24;

import {Script} from "forge-std/Script.sol";
import {CAIP2} from "openzeppelin-contracts/contracts/utils/CAIP2.sol";

import {ERC7786Base} from "../../src/ERC7786Base.sol";
import {GlobalTypes} from "../../src/libraries/GlobalTypes.sol";
import {RIP7755Base} from "../../src/RIP7755Base.sol";
import {RIP7755Inbox} from "../../src/RIP7755Inbox.sol";

contract SubmitToInbox is Script, ERC7786Base {
contract SubmitToInbox is Script, RIP7755Base {
using GlobalTypes for address;

bytes4 internal constant _REWARD_ATTRIBUTE_SELECTOR = 0xa362e5db; // reward(bytes32,uint256) rewardAsset, rewardAmount
bytes4 internal constant _DELAY_ATTRIBUTE_SELECTOR = 0x84f550e0; // delay(uint256,uint256) finalityDelaySeconds, expiry
bytes4 internal constant _NONCE_ATTRIBUTE_SELECTOR = 0xce03fdab; // nonce(uint256)
bytes4 internal constant _REQUESTER_ATTRIBUTE_SELECTOR = 0x3bd94e4c; // requester(bytes32)
bytes4 internal constant _SHOYU_BASHI_ATTRIBUTE_SELECTOR = 0xda07e15d; // shoyuBashi(bytes32)

function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
RIP7755Inbox inbox = RIP7755Inbox(payable(0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512));
address fulfiller = 0x23214A0864FC0014CAb6030267738F01AFfdd547;

(string memory sourceChain, string memory sender, Message[] memory messages, bytes[] memory attributes) =
_initMessage();
(bytes32 sourceChain, bytes32 sender, bytes memory payload, bytes[] memory attributes) = _initMessage();

vm.startBroadcast(pk);
inbox.executeMessages(sourceChain, sender, messages, attributes);
inbox.fulfill(sourceChain, sender, payload, attributes, fulfiller);
vm.stopBroadcast();
}

// Using dummy values for local testing
function _initMessage() private pure returns (string memory, string memory, Message[] memory, bytes[] memory) {
Message[] memory calls = new Message[](0);
function _initMessage() private pure returns (bytes32, bytes32, bytes memory, bytes[] memory) {
Call[] memory calls = new Call[](0);

string memory sourceChain = CAIP2.format("eip155", "31337");
string memory sender = "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496";
bytes[] memory attributes = new bytes[](6);
bytes32 sourceChain = bytes32(uint256(31337));
bytes32 sender = 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496.addressToBytes32();
bytes memory payload = abi.encode(calls);
bytes[] memory attributes = new bytes[](5);

attributes[0] = abi.encodeWithSelector(
_REWARD_ATTRIBUTE_SELECTOR, 0x000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a, 1 ether
Expand All @@ -36,13 +45,11 @@ contract SubmitToInbox is Script, ERC7786Base {
attributes[3] = abi.encodeWithSelector(
_REQUESTER_ATTRIBUTE_SELECTOR, 0x000000000000000000000000328809bc894f92807417d2dad6b7c998c1afdac6
);
attributes[4] =
abi.encodeWithSelector(_FULFILLER_ATTRIBUTE_SELECTOR, 0x23214A0864FC0014CAb6030267738F01AFfdd547);
attributes[5] = abi.encodeWithSelector(
attributes[4] = abi.encodeWithSelector(
_SHOYU_BASHI_ATTRIBUTE_SELECTOR, 0x0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f
);

return (sourceChain, sender, calls, attributes);
return (sourceChain, sender, payload, attributes);
}

// Including to block from coverage report
Expand Down
121 changes: 0 additions & 121 deletions contracts/src/ERC7786Base.sol

This file was deleted.

92 changes: 92 additions & 0 deletions contracts/src/RIP7755Base.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/// @title ERC7786Base
///
/// @author Coinbase (https://github.com/base-org/RIP-7755-poc)
///
/// @notice This contract contains the selectors for the RIP-7755-supported attributes of the ERC7786 standard
contract RIP7755Base {
/// @notice Low-level call specs representing the desired transaction on destination chain
struct Call {
/// @dev The address to call
bytes32 to;
/// @dev The calldata to call with
bytes data;
/// @dev The native asset value of the call
uint256 value;
}

/// @notice The selector for the precheck attribute
bytes4 internal constant _PRECHECK_ATTRIBUTE_SELECTOR = 0xfa1e5831; // precheck(address)

/// @notice The selector for the isUserOp attribute. Used to designate a request designated to be a destination
/// chain ERC-4337 User Operation
bytes4 internal constant _USER_OP_ATTRIBUTE_SELECTOR = 0xd45448dd; // isUserOp(bool)

/// @notice This error is thrown if an attribute is not found in the attributes array
///
/// @param selector The selector of the attribute that was not found
error AttributeNotFound(bytes4 selector);

/// @notice Returns the keccak256 hash of a message request
///
/// @dev Filters out the fulfiller attribute from the attributes array
///
/// @param sourceChain The source chain identifier
/// @param sender The account address of the sender
/// @param destinationChain The destination chain identifier
/// @param receiver The account address of the receiver
/// @param payload The encoded calls to be included in the request
/// @param attributes The attributes to be included in the message
///
/// @return _ The keccak256 hash of the message request
function getRequestId(
bytes32 sourceChain,
bytes32 sender,
bytes32 destinationChain,
bytes32 receiver,
bytes calldata payload,
bytes[] calldata attributes
) public pure returns (bytes32) {
return keccak256(abi.encode(sourceChain, sender, destinationChain, receiver, payload, attributes));
}

/// @notice Locates an attribute in the attributes array
///
/// @custom:reverts If the attribute is not found
///
/// @param attributes The attributes array to search
/// @param selector The selector of the attribute to find
///
/// @return attribute The attribute found
function _locateAttribute(bytes[] calldata attributes, bytes4 selector) internal pure returns (bytes calldata) {
(bool found, bytes calldata attribute) = _locateAttributeUnchecked(attributes, selector);

if (!found) {
revert AttributeNotFound(selector);
}

return attribute;
}

/// @notice Locates an attribute in the attributes array without checking if the attribute is found
///
/// @param attributes The attributes array to search
/// @param selector The selector of the attribute to find
///
/// @return found Whether the attribute was found
/// @return attribute The attribute found
function _locateAttributeUnchecked(bytes[] calldata attributes, bytes4 selector)
internal
pure
returns (bool found, bytes calldata attribute)
{
for (uint256 i; i < attributes.length; i++) {
if (bytes4(attributes[i]) == selector) {
return (true, attributes[i]);
}
}
return (false, attributes[0]);
}
}
Loading

0 comments on commit f969d64

Please sign in to comment.