Skip to content

Commit

Permalink
fix #63
Browse files Browse the repository at this point in the history
  • Loading branch information
hujw77 committed Oct 31, 2023
1 parent ec8fcb4 commit 3ac93d3
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 72 deletions.
9 changes: 7 additions & 2 deletions src/Channel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@ contract Channel is UserConfig {
/// @param from User application contract address which send the message.
/// @param toChainId The Message destination chain id.
/// @param to User application contract address which receive the message.
/// @param gasLimit Gas limit for UA used.
/// @param encoded The calldata which encoded by ABI Encoding.
function _send(address from, uint256 toChainId, address to, bytes calldata encoded) internal returns (bytes32) {
function _send(address from, uint256 toChainId, address to, uint256 gasLimit, bytes calldata encoded)
internal
returns (bytes32)
{
// only cross-chain message
require(toChainId != LOCAL_CHAINID(), "!cross-chain");
// get this message leaf index.
Expand All @@ -84,7 +88,8 @@ contract Channel is UserConfig {
from: from,
toChainId: toChainId,
to: to,
encoded: encoded
encoded: encoded,
gasLimit: gasLimit
});
// hash the message.
bytes32 msgHash = hash(message);
Expand Down
2 changes: 2 additions & 0 deletions src/Common.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pragma solidity 0.8.17;
/// @param from User application contract address which send the message.
/// @param toChainId The Message destination chain id.
/// @param to User application contract address which receive the message.
/// @param gasLimit Gas limit for UA used.
/// @param encoded The calldata which encoded by ABI Encoding.
struct Message {
address channel;
Expand All @@ -34,6 +35,7 @@ struct Message {
address from;
uint256 toChainId;
address to;
uint256 gasLimit;
bytes encoded; /*(abi.encodePacked(SELECTOR, PARAMS))*/
}

Expand Down
67 changes: 40 additions & 27 deletions src/ORMP.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,50 +36,66 @@ contract ORMP is ReentrancyGuard, Channel {
/// @notice follow https://eips.ethereum.org/EIPS/eip-5750
/// @param toChainId The Message destination chain id.
/// @param to User application contract address which receive the message.
/// @param gasLimit Gas limit for UA used.
/// @param encoded The calldata which encoded by ABI Encoding.
/// @param refund Return extra fee to refund address.
/// @param params General extensibility for relayer to custom functionality.
function send(uint256 toChainId, address to, bytes calldata encoded, address refund, bytes calldata params)
external
payable
sendNonReentrant
returns (bytes32)
{
function send(
uint256 toChainId,
address to,
uint256 gasLimit,
bytes calldata encoded,
address refund,
bytes calldata params
) external payable sendNonReentrant returns (bytes32) {
// user application address.
address ua = msg.sender;
// fetch user application's config.
Config memory uaConfig = getAppConfig(ua);
// send message by channel, return the hash of the message as id.
bytes32 msgHash = _send(ua, toChainId, to, encoded);
bytes32 msgHash = _send(ua, toChainId, to, gasLimit, encoded);

// handle fee
_handleFee(ua, refund, msgHash, toChainId, gasLimit, encoded, params);

return msgHash;
}

function _handleFee(
address ua,
address refund,
bytes32 msgHash,
uint256 toChainId,
uint256 gasLimit,
bytes calldata encoded,
bytes calldata params
) internal {
// fetch user application's config.
Config memory uaConfig = getAppConfig(ua);
// handle relayer fee
uint256 relayerFee = _handleRelayer(uaConfig.relayer, msgHash, toChainId, ua, encoded.length, params);
uint256 relayerFee = _handleRelayer(uaConfig.relayer, msgHash, toChainId, ua, gasLimit, encoded, params);
// handle oracle fee
uint256 oracleFee = _handleOracle(uaConfig.oracle, msgHash, toChainId, ua);

//refund
// refund
if (msg.value > relayerFee + oracleFee) {
uint256 refundFee = msg.value - (relayerFee + oracleFee);
(bool success,) = refund.call{value: refundFee}("");
require(success, "!refund");
}

return msgHash;
}

/// @notice Get a quote in source native gas, for the amount that send() requires to pay for message delivery.
/// @param toChainId The Message destination chain id.
// @param to User application contract address which receive the message.
// @param ua User application contract address which send the message.
/// @param gasLimit Gas limit for UA used.
/// @param encoded The calldata which encoded by ABI Encoding.
/// @param params General extensibility for relayer to custom functionality.
function fee(uint256 toChainId, address, /*to*/ bytes calldata encoded, bytes calldata params)
function fee(uint256 toChainId, address ua, uint256 gasLimit, bytes calldata encoded, bytes calldata params)
external
view
returns (uint256)
{
address ua = msg.sender;
Config memory uaConfig = getAppConfig(ua);
uint256 relayerFee = IRelayer(uaConfig.relayer).fee(toChainId, ua, encoded.length, params);
uint256 relayerFee = IRelayer(uaConfig.relayer).fee(toChainId, ua, gasLimit, encoded, params);
uint256 oracleFee = IOracle(uaConfig.oracle).fee(toChainId, ua);
return relayerFee + oracleFee;
}
Expand All @@ -89,10 +105,11 @@ contract ORMP is ReentrancyGuard, Channel {
bytes32 msgHash,
uint256 toChainId,
address ua,
uint256 size,
uint256 gasLimit,
bytes calldata encoded,
bytes calldata params
) internal returns (uint256) {
uint256 relayerFee = IRelayer(relayer).fee(toChainId, ua, size, params);
uint256 relayerFee = IRelayer(relayer).fee(toChainId, ua, gasLimit, encoded, params);
IRelayer(relayer).assign{value: relayerFee}(msgHash, params);
return relayerFee;
}
Expand All @@ -107,27 +124,23 @@ contract ORMP is ReentrancyGuard, Channel {
/// @notice Only channel could call this function.
/// @param message Verified receive message info.
/// @param proof Message proof of this message.
/// @param gasLimit The gas limit of message execute.
/// @return dispatchResult Result of the message dispatch.
function recv(Message calldata message, bytes calldata proof, uint256 gasLimit)
function recv(Message calldata message, bytes calldata proof)
external
recvNonReentrant
returns (bool dispatchResult)
{
bytes32 msgHash = _recv(message, proof);
dispatchResult = _dispatch(message, msgHash, gasLimit);
dispatchResult = _dispatch(message, msgHash);
// emit dispatched message event.
emit MessageDispatched(msgHash, dispatchResult);
}

/// @dev Dispatch the cross chain message.
function _dispatch(Message memory message, bytes32 msgHash, uint256 gasLimit)
private
returns (bool dispatchResult)
{
function _dispatch(Message memory message, bytes32 msgHash) private returns (bool dispatchResult) {
// Deliver the message to user application contract address.
(dispatchResult,) = message.to.excessivelySafeCall(
gasLimit, 0, abi.encodePacked(message.encoded, msgHash, message.fromChainId, message.from)
message.gasLimit, 0, abi.encodePacked(message.encoded, msgHash, message.fromChainId, message.from)
);
}
}
19 changes: 11 additions & 8 deletions src/eco/Relayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,15 @@ contract Relayer {
}

// params = [extraGas]
function fee(uint256 toChainId, address, /*ua*/ uint256 size, bytes calldata params)
public
view
returns (uint256)
{
uint256 extraGas = abi.decode(params, (uint256));
function fee(
uint256 toChainId,
address, /*ua*/
uint256 gasLimit,
bytes calldata encoded,
bytes calldata /*params*/
) public view returns (uint256) {
uint256 size = encoded.length;
uint256 extraGas = gasLimit;
DstPrice memory p = priceOf[toChainId];
DstConfig memory c = configOf[toChainId];

Expand All @@ -112,7 +115,7 @@ contract Relayer {
emit Assigned(msgHash, msg.value, params, IORMP(PROTOCOL).prove());
}

function relay(Message calldata message, bytes calldata proof, uint256 gasLimit) external onlyApproved {
IORMP(PROTOCOL).recv(message, proof, gasLimit);
function relay(Message calldata message, bytes calldata proof) external onlyApproved {
IORMP(PROTOCOL).recv(message, proof);
}
}
18 changes: 10 additions & 8 deletions src/interfaces/IORMP.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ interface IORMP {
/// @notice follow https://eips.ethereum.org/EIPS/eip-5750
/// @param toChainId The Message destination chain id.
/// @param to User application contract address which receive the message.
/// @param gasLimit Gas limit for UA used.
/// @param encoded The calldata which encoded by ABI Encoding.
/// @param refund Return extra fee to refund address.
/// @param params General extensibility for relayer to custom functionality.
/// @return Return the hash of the message as message id.
function send(uint256 toChainId, address to, bytes calldata encoded, address refund, bytes calldata params)
external
payable
returns (bytes32);
function send(
uint256 toChainId,
address to,
uint256 gasLimit,
bytes calldata encoded,
address refund,
bytes calldata params
) external payable returns (bytes32);

/// @notice Get a quote in source native gas, for the amount that send() requires to pay for message delivery.
/// @param toChainId The Message destination chain id.
Expand All @@ -46,11 +51,8 @@ interface IORMP {
/// @dev Recv verified message and dispatch to destination user application address.
/// @param message Verified receive message info.
/// @param proof Message proof of this message.
/// @param gasLimit The gas limit of message execute.
/// @return dispatchResult Result of the message dispatch.
function recv(Message calldata message, bytes calldata proof, uint256 gasLimit)
external
returns (bool dispatchResult);
function recv(Message calldata message, bytes calldata proof) external returns (bool dispatchResult);

function prove() external view returns (bytes32[32] memory);

Expand Down
8 changes: 6 additions & 2 deletions src/interfaces/IRelayer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ interface IRelayer {
/// @notice Fetch relayer price to relay message to the destination chain.
/// @param toChainId The destination chain id.
/// @param ua The user application which send the message.
/// @param size The size of message encoded payload.
/// @param gasLimit Gas limit for UA used.
/// @param encoded The calldata which encoded by ABI Encoding.
/// @param params General extensibility for relayer to custom functionality.
/// @return Relayer price in source native gas.
function fee(uint256 toChainId, address ua, uint256 size, bytes calldata params) external view returns (uint256);
function fee(uint256 toChainId, address ua, uint256 gasLimit, bytes calldata encoded, bytes calldata params)
external
view
returns (uint256);

/// @notice Assign the relay message task to relayer maintainer.
/// @param msgHash Hash of the message.
Expand Down
18 changes: 10 additions & 8 deletions test/Channel.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ contract ChannelTest is Test, Verifier {
}

function test_sendMessage() public {
channel.sendMessage(self, 2, self, "");
channel.sendMessage(self, 2, self, 0, "");
}

function testFail_sendMessage_notCrossChain() public {
channel.sendMessage(self, 1, self, "");
channel.sendMessage(self, 1, self, 0, "");
}

function test_recvMessage() public {
bytes32 msgHash = channel.sendMessage(self, 2, self, "");
bytes32 msgHash = channel.sendMessage(self, 2, self, 0, "");

Message memory message = Message({
channel: address(channel),
Expand All @@ -64,7 +64,8 @@ contract ChannelTest is Test, Verifier {
from: self,
toChainId: 2,
to: self,
encoded: ""
encoded: "",
gasLimit: 0
});
assertEq(msgHash, hash(message));
Proof memory proof = Proof({blockNumber: block.number, messageIndex: 0, messageProof: channel.prove()});
Expand All @@ -76,15 +77,16 @@ contract ChannelTest is Test, Verifier {
for (uint256 i = 0; i < 100; i++) {
vm.chainId(1);
uint256 index = channel.messageCount();
bytes32 msgHash = channel.sendMessage(self, 2, self, "");
bytes32 msgHash = channel.sendMessage(self, 2, self, 0, "");
Message memory message = Message({
channel: address(channel),
index: index,
fromChainId: 1,
from: self,
toChainId: 2,
to: self,
encoded: ""
encoded: "",
gasLimit: 0
});
assertEq(msgHash, hash(message));
Proof memory proof = Proof({blockNumber: block.number, messageIndex: index, messageProof: channel.prove()});
Expand All @@ -101,11 +103,11 @@ contract ChannelTest is Test, Verifier {
contract ChannelWrapper is Channel {
constructor(address dao) Channel(dao) {}

function sendMessage(address from, uint256 toChainId, address to, bytes calldata encoded)
function sendMessage(address from, uint256 toChainId, address to, uint256 gasLimit, bytes calldata encoded)
public
returns (bytes32)
{
return _send(from, toChainId, to, encoded);
return _send(from, toChainId, to, gasLimit, encoded);
}

function recvMessage(Message calldata message, bytes calldata proof) public {
Expand Down
6 changes: 4 additions & 2 deletions test/Common.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ contract CommonTest is Test {
from: address(0x0),
toChainId: 2,
to: address(0x0),
encoded: ""
encoded: "",
gasLimit: 0
});
assertEq0(
hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000",
Expand All @@ -46,7 +47,8 @@ contract CommonTest is Test {
from: 0x0f14341A7f464320319025540E8Fe48Ad0fe5aec,
toChainId: 43,
to: 0x000000fbfBc6954C8CBba3130b5Aee7f3Ea5108e,
encoded: ""
encoded: "",
gasLimit: 0
});
assertEq(bytes32(0xec824c8e8f1f19fadc3b4532bc2925af53fdad9162eecc17342909ac8ab787f7), hash(message));
}
Expand Down
20 changes: 14 additions & 6 deletions test/ORMP.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,32 @@ contract ORMPTest is Test, Verifier {
vm.chainId(1);
ormp = new ORMP(self);
ormp.setDefaultConfig(self, self);
message =
Message({channel: address(ormp), index: 0, fromChainId: 1, from: self, toChainId: 2, to: self, encoded: ""});
message = Message({
channel: address(ormp),
index: 0,
fromChainId: 1,
from: self,
toChainId: 2,
to: self,
encoded: "",
gasLimit: 0
});
}

function test_send() public {
perform_send();
}

function perform_send() public {
uint256 f = ormp.fee(2, self, "", "");
ormp.send{value: f}(2, self, "", self, "");
uint256 f = ormp.fee(2, self, 0, "", "");
ormp.send{value: f}(2, self, 0, "", self, "");
proof = Proof({blockNumber: block.number, messageIndex: ormp.messageCount() - 1, messageProof: ormp.prove()});
vm.chainId(2);
}

function test_recv() public {
perform_send();
bool r = ormp.recv(message, abi.encode(proof), gasleft());
bool r = ormp.recv(message, abi.encode(proof));
assertEq(r, false);
}

Expand All @@ -59,7 +67,7 @@ contract ORMPTest is Test, Verifier {
function assign(bytes32) external payable {}
function assign(bytes32, bytes calldata) external payable {}

function fee(uint256, address, uint256, bytes calldata) external pure returns (uint256) {
function fee(uint256, address, uint256, bytes calldata, bytes calldata) external pure returns (uint256) {
return 1;
}

Expand Down
Loading

0 comments on commit 3ac93d3

Please sign in to comment.