Skip to content

Commit

Permalink
progress on tribunal integration
Browse files Browse the repository at this point in the history
  • Loading branch information
0age committed Dec 20, 2024
1 parent 151db07 commit bed0240
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 100 deletions.
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ solady/=lib/the-compact/lib/solady/src/
soledge/=lib/the-compact/lib/soledge/src/
solmate/=lib/the-compact/lib/permit2/lib/solmate/
the-compact/=lib/the-compact/
tribunal/=lib/tribunal/src/
tstorish/=lib/the-compact/lib/tstorish/src/
hyperlane/=node_modules/@hyperlane-xyz/core
@openzeppelin/contracts/=node_modules/@openzeppelin/contracts
Expand Down
151 changes: 51 additions & 100 deletions src/HyperlaneTribunal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.27;
import {TheCompact} from "the-compact/src/TheCompact.sol";
import {ClaimWithWitness} from "the-compact/src/types/Claims.sol";
import {Compact} from "the-compact/src/types/EIP712Types.sol";
import {Tribunal} from "tribunal/Tribunal.sol";

import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol";
Expand All @@ -25,25 +26,25 @@ string constant WITNESS_TYPESTRING =

library Message {
function encode(
Compact calldata compact,
bytes calldata allocatorSignature,
bytes calldata sponsorSignature,
bytes32 witness,
uint256 fee,
address filler
Tribunal.Compact calldata compact,
bytes32 mandateHash,
uint256 claimedAmount,
address claimant
) internal pure returns (bytes memory) {
require(compact.allocatorSignature.length == 64 && compact.sponsorSignature.length == 64, "invalid signature length");

return abi.encodePacked(
compact.arbiter,
compact.sponsor,
compact.nonce,
compact.expires,
compact.id,
compact.amount,
allocatorSignature,
sponsorSignature,
witness,
fee,
filler
compact.maximumAmount,
compact.allocatorSignature,
compact.sponsorSignature,
mandateHash,
claimedAmount,
claimant
);
}

Expand All @@ -56,8 +57,8 @@ library Message {
bytes calldata allocatorSignature,
bytes calldata sponsorSignature,
bytes32 witness,
uint256 fee,
address filler
uint256 claimedAmount,
address claimant
)
{
assert(message.length == 380);
Expand All @@ -72,14 +73,13 @@ library Message {
allocatorSignature = message[168:232];
sponsorSignature = message[232:296];
witness = bytes32(message[296:328]);
fee = uint256(bytes32(message[328:360]));
filler = address(bytes20(message[360:380]));
claimedAmount = uint256(bytes32(message[328:360]));
claimant = address(bytes20(message[360:380]));
}
}

contract HyperlaneArbiter is Router {
contract HyperlaneTribunal is Router, Tribunal {
using Message for bytes;
using SafeTransferLib for address;

TheCompact public immutable theCompact;

Expand All @@ -88,99 +88,50 @@ contract HyperlaneArbiter is Router {
}

/**
* @notice Fills a compact intent and dispatches the claim to the arbiter.
* @dev msg.value is used to cover all hyperlane fees (relay, etc).
* @param claimChain The chain ID of the claim.
* @param compact The compact intent to fill.
* @dev signatures must be compliant with https://eips.ethereum.org/EIPS/eip-2098
* @param allocatorSignature The allocator's signature.
* @param sponsorSignature The sponsor's signature.
* @dev Process the directive for token claims
* @param compact The claim parameters
* @param mandateHash The derived mandate hash
* @param directive The execution details
* @param claimAmount The amount to claim
*/
function fill(
uint32 claimChain,
Compact calldata compact,
Intent calldata intent,
bytes calldata allocatorSignature,
bytes calldata sponsorSignature
) external payable {
require(block.chainid == intent.chainId, "invalid chain");

require(allocatorSignature.length == 64 && sponsorSignature.length == 64, "invalid signature length");

// TODO: support Permit2 fills
address filler = msg.sender;
uint256 hyperlaneFee = msg.value;
if (intent.token == address(0)) {
Address.sendValue(payable(intent.recipient), intent.amount);
hyperlaneFee -= intent.amount;
} else {
intent.token.safeTransferFrom(filler, intent.recipient, intent.amount);
}

function _processDirective(
Tribunal.Compact memory compact,
bytes32 mandateHash,
Directive memory directive,
uint256 claimAmount
) internal virtual override {
_Router_dispatch(
claimChain,
hyperlaneFee,
Message.encode(compact, allocatorSignature, sponsorSignature, hash(intent), intent.fee, filler),
compact.chainId,
directive.dispensation,
Message.encode(compact, mandateHash, claimAmount, directive.claimant),
"",
address(hook)
);
}

/**
* @notice Quotes a compact intent and returns the msg.value that should be provided
* cover all hyperlane fees (relay, etc).
* @param claimChain The chain ID of the claim.
* @param compact The compact intent to fill.
* @dev signatures must be compliant with https://eips.ethereum.org/EIPS/eip-2098
* @param allocatorSignature The allocator's signature.
* @param sponsorSignature The sponsor's signature.
* @return The quoted fee.
* @dev Derive the quote for the dispensation required for
* the directive for token claims
* @param compact The claim parameters
* @param mandateHash The derived mandate hash
* @param claimant The address of the claimant
* @param claimAmount The amount to claim
* @return dispensation The quoted dispensation amount
*/
function quote(
uint32 claimChain,
Compact calldata compact,
Intent calldata intent,
bytes calldata allocatorSignature,
bytes calldata sponsorSignature
) external view returns (uint256) {
require(block.chainid == intent.chainId, "invalid chain");

// TODO: support Permit2 fills
address filler = msg.sender;

function _quoteDirective(
Tribunal.Compact memory compact,
bytes32 mandateHash,
address claimant,
uint256 claimAmount
) internal view virtual override returns (uint256 dispensation) {
return _Router_quoteDispatch(
claimChain,
Message.encode(compact, allocatorSignature, sponsorSignature, hash(intent), intent.fee, filler),
compact.chainId,
Message.encode(compact, mandateHash, claimAmount, claimant),
"",
address(hook)
);
}

function hash(Intent memory intent) public pure returns (bytes32) {
return
keccak256(abi.encode(TYPEHASH, intent.fee, intent.chainId, intent.token, intent.recipient, intent.amount));
}

function getCompactWitnessDetails()
external
pure
returns (
string memory typestring,
string[] memory compactTokenArguments,
string[3][] memory customTokenArguments
)
{
typestring = WITNESS_TYPESTRING;

// Arguments that refer to some amount of the token in the resource lock
compactTokenArguments = new string[](1);
compactTokenArguments[0] = "fee";

// Arguments that refer to some amount of an arbitrary chain + token combination
customTokenArguments = new string[3][](1);
customTokenArguments[0] = ["intent.chainId", "intent.token", "intent.amount"];
}

function _handle(
uint32,
/*origin*/
Expand All @@ -193,8 +144,8 @@ contract HyperlaneArbiter is Router {
bytes memory allocatorSignature,
bytes memory sponsorSignature,
bytes32 witness,
uint256 fee,
address filler
uint256 claimedAmount,
address claimant
) = message.decode();

ClaimWithWitness memory claimPayload = ClaimWithWitness({
Expand All @@ -207,8 +158,8 @@ contract HyperlaneArbiter is Router {
expires: compact.expires,
id: compact.id,
allocatedAmount: compact.amount,
amount: fee,
claimant: filler
amount: claimedAmount,
claimant: claimant
});

theCompact.claim(claimPayload);
Expand Down

0 comments on commit bed0240

Please sign in to comment.