编译器
0.8.17+commit.8df45f5f
文件 1 的 9:Channel.sol
pragma solidity 0.8.17;
import "./UserConfig.sol";
import "./interfaces/IVerifier.sol";
contract Channel is UserConfig {
mapping(bytes32 => bool) public dones;
uint256 public count;
address private immutable __self = address(this);
event MessageAccepted(bytes32 indexed msgHash, Message message);
event MessageDispatched(bytes32 indexed msgHash, bool dispatchResult);
constructor(address dao) UserConfig(dao) {}
function LOCAL_CHAINID() public view returns (uint256) {
return block.chainid;
}
function _send(address from, uint256 toChainId, address to, uint256 gasLimit, bytes calldata encoded)
internal
returns (bytes32)
{
require(toChainId != LOCAL_CHAINID(), "!cross-chain");
Message memory message = Message({
channel: __self,
index: count,
fromChainId: LOCAL_CHAINID(),
from: from,
toChainId: toChainId,
to: to,
gasLimit: gasLimit,
encoded: encoded
});
bytes32 msgHash = hash(message);
emit MessageAccepted(msgHash, message);
count = count + 1;
return msgHash;
}
function _recv(Message calldata message, bytes calldata proof) internal returns (bytes32) {
UC memory uc = getAppConfig(message.to);
require(uc.relayer == msg.sender, "!auth");
require(IVerifier(uc.oracle).verifyMessageProof(message, proof), "!proof");
require(LOCAL_CHAINID() == message.toChainId, "!toChainId");
bytes32 msgHash = hash(message);
require(dones[msgHash] == false, "done");
dones[msgHash] = true;
return msgHash;
}
}
文件 2 的 9:Common.sol
pragma solidity 0.8.17;
struct Message {
address channel;
uint256 index;
uint256 fromChainId;
address from;
uint256 toChainId;
address to;
uint256 gasLimit;
bytes encoded;
}
function hash(Message memory message) pure returns (bytes32) {
return keccak256(abi.encode(message));
}
文件 3 的 9:ExcessivelySafeCall.sol
pragma solidity 0.8.17;
library ExcessivelySafeCall {
function excessivelySafeCall(address _target, uint256 _gas, uint256 _value, uint16 _maxCopy, bytes memory _calldata)
internal
returns (bool, bytes memory)
{
uint256 _toCopy;
bool _success;
bytes memory _returnData = new bytes(_maxCopy);
assembly ("memory-safe") {
_success :=
call(
_gas,
_target,
_value,
add(_calldata, 0x20),
mload(_calldata),
0,
0
)
_toCopy := returndatasize()
if gt(_toCopy, _maxCopy) { _toCopy := _maxCopy }
mstore(_returnData, _toCopy)
returndatacopy(add(_returnData, 0x20), 0, _toCopy)
}
return (_success, _returnData);
}
function excessivelySafeStaticCall(address _target, uint256 _gas, uint16 _maxCopy, bytes memory _calldata)
internal
view
returns (bool, bytes memory)
{
uint256 _toCopy;
bool _success;
bytes memory _returnData = new bytes(_maxCopy);
assembly ("memory-safe") {
_success :=
staticcall(
_gas,
_target,
add(_calldata, 0x20),
mload(_calldata),
0,
0
)
_toCopy := returndatasize()
if gt(_toCopy, _maxCopy) { _toCopy := _maxCopy }
mstore(_returnData, _toCopy)
returndatacopy(add(_returnData, 0x20), 0, _toCopy)
}
return (_success, _returnData);
}
}
文件 4 的 9:IOracle.sol
pragma solidity 0.8.17;
import "./IVerifier.sol";
interface IOracle is IVerifier {
function fee(uint256 toChainId, address ua) external view returns (uint256);
}
文件 5 的 9:IRelayer.sol
pragma solidity 0.8.17;
interface IRelayer {
function fee(uint256 toChainId, address ua, uint256 gasLimit, bytes calldata encoded, bytes calldata params)
external
view
returns (uint256);
}
文件 6 的 9:IVerifier.sol
pragma solidity 0.8.17;
import "../Common.sol";
interface IVerifier {
function verifyMessageProof(Message calldata message, bytes calldata proof) external view returns (bool);
}
文件 7 的 9:ORMP.sol
pragma solidity 0.8.17;
import "./Channel.sol";
import "./interfaces/IOracle.sol";
import "./interfaces/IRelayer.sol";
import "./security/ReentrancyGuard.sol";
import "./security/ExcessivelySafeCall.sol";
contract ORMP is ReentrancyGuard, Channel {
using ExcessivelySafeCall for address;
event MessageAssigned(
bytes32 indexed msgHash,
address indexed oracle,
address indexed relayer,
uint256 oracleFee,
uint256 relayerFee,
bytes params
);
event HashImported(address indexed oracle, uint256 chainId, address channel, uint256 msgIndex, bytes32 hash);
mapping(address => mapping(bytes32 => bytes32)) public hashLookup;
constructor(address dao) Channel(dao) {}
function version() public pure returns (string memory) {
return "2.1.0";
}
function send(
uint256 toChainId,
address to,
uint256 gasLimit,
bytes calldata encoded,
address refund,
bytes calldata params
) external payable sendNonReentrant returns (bytes32) {
address ua = msg.sender;
bytes32 msgHash = _send(ua, toChainId, to, gasLimit, encoded);
_handleFee(ua, refund, msgHash, toChainId, gasLimit, encoded, params);
return msgHash;
}
function importHash(uint256 chainId, address channel, uint256 msgIndex, bytes32 hash_) external {
bytes32 lookupKey = keccak256(abi.encode(chainId, channel, msgIndex));
hashLookup[msg.sender][lookupKey] = hash_;
emit HashImported(msg.sender, chainId, channel, msgIndex, hash_);
}
function _handleFee(
address ua,
address refund,
bytes32 msgHash,
uint256 toChainId,
uint256 gasLimit,
bytes calldata encoded,
bytes calldata params
) internal {
UC memory uc = getAppConfig(ua);
uint256 relayerFee = _handleRelayer(uc.relayer, toChainId, ua, gasLimit, encoded, params);
uint256 oracleFee = _handleOracle(uc.oracle, toChainId, ua);
emit MessageAssigned(msgHash, uc.oracle, uc.relayer, oracleFee, relayerFee, params);
require(msg.value >= relayerFee + oracleFee, "!fee");
if (msg.value > relayerFee + oracleFee) {
uint256 refundFee = msg.value - (relayerFee + oracleFee);
_sendValue(refund, refundFee);
}
}
function fee(uint256 toChainId, address ua, uint256 gasLimit, bytes calldata encoded, bytes calldata params)
external
view
returns (uint256)
{
UC memory uc = getAppConfig(ua);
uint256 relayerFee = IRelayer(uc.relayer).fee(toChainId, ua, gasLimit, encoded, params);
uint256 oracleFee = IOracle(uc.oracle).fee(toChainId, ua);
return relayerFee + oracleFee;
}
function _handleRelayer(
address relayer,
uint256 toChainId,
address ua,
uint256 gasLimit,
bytes calldata encoded,
bytes calldata params
) internal returns (uint256) {
uint256 relayerFee = IRelayer(relayer).fee(toChainId, ua, gasLimit, encoded, params);
_sendValue(relayer, relayerFee);
return relayerFee;
}
function _handleOracle(address oracle, uint256 toChainId, address ua) internal returns (uint256) {
uint256 oracleFee = IOracle(oracle).fee(toChainId, ua);
_sendValue(oracle, oracleFee);
return oracleFee;
}
function recv(Message calldata message, bytes calldata proof)
external
recvNonReentrant
returns (bool dispatchResult)
{
bytes32 msgHash = _recv(message, proof);
dispatchResult = _dispatch(message, msgHash);
emit MessageDispatched(msgHash, dispatchResult);
}
function _dispatch(Message memory message, bytes32 msgHash) private returns (bool dispatchResult) {
uint256 gasAvailable = gasleft() - 5000;
require(gasAvailable - gasAvailable / 64 > message.gasLimit, "!gas");
(dispatchResult,) = message.to.excessivelySafeCall(
message.gasLimit, 0, 0, abi.encodePacked(message.encoded, msgHash, message.fromChainId, message.from)
);
}
function _sendValue(address recipient, uint256 amount) internal {
(bool success,) = recipient.call{value: amount}("");
require(success, "!send");
}
}
文件 8 的 9:ReentrancyGuard.sol
pragma solidity 0.8.17;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _send_state = 1;
uint256 private _receive_state = 1;
modifier sendNonReentrant() {
require(_send_state == _NOT_ENTERED, "!send-reentrancy");
_send_state = _ENTERED;
_;
_send_state = _NOT_ENTERED;
}
modifier recvNonReentrant() {
require(_receive_state == _NOT_ENTERED, "!recv-reentrancy");
_receive_state = _ENTERED;
_;
_receive_state = _NOT_ENTERED;
}
}
文件 9 的 9:UserConfig.sol
pragma solidity 0.8.17;
struct UC {
address oracle;
address relayer;
}
contract UserConfig {
address public setter;
UC public defaultUC;
mapping(address => UC) public ucOf;
event DefaultConfigUpdated(address oracle, address relayer);
event AppConfigUpdated(address indexed ua, address oracle, address relayer);
event SetterChanged(address indexed oldSetter, address indexed newSetter);
modifier onlySetter() {
require(msg.sender == setter, "!auth");
_;
}
constructor(address dao) {
setter = dao;
}
function changeSetter(address newSetter) external onlySetter {
address oldSetter = setter;
setter = newSetter;
emit SetterChanged(oldSetter, newSetter);
}
function setDefaultConfig(address oracle, address relayer) external onlySetter {
defaultUC = UC(oracle, relayer);
emit DefaultConfigUpdated(oracle, relayer);
}
function setAppConfig(address oracle, address relayer) external {
ucOf[msg.sender] = UC(oracle, relayer);
emit AppConfigUpdated(msg.sender, oracle, relayer);
}
function getAppConfig(address ua) public view returns (UC memory) {
UC memory c = ucOf[ua];
if (c.relayer == address(0x0)) {
c.relayer = defaultUC.relayer;
}
if (c.oracle == address(0x0)) {
c.oracle = defaultUC.oracle;
}
return c;
}
}
{
"compilationTarget": {
"lib/ORMP/src/ORMP.sol": "ORMP"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 999999
},
"remappings": [
":@darwinia-msgport/=lib/darwinia-msgport/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":@openzeppelin/contracts@4.9.2/=lib/openzeppelin-contracts/contracts/",
":@safe-smart-account/=lib/subapi/lib/safe-smart-account/contracts/",
":@sphinx-labs/contracts/=lib/sphinx/packages/contracts/contracts/foundry/",
":ORMP/=lib/ORMP/",
":create3-deploy/=lib/create3-deploy/",
":forge-std/=lib/forge-std/src/",
":solmate/=lib/darwinia-msgport/lib/solmate/src/",
":subapi/=lib/subapi/"
]
}
[{"inputs":[{"internalType":"address","name":"dao","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"ua","type":"address"},{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"AppConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"DefaultConfigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"channel","type":"address"},{"indexed":false,"internalType":"uint256","name":"msgIndex","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"HashImported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"},{"components":[{"internalType":"address","name":"channel","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"fromChainId","type":"uint256"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"encoded","type":"bytes"}],"indexed":false,"internalType":"struct Message","name":"message","type":"tuple"}],"name":"MessageAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"oracle","type":"address"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"uint256","name":"oracleFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"relayerFee","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"params","type":"bytes"}],"name":"MessageAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"dispatchResult","type":"bool"}],"name":"MessageDispatched","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSetter","type":"address"},{"indexed":true,"internalType":"address","name":"newSetter","type":"address"}],"name":"SetterChanged","type":"event"},{"inputs":[],"name":"LOCAL_CHAINID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newSetter","type":"address"}],"name":"changeSetter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultUC","outputs":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"relayer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"dones","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"address","name":"ua","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"encoded","type":"bytes"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"ua","type":"address"}],"name":"getAppConfig","outputs":[{"components":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"relayer","type":"address"}],"internalType":"struct UC","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"hashLookup","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"channel","type":"address"},{"internalType":"uint256","name":"msgIndex","type":"uint256"},{"internalType":"bytes32","name":"hash_","type":"bytes32"}],"name":"importHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"channel","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"fromChainId","type":"uint256"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"encoded","type":"bytes"}],"internalType":"struct Message","name":"message","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"recv","outputs":[{"internalType":"bool","name":"dispatchResult","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"encoded","type":"bytes"},{"internalType":"address","name":"refund","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"send","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"relayer","type":"address"}],"name":"setAppConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"relayer","type":"address"}],"name":"setDefaultConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ucOf","outputs":[{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"relayer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]