编译器
0.8.17+commit.8df45f5f
文件 1 的 14:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 14:BridgeLib.sol
pragma solidity ^0.8.17;
library BridgeLib {
struct TokenInfo {
uint token;
address mainnetToken;
uint8 decimals;
}
struct ChainInfo {
uint64 id;
uint192 batchLimit;
uint64 minVerifyChallengeSourceTxSecond;
uint64 maxVerifyChallengeSourceTxSecond;
uint64 minVerifyChallengeDestTxSecond;
uint64 maxVerifyChallengeDestTxSecond;
uint nativeToken;
address[] spvs;
}
}
文件 3 的 14:ConstantsLib.sol
pragma solidity ^0.8.17;
library ConstantsLib {
uint constant RATIO_MULTIPLE = 1000000;
uint constant MIN_ENABLE_DELAY = 120;
uint constant DEALER_WITHDRAW_DELAY = 3600;
uint constant WITHDRAW_DURATION = 3360;
uint constant LOCK_DURATION = 240;
uint constant EBC_AMOUNT_PARAMS_MODULUS = 10000;
}
文件 4 的 14:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 5 的 14:HelperLib.sol
pragma solidity ^0.8.17;
library HelperLib {
function hash(bytes memory data) internal pure returns (bytes32) {
return keccak256(data);
}
function includes(uint[] memory arr, uint element) internal pure returns (bool) {
for (uint i = 0; i < arr.length; ) {
if (element == arr[i]) {
return true;
}
unchecked {
i++;
}
}
return false;
}
function arrayIncludes(uint[] memory arr, uint[] memory elements) internal pure returns (bool) {
for (uint i = 0; i < elements.length; i++) {
bool ic = false;
for (uint j = 0; j < arr.length; ) {
if (elements[i] == arr[j]) {
ic = true;
break;
}
unchecked {
j++;
}
}
if (!ic) return false;
unchecked {
i++;
}
}
return true;
}
function includes(address[] memory arr, address element) internal pure returns (bool) {
for (uint i = 0; i < arr.length; ) {
if (element == arr[i]) {
return true;
}
unchecked {
i++;
}
}
return false;
}
function arrayIncludes(address[] memory arr, address[] memory elements) internal pure returns (bool) {
for (uint i = 0; i < elements.length; i++) {
bool ic = false;
for (uint j = 0; j < arr.length; ) {
if (elements[i] == arr[j]) {
ic = true;
break;
}
unchecked {
j++;
}
}
if (!ic) return false;
unchecked {
i++;
}
}
return true;
}
}
文件 6 的 14:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 7 的 14:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 8 的 14:IORFeeManager.sol
pragma solidity ^0.8.17;
interface IORFeeManager {
struct DealerInfo {
uint feeRatio;
bytes32 extraInfoHash;
}
struct Submission {
uint64 startBlock;
uint64 endBlock;
uint64 submitTimestamp;
bytes32 profitRoot;
bytes32 stateTransTreeRoot;
}
enum ChallengeStatus {
none,
challengeDuration,
challengeAccepted,
challengeSuccess,
challengeFail
}
enum FeeMangerDuration {
lock,
challenge,
withdraw
}
event DealerUpdated(address indexed dealer, uint feeRatio, bytes extraInfo);
event SubmitterRegistered(address indexed submitter, uint marginAmount);
event SubmissionUpdated(
uint64 startBlock,
uint64 endBlock,
uint64 indexed submitTimestamp,
bytes32 indexed profitRoot,
bytes32 indexed stateTransTreeRoot
);
event Withdraw(address indexed user, uint64 chainId, address token, uint debt, uint amount);
event ETHDeposit(address indexed sender, uint amount);
function registerSubmitter(uint marginAmount, address submitter) external;
function submit(uint64 startBlock, uint64 endBlock, bytes32 profitRoot, bytes32 stateTransTreeRoot) external;
function startChallenge(uint marginAmount, address challenger) external;
function responsePositioning(bytes calldata response) external;
function getCurrentBlockInfo() external view returns (Submission memory);
}
文件 9 的 14:IORManager.sol
pragma solidity ^0.8.17;
import {BridgeLib} from "../library/BridgeLib.sol";
interface IORManager {
event ChainInfoUpdated(uint64 indexed id, BridgeLib.ChainInfo chainInfo);
event ChainTokenUpdated(uint64 indexed id, BridgeLib.TokenInfo tokenInfo);
event EbcsUpdated(address[] ebcs, bool[] statuses);
event SubmitterFeeUpdated(address submitter);
event ProtocolFeeUpdated(uint64 protocolFee);
event MinChallengeRatioUpdated(uint64 minChallengeRatio);
event ChallengeUserRatioUpdated(uint64 challengeUserRatio);
event FeeChallengeSecondUpdated(uint64 feeChallengeSecond);
event FeeTakeOnChallengeSecondUpdated(uint64 feeTakeOnChallengeSecond);
event MaxMDCLimitUpdated(uint64 maxMDCLimit);
event ExtraTransferContractsUpdated(uint64[] chainIds, uint[] extraTransferContracts);
function registerChains(uint64 enableTime, BridgeLib.ChainInfo[] calldata chains_) external;
function updateChainSpvs(uint64 enableTime, uint64 id, address[] calldata spvs, uint[] calldata indexs) external;
function getChainInfo(uint64 id) external view returns (BridgeLib.ChainInfo memory);
function updateChainTokens(
uint64 enableTime,
uint64[] memory ids,
BridgeLib.TokenInfo[] calldata tokenInfos
) external;
function getChainTokenInfo(uint64 id, uint token) external view returns (BridgeLib.TokenInfo memory);
function ebcIncludes(address ebc) external view returns (bool);
function updateEbcs(address[] calldata ebcs_, bool[] calldata statuses) external;
function submitter() external view returns (address);
function updateSubmitter(uint64 enableTime, address submitter_) external;
function protocolFee() external view returns (uint64);
function updateProtocolFee(uint64 enableTime, uint64 protocolFee_) external;
function minChallengeRatio() external view returns (uint64);
function updateMinChallengeRatio(uint64 enableTime, uint64 minChallengeRatio_) external;
function challengeUserRatio() external view returns (uint64);
function updateChallengeUserRatio(uint64 enableTime, uint64 challengeUserRatio_) external;
function feeChallengeSecond() external view returns (uint64);
function updateFeeChallengeSecond(uint64 enableTime, uint64 feeChallengeSecond_) external;
function feeTakeOnChallengeSecond() external view returns (uint64);
function updateFeeTakeOnChallengeSecond(uint64 enableTime, uint64 feeTakeOnChallengeSecond_) external;
function maxMDCLimit() external view returns (uint64);
function updateMaxMDCLimit(uint64 maxMDCLimit_) external;
function getExtraTransferContract(uint64 chainId) external view returns (uint);
function updateExtraTransferContracts(
uint64 enableTime,
uint64[] calldata chainIds,
uint[] calldata extraTransferContracts
) external;
}
文件 10 的 14:MerkleTreeLib.sol
pragma solidity ^0.8.17;
library MerkleTreeLib {
enum MergeValueType {
VALUE,
MERGE_WITH_ZERO,
SHORT_CUT
}
struct SMTLeaf {
uint64 chainId;
address token;
address user;
uint256 amount;
uint256 debt;
}
uint8 internal constant MERGE_NORMAL = 1;
uint8 internal constant MERGE_ZEROS = 2;
uint8 internal constant MAX_TREE_LEVEL = 255;
function isRight(bytes32 _hash, uint height) internal pure returns (bool) {
return getBit(_hash, height);
}
function setBit(bytes32 bitmap, uint index) internal pure returns (bytes32) {
return bytes32(uint256(bitmap) | (1 << (index & 0xff)));
}
function getBit(uint256 bitmap, uint index) internal pure returns (bool) {
bool result;
assembly {
let shifted := shl(index, 1)
let temp := and(bitmap, shifted)
result := iszero(iszero(temp))
}
return result;
}
function getBit(bytes32 bitmap, uint index) internal pure returns (bool) {
bool result;
assembly {
let shifted := shl(index, 1)
let temp := and(bitmap, shifted)
result := iszero(iszero(temp))
}
return result;
}
function clearBit(bytes32 bitmap, uint index) internal pure returns (bytes32) {
return bytes32(uint256(bitmap) & (~(1 << index)));
}
function copyBits(bytes32 bitmap, uint index) internal pure returns (bytes32) {
return bytes32((uint256(bitmap) << index) >> index);
}
function parentPath(bytes32 path, uint height) internal pure returns (bytes32) {
if (height == 255) {
return bytes32(0);
}
unchecked {
return copyBits(path, (height + 1));
}
}
function isZero(bytes32 value) internal pure returns (bool) {
bool result;
assembly {
result := eq(value, 0)
}
return result;
}
function isZero(uint256 value) internal pure returns (bool) {
bool result;
assembly {
result := eq(value, 0)
}
return result;
}
using MerkleTreeLib for uint256;
using MerkleTreeLib for bytes32;
error InvalidMergeValue();
function verify(
bytes32 key,
bytes32 v,
uint256 leaves_bitmap,
bytes32 root,
bytes32 firstZeroBits,
uint8 startIndex,
bytes32[] calldata siblings
) internal pure returns (bool) {
bytes32 parent_path;
uint iReverse;
uint8 n;
bool _isRight;
MergeValueType mergeType;
uint8 currentZeroCount;
bytes32 currentBaseNode;
bytes32 currentZeroBits;
if (leaves_bitmap.isZero()) {
return
keccak256(
abi.encode(
MERGE_ZEROS,
keccak256(abi.encode(0, key.parentPath(0), v)),
key.getBit(0) ? key.clearBit(0) : key,
0
)
) == root;
}
if (!(v.isZero() || startIndex == 0)) {
mergeType = MergeValueType.MERGE_WITH_ZERO;
currentZeroCount = startIndex;
currentBaseNode = keccak256(abi.encode(0, key.parentPath(0), v));
currentZeroBits = firstZeroBits;
}
for (uint i = startIndex; ; ) {
unchecked {
iReverse = MAX_TREE_LEVEL - i;
}
parent_path = key.parentPath(i);
_isRight = key.isRight(iReverse);
if (leaves_bitmap.getBit(iReverse)) {
if (mergeType == MergeValueType.MERGE_WITH_ZERO) {
currentBaseNode = keccak256(
abi.encode(MERGE_ZEROS, currentBaseNode, currentZeroBits, currentZeroCount)
);
}
currentBaseNode = keccak256(
abi.encode(
MERGE_NORMAL,
i,
parent_path,
_isRight ? siblings[n] : currentBaseNode,
_isRight ? currentBaseNode : siblings[n]
)
);
mergeType = MergeValueType.VALUE;
unchecked {
n += 1;
}
} else {
if (n > 0) {
if (mergeType == MergeValueType.VALUE) {
currentZeroCount = 1;
currentZeroBits = _isRight ? bytes32(0).setBit(MAX_TREE_LEVEL - i) : bytes32(0);
currentBaseNode = keccak256(abi.encode(i, parent_path, currentBaseNode));
} else if (mergeType == MergeValueType.MERGE_WITH_ZERO) {
unchecked {
currentZeroCount = currentZeroCount + 1;
}
currentZeroBits = _isRight ? currentZeroBits.setBit(MAX_TREE_LEVEL - i) : currentZeroBits;
} else {
revert InvalidMergeValue();
}
mergeType = MergeValueType.MERGE_WITH_ZERO;
}
}
key = parent_path;
if (i == MAX_TREE_LEVEL) {
break;
}
unchecked {
i += 1;
}
}
if (mergeType == MergeValueType.VALUE) {
return currentBaseNode == root;
} else if (mergeType == MergeValueType.MERGE_WITH_ZERO) {
return
keccak256(
abi.encode(
MERGE_ZEROS,
currentBaseNode,
currentZeroBits,
currentZeroCount
)
) == root;
}
return false;
}
}
文件 11 的 14:ORFeeManager.sol
pragma solidity ^0.8.17;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IORFeeManager} from "./interface/IORFeeManager.sol";
import {IORManager} from "./interface/IORManager.sol";
import {HelperLib} from "./library/HelperLib.sol";
import {ConstantsLib} from "./library/ConstantsLib.sol";
import {MerkleTreeLib} from "./library/MerkleTreeLib.sol";
contract ORFeeManager is IORFeeManager, Ownable, ReentrancyGuard {
using HelperLib for bytes;
using SafeERC20 for IERC20;
using MerkleTreeLib for bytes32;
IORManager private immutable _manager;
ChallengeStatus public challengeStatus;
Submission public submissions;
mapping(address => DealerInfo) private _dealers;
mapping(address => uint) public submitter;
mapping(address => uint64) public withdrawLock;
modifier isChallengerQualified() {
require(address(msg.sender).balance >= address(IORManager(_manager).submitter()).balance, "NF");
_;
}
function durationCheck() public view returns (FeeMangerDuration duration) {
uint challengeEnd = submissions.submitTimestamp + ConstantsLib.DEALER_WITHDRAW_DELAY;
if (block.timestamp <= challengeEnd) {
return FeeMangerDuration.challenge;
}
uint mod = (block.timestamp - challengeEnd) % (ConstantsLib.WITHDRAW_DURATION + ConstantsLib.LOCK_DURATION);
if (mod <= ConstantsLib.WITHDRAW_DURATION) {
return FeeMangerDuration.withdraw;
} else {
return FeeMangerDuration.lock;
}
}
function withdrawLockCheck(address withdrawUser) external view returns (bool) {
return withdrawLock[withdrawUser] < submissions.submitTimestamp ? false : true;
}
receive() external payable {
emit ETHDeposit(msg.sender, msg.value);
}
constructor(address owner_, address manager_) {
require(owner_ != address(0), "OZ");
require(manager_ != address(0), "MZ");
_transferOwnership(owner_);
_manager = IORManager(manager_);
}
function withdrawVerification(
MerkleTreeLib.SMTLeaf[] calldata smtLeaves,
bytes32[][] calldata siblings,
uint8[] calldata startIndex,
bytes32[] calldata firstZeroBits,
uint256[] calldata bitmaps,
uint256[] calldata withdrawAmount
) external nonReentrant {
require(durationCheck() == FeeMangerDuration.withdraw, "WE");
require(challengeStatus == ChallengeStatus.none, "WDC");
require(withdrawLock[msg.sender] < submissions.submitTimestamp, "WL");
withdrawLock[msg.sender] = submissions.submitTimestamp;
for (uint i = 0; i < smtLeaves.length; ) {
address token = smtLeaves[i].token;
address user = smtLeaves[i].user;
uint64 chainId = smtLeaves[i].chainId;
uint256 debt = smtLeaves[i].debt;
uint256 amount = smtLeaves[i].amount;
require(msg.sender == user, "NU");
require(withdrawAmount[i] <= amount, "UIF");
require(
keccak256(abi.encode(chainId, token, user)).verify(
keccak256(abi.encode(token, chainId, amount, debt)),
bitmaps[i],
submissions.profitRoot,
firstZeroBits[i],
startIndex[i],
siblings[i]
),
"merkle root verify failed"
);
if (token != address(0)) {
IERC20(token).safeTransfer(msg.sender, withdrawAmount[i]);
} else {
(bool success, ) = payable(msg.sender).call{value: withdrawAmount[i]}("");
require(success, "ETH: IF");
}
emit Withdraw(msg.sender, chainId, token, debt, withdrawAmount[i]);
unchecked {
i += 1;
}
}
}
function submit(
uint64 startBlock,
uint64 endBlock,
bytes32 profitRoot,
bytes32 stateTransTreeRoot
) external override nonReentrant {
require(submitter[msg.sender] != 0, "NS");
require(challengeStatus == ChallengeStatus.none, "SDC");
require(durationCheck() == FeeMangerDuration.lock, "NL2");
require(endBlock > startBlock, "EB");
require(startBlock == submissions.endBlock, "BE");
submissions = Submission(startBlock, endBlock, uint64(block.timestamp), profitRoot, stateTransTreeRoot);
emit SubmissionUpdated(startBlock, endBlock, uint64(block.timestamp), profitRoot, stateTransTreeRoot);
}
function updateDealer(uint feeRatio, bytes calldata extraInfo) external {
bytes32 extraInfoHash = extraInfo.hash();
_dealers[msg.sender] = DealerInfo(feeRatio, extraInfoHash);
emit DealerUpdated(msg.sender, feeRatio, extraInfo);
}
function getDealerInfo(address dealer) external view returns (DealerInfo memory) {
return _dealers[dealer];
}
function transferOwnership(address newOwner) public override onlyOwner {
require(newOwner != address(0), "OZ");
_transferOwnership(newOwner);
}
function registerSubmitter(uint marginAmount, address _submitter) external override onlyOwner {
require(_submitter == IORManager(_manager).submitter(), "NSR");
submitter[_submitter] = marginAmount;
emit SubmitterRegistered(_submitter, marginAmount);
}
function getCurrentBlockInfo() external view override returns (Submission memory) {}
function startChallenge(uint marginAmount, address _submitter) public override isChallengerQualified nonReentrant {
challengeStatus = ChallengeStatus.challengeAccepted;
(marginAmount, _submitter);
}
function responsePositioning(bytes calldata response) public override {
(response);
endChallenge();
}
function endChallenge() internal nonReentrant {
challengeStatus = ChallengeStatus.none;
}
}
文件 12 的 14:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 13 的 14:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
文件 14 的 14:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
{
"compilationTarget": {
"contracts/ORFeeManager.sol": "ORFeeManager"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 10
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"manager_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidMergeValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dealer","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeRatio","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraInfo","type":"bytes"}],"name":"DealerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"startBlock","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"endBlock","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"submitTimestamp","type":"uint64"},{"indexed":true,"internalType":"bytes32","name":"profitRoot","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"stateTransTreeRoot","type":"bytes32"}],"name":"SubmissionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"submitter","type":"address"},{"indexed":false,"internalType":"uint256","name":"marginAmount","type":"uint256"}],"name":"SubmitterRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"debt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"challengeStatus","outputs":[{"internalType":"enum IORFeeManager.ChallengeStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"durationCheck","outputs":[{"internalType":"enum IORFeeManager.FeeMangerDuration","name":"duration","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentBlockInfo","outputs":[{"components":[{"internalType":"uint64","name":"startBlock","type":"uint64"},{"internalType":"uint64","name":"endBlock","type":"uint64"},{"internalType":"uint64","name":"submitTimestamp","type":"uint64"},{"internalType":"bytes32","name":"profitRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateTransTreeRoot","type":"bytes32"}],"internalType":"struct IORFeeManager.Submission","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dealer","type":"address"}],"name":"getDealerInfo","outputs":[{"components":[{"internalType":"uint256","name":"feeRatio","type":"uint256"},{"internalType":"bytes32","name":"extraInfoHash","type":"bytes32"}],"internalType":"struct IORFeeManager.DealerInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marginAmount","type":"uint256"},{"internalType":"address","name":"_submitter","type":"address"}],"name":"registerSubmitter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"name":"responsePositioning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"marginAmount","type":"uint256"},{"internalType":"address","name":"_submitter","type":"address"}],"name":"startChallenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"submissions","outputs":[{"internalType":"uint64","name":"startBlock","type":"uint64"},{"internalType":"uint64","name":"endBlock","type":"uint64"},{"internalType":"uint64","name":"submitTimestamp","type":"uint64"},{"internalType":"bytes32","name":"profitRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateTransTreeRoot","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"startBlock","type":"uint64"},{"internalType":"uint64","name":"endBlock","type":"uint64"},{"internalType":"bytes32","name":"profitRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateTransTreeRoot","type":"bytes32"}],"name":"submit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"submitter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"feeRatio","type":"uint256"},{"internalType":"bytes","name":"extraInfo","type":"bytes"}],"name":"updateDealer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawLock","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"withdrawUser","type":"address"}],"name":"withdrawLockCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"debt","type":"uint256"}],"internalType":"struct MerkleTreeLib.SMTLeaf[]","name":"smtLeaves","type":"tuple[]"},{"internalType":"bytes32[][]","name":"siblings","type":"bytes32[][]"},{"internalType":"uint8[]","name":"startIndex","type":"uint8[]"},{"internalType":"bytes32[]","name":"firstZeroBits","type":"bytes32[]"},{"internalType":"uint256[]","name":"bitmaps","type":"uint256[]"},{"internalType":"uint256[]","name":"withdrawAmount","type":"uint256[]"}],"name":"withdrawVerification","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]