编译器
0.8.25+commit.b61c2a91
文件 1 的 19:Address.sol
pragma solidity ^0.8.20;
library Address {
error AddressInsufficientBalance(address account);
error AddressEmptyCode(address target);
error FailedInnerCall();
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
文件 2 的 19:IAxelarExecutable.sol
pragma solidity 0.8.25;
import { IAxelarGateway } from './IAxelarGateway.sol';
abstract contract IAxelarExecutable {
error NotApprovedByGateway();
function _execute(
string memory sourceChain,
string memory sourceAddress,
bytes calldata payload
) internal virtual {}
function _executeWithToken(
string memory sourceChain,
string memory sourceAddress,
bytes calldata payload,
string memory tokenSymbol,
uint256 amount
) internal virtual {}
}
文件 3 的 19:IAxelarGateway.sol
pragma solidity 0.8.25;
interface IAxelarGateway {
function sendToken(
string calldata destinationChain,
string calldata destinationAddress,
string calldata symbol,
uint256 amount
) external;
function callContract(
string calldata destinationChain,
string calldata contractAddress,
bytes calldata payload
) external;
function callContractWithToken(
string calldata destinationChain,
string calldata contractAddress,
bytes calldata payload,
string calldata symbol,
uint256 amount
) external;
function validateContractCall(
bytes32 commandId,
string calldata sourceChain,
string calldata sourceAddress,
bytes32 payloadHash
) external returns (bool);
function validateContractCallAndMint(
bytes32 commandId,
string calldata sourceChain,
string calldata sourceAddress,
bytes32 payloadHash,
string calldata symbol,
uint256 amount
) external returns (bool);
function tokenAddresses(string memory symbol) external view returns (address);
}
文件 4 的 19:ICurve.sol
pragma solidity 0.8.25;
interface ICurve {
function exchange(
address [11] calldata _route,
uint256 [5][5] calldata _swap_params,
uint256 _amount,
uint256 _expected,
address [5] calldata _pools,
address _receiver
) external payable returns (uint256 amountOut);
}
文件 5 的 19:IERC20.sol
pragma solidity ^0.8.20;
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 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 6 的 19:IERC20Permit.sol
pragma solidity ^0.8.20;
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);
}
文件 7 的 19:IRango.sol
pragma solidity 0.8.25;
interface IRango {
struct RangoBridgeRequest {
address requestId;
address token;
uint amount;
uint platformFee;
uint affiliateFee;
address payable affiliatorAddress;
uint destinationExecutorFee;
uint16 dAppTag;
string dAppName;
}
enum BridgeType {
Across,
CBridge,
Hop,
Hyphen,
Multichain,
Stargate,
Synapse,
Thorchain,
Symbiosis,
Axelar,
Voyager,
Poly,
OptimismBridge,
ArbitrumBridge,
Wormhole,
AllBridge,
CCTP,
Connext,
NitroAssetForwarder,
DeBridge,
YBridge,
Swft,
Orbiter,
ChainFlip
}
enum CrossChainOperationStatus {
Succeeded,
RefundInSource,
RefundInDestination,
SwapFailedInDestination
}
event RangoBridgeInitiated(
address indexed requestId,
address bridgeToken,
uint256 bridgeAmount,
address receiver,
uint destinationChainId,
bool hasInterchainMessage,
bool hasDestinationSwap,
uint8 indexed bridgeId,
uint16 indexed dAppTag,
string dAppName
);
event RangoBridgeCompleted(
address indexed requestId,
address indexed token,
address indexed originalSender,
address receiver,
uint amount,
CrossChainOperationStatus status,
uint16 dAppTag
);
}
文件 8 的 19:IRangoMessageReceiver.sol
pragma solidity 0.8.25;
interface IRangoMessageReceiver {
enum ProcessStatus { SUCCESS, REFUND_IN_SOURCE, REFUND_IN_DESTINATION }
function handleRangoMessage(
address token,
uint amount,
ProcessStatus status,
bytes memory message
) external;
}
文件 9 的 19:IRangoMiddlewareWhitelists.sol
pragma solidity 0.8.25;
interface IRangoMiddlewareWhitelists {
function addWhitelist(address contractAddress) external;
function removeWhitelist(address contractAddress) external;
function isContractWhitelisted(address _contractAddress) external view returns (bool);
function isMessagingContractWhitelisted(address _messagingContract) external view returns (bool);
function updateWeth(address _weth) external;
function getWeth() external view returns (address);
function getRangoDiamond() external view returns (address);
function isMiddlewaresPaused(address _middleware) external view returns (bool);
}
文件 10 的 19:IUniswapV2.sol
pragma solidity 0.8.25;
interface IUniswapV2 {
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function swapExactAVAXForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
}
文件 11 的 19:IUniswapV3.sol
pragma solidity 0.8.25;
interface IUniswapV3 {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
struct ExactInputParamsRouter2 {
bytes path;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
function exactInput(ExactInputParamsRouter2 calldata params) external payable returns (uint256 amountOut);
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;
}
文件 12 的 19:IWETH.sol
pragma solidity 0.8.25;
interface IWETH {
function deposit() external payable;
function withdraw(uint256) external;
}
文件 13 的 19:Interchain.sol
pragma solidity 0.8.25;
interface Interchain {
enum ActionType { NO_ACTION, UNI_V2, UNI_V3, CALL, CURVE }
enum CallSubActionType { WRAP, UNWRAP, NO_ACTION }
struct RangoInterChainMessage {
address requestId;
uint64 dstChainId;
address bridgeRealOutput;
address toToken;
address originalSender;
address recipient;
ActionType actionType;
bytes action;
CallSubActionType postAction;
uint16 dAppTag;
bytes dAppMessage;
address dAppSourceContract;
address dAppDestContract;
}
struct UniswapV2Action {
address dexAddress;
uint amountOutMin;
address[] path;
uint deadline;
}
struct UniswapV3ActionExactInputParams {
address dexAddress;
address tokenIn;
address tokenOut;
bytes encodedPath;
uint256 deadline;
uint256 amountOutMinimum;
bool isRouter2;
}
struct CallAction {
address tokenIn;
address spender;
CallSubActionType preAction;
address payable target;
bool overwriteAmount;
uint256 startIndexForAmount;
bytes callData;
}
struct CurveAction {
address routerContractAddress;
address [11] routes;
uint256 [5][5] swap_params;
uint256 expected;
address [5] pools;
address toToken;
}
}
文件 14 的 19:LibInterchain.sol
pragma solidity 0.8.25;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IUniswapV2.sol";
import "../interfaces/IUniswapV3.sol";
import "../interfaces/ICurve.sol";
import "../interfaces/IWETH.sol";
import "../interfaces/Interchain.sol";
import "../interfaces/IRangoMessageReceiver.sol";
import "../interfaces/IRangoMiddlewareWhitelists.sol";
import "./LibSwapper.sol";
library LibInterchain {
bytes32 internal constant LIBINTERCHAIN_CONTRACT_NAMESPACE = keccak256("exchange.rango.library.interchain");
struct BaseInterchainStorage {
address whitelistsStorageContract;
}
event CrossChainMessageCalled(
address _receiverContract,
address _token,
uint _amount,
IRangoMessageReceiver.ProcessStatus _status,
bytes _appMessage,
bool success,
string failReason
);
event ActionDone(Interchain.ActionType actionType, address contractAddress, bool success, string reason);
event SubActionDone(Interchain.CallSubActionType subActionType, address contractAddress, bool success, string reason);
event WhitelistStorageAddressUpdated(address _oldAddress, address _newAddress);
function isContractWhitelisted(address _contractAddress) internal view returns(bool) {
address whitelistsContractAddress = getLibInterchainStorage().whitelistsStorageContract;
return IRangoMiddlewareWhitelists(whitelistsContractAddress).isContractWhitelisted(_contractAddress);
}
function isMessagingContractWhitelisted(address _messagingContract) internal view returns(bool) {
address s = getLibInterchainStorage().whitelistsStorageContract;
return IRangoMiddlewareWhitelists(s).isMessagingContractWhitelisted(_messagingContract);
}
function updateWhitelistsContractAddress(address _storageContract) internal {
require(_storageContract != address(0), "Invalid storage contract address");
BaseInterchainStorage storage baseStorage = getLibInterchainStorage();
address oldAddress = baseStorage.whitelistsStorageContract;
baseStorage.whitelistsStorageContract = _storageContract;
emit WhitelistStorageAddressUpdated(oldAddress, _storageContract);
}
function handleDestinationMessage(
address _token,
uint _amount,
Interchain.RangoInterChainMessage memory m
) internal returns (address, uint256 dstAmount, IRango.CrossChainOperationStatus status) {
address sourceToken = m.bridgeRealOutput == LibSwapper.ETH && _token == getWeth() ? LibSwapper.ETH : _token;
bool ok = true;
address receivedToken = sourceToken;
dstAmount = _amount;
if (m.actionType == Interchain.ActionType.UNI_V2)
(ok, dstAmount, receivedToken) = _handleUniswapV2(sourceToken, _amount, m);
else if (m.actionType == Interchain.ActionType.UNI_V3)
(ok, dstAmount, receivedToken) = _handleUniswapV3(sourceToken, _amount, m);
else if (m.actionType == Interchain.ActionType.CALL)
(ok, dstAmount, receivedToken) = _handleCall(sourceToken, _amount, m);
else if (m.actionType == Interchain.ActionType.CURVE)
(ok, dstAmount, receivedToken) = _handleCurve(sourceToken, _amount, m);
else if (m.actionType != Interchain.ActionType.NO_ACTION)
revert("Unsupported actionType");
if (ok && m.postAction != Interchain.CallSubActionType.NO_ACTION) {
(ok, dstAmount, receivedToken) = _handlePostAction(receivedToken, dstAmount, m.postAction);
}
status = ok ? IRango.CrossChainOperationStatus.Succeeded : IRango.CrossChainOperationStatus.RefundInDestination;
IRangoMessageReceiver.ProcessStatus dAppStatus = ok
? IRangoMessageReceiver.ProcessStatus.SUCCESS
: IRangoMessageReceiver.ProcessStatus.REFUND_IN_DESTINATION;
_sendTokenWithDApp(receivedToken, dstAmount, m.recipient, m.dAppMessage, m.dAppDestContract, dAppStatus);
return (receivedToken, dstAmount, status);
}
function _handleUniswapV2(
address _token,
uint _amount,
Interchain.RangoInterChainMessage memory _message
) private returns (bool ok, uint256 amountOut, address outToken) {
Interchain.UniswapV2Action memory action = abi.decode((_message.action), (Interchain.UniswapV2Action));
address weth = getWeth();
if (isContractWhitelisted(action.dexAddress) != true) {
return (false, _amount, _token);
}
if (action.path.length < 2) {
return (false, _amount, _token);
}
bool shouldDeposit = _token == LibSwapper.ETH && action.path[0] == weth;
if (!shouldDeposit) {
if (_token != action.path[0]) {
return (false, _amount, _token);
}
} else {
IWETH(weth).deposit{value : _amount}();
}
LibSwapper.approve(action.path[0], action.dexAddress, _amount);
address toToken = action.path[action.path.length - 1];
uint toBalanceBefore = LibSwapper.getBalanceOf(toToken);
try
IUniswapV2(action.dexAddress).swapExactTokensForTokens(
_amount,
action.amountOutMin,
action.path,
address(this),
action.deadline
)
returns (uint256[] memory) {
emit ActionDone(Interchain.ActionType.UNI_V2, action.dexAddress, true, "");
uint toBalanceAfter = LibSwapper.getBalanceOf(toToken);
SafeERC20.forceApprove(IERC20(action.path[0]), action.dexAddress, 0);
return (true, toBalanceAfter - toBalanceBefore, toToken);
} catch {
emit ActionDone(Interchain.ActionType.UNI_V2, action.dexAddress, false, "Uniswap-V2 call failed");
SafeERC20.forceApprove(IERC20(action.path[0]), action.dexAddress, 0);
return (false, _amount, shouldDeposit ? weth : _token);
}
}
function _handleUniswapV3(
address _token,
uint _amount,
Interchain.RangoInterChainMessage memory _message
) private returns (bool, uint256, address) {
Interchain.UniswapV3ActionExactInputParams memory action = abi
.decode((_message.action), (Interchain.UniswapV3ActionExactInputParams));
if (isContractWhitelisted(action.dexAddress) != true) {
return (false, _amount, _token);
}
address toToken = action.tokenOut;
{
bytes memory encodedPath = action.encodedPath;
address toTokenFromPath;
uint256 encodedPathLen = action.encodedPath.length;
assembly {
toTokenFromPath := mload(add(encodedPath, encodedPathLen))
}
if (toTokenFromPath != toToken) {
return (false, _amount, _token);
}
}
address weth = getWeth();
bool shouldDeposit = _token == LibSwapper.ETH && action.tokenIn == weth;
if (!shouldDeposit) {
if (_token != action.tokenIn) {
return (false, _amount, _token);
}
} else {
IWETH(weth).deposit{value : _amount}();
}
LibSwapper.approve(action.tokenIn, action.dexAddress, _amount);
uint toBalanceBefore = LibSwapper.getBalanceOf(toToken);
if (action.isRouter2 == false) {
try
IUniswapV3(action.dexAddress).exactInput(IUniswapV3.ExactInputParams({
path : action.encodedPath,
recipient : address(this),
deadline : action.deadline,
amountIn : _amount,
amountOutMinimum : action.amountOutMinimum
}))
returns (uint) {
emit ActionDone(Interchain.ActionType.UNI_V3, action.dexAddress, true, "");
uint toBalanceAfter = LibSwapper.getBalanceOf(toToken);
SafeERC20.forceApprove(IERC20(action.tokenIn), action.dexAddress, 0);
return (true, toBalanceAfter - toBalanceBefore, toToken);
} catch {
emit ActionDone(Interchain.ActionType.UNI_V3, action.dexAddress, false, "Uniswap-V3 call failed");
SafeERC20.forceApprove(IERC20(action.tokenIn), action.dexAddress, 0);
return (false, _amount, shouldDeposit ? weth : _token);
}
}
else {
try
IUniswapV3(action.dexAddress).exactInput(IUniswapV3.ExactInputParamsRouter2({
path : action.encodedPath,
recipient : address(this),
amountIn : _amount,
amountOutMinimum : action.amountOutMinimum
}))
returns (uint) {
emit ActionDone(Interchain.ActionType.UNI_V3, action.dexAddress, true, "");
uint toBalanceAfter = LibSwapper.getBalanceOf(toToken);
SafeERC20.forceApprove(IERC20(action.tokenIn), action.dexAddress, 0);
return (true, toBalanceAfter - toBalanceBefore, toToken);
} catch {
emit ActionDone(Interchain.ActionType.UNI_V3, action.dexAddress, false, "Uniswap-V3 call failed");
SafeERC20.forceApprove(IERC20(action.tokenIn), action.dexAddress, 0);
return (false, _amount, shouldDeposit ? weth : _token);
}
}
}
function _handleCall(
address _token,
uint _amount,
Interchain.RangoInterChainMessage memory _message
) private returns (bool ok, uint256 amountOut, address outToken) {
Interchain.CallAction memory action = abi.decode((_message.action), (Interchain.CallAction));
if (isContractWhitelisted(action.target) != true) {
return (false, _amount, _token);
}
if (isContractWhitelisted(action.spender) != true) {
return (false, _amount, _token);
}
address sourceToken = _token;
if (action.preAction == Interchain.CallSubActionType.WRAP) {
if (_token != LibSwapper.ETH) {
return (false, _amount, _token);
}
if (action.tokenIn != getWeth()) {
return (false, _amount, _token);
}
(ok, amountOut, sourceToken) = _handleWrap(_token, _amount);
} else if (action.preAction == Interchain.CallSubActionType.UNWRAP) {
if (_token != getWeth()) {
return (false, _amount, _token);
}
if (action.tokenIn != LibSwapper.ETH) {
return (false, _amount, _token);
}
(ok, amountOut, sourceToken) = _handleUnwrap(_token, _amount);
} else {
ok = true;
if (action.tokenIn != _token) {
return (false, _amount, _token);
}
}
if (!ok)
return (false, _amount, _token);
if (sourceToken != LibSwapper.ETH)
LibSwapper.approve(sourceToken, action.spender, _amount);
uint value = sourceToken == LibSwapper.ETH ? _amount : 0;
uint toBalanceBefore = LibSwapper.getBalanceOf(_message.toToken);
if (action.overwriteAmount == true) {
bytes memory data = action.callData;
uint256 index = action.startIndexForAmount;
if (index < 4 || data.length < 32 || index > (data.length - 32))
return (false, _amount, _token);
assembly {
mstore(add(data, add(index,32)), _amount)
}
}
(bool success, bytes memory ret) = action.target.call{value: value}(action.callData);
if (sourceToken != LibSwapper.ETH)
SafeERC20.forceApprove(IERC20(sourceToken), action.spender, 0);
if (success) {
emit ActionDone(Interchain.ActionType.CALL, action.target, true, "");
uint toBalanceAfter = LibSwapper.getBalanceOf(_message.toToken);
return (true, toBalanceAfter - toBalanceBefore, _message.toToken);
} else {
emit ActionDone(Interchain.ActionType.CALL, action.target, false, LibSwapper._getRevertMsg(ret));
return (false, _amount, sourceToken);
}
}
function _handleCurve(
address _token,
uint _amount,
Interchain.RangoInterChainMessage memory _message
) private returns (bool ok, uint256 amountOut, address outToken) {
Interchain.CurveAction memory action = abi.decode((_message.action), (Interchain.CurveAction));
if (isContractWhitelisted(action.routerContractAddress) != true) {
return (false, _amount, _token);
}
uint value = 0;
if (_token == LibSwapper.ETH) {
if (action.routes[0] != address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)) {
return (false, _amount, _token);
}
value = _amount;
} else {
if (_token != action.routes[0]) {
return (false, _amount, _token);
}
LibSwapper.approve(_token, action.routerContractAddress, _amount);
}
address toToken = action.toToken;
uint toBalanceBefore = LibSwapper.getBalanceOf(toToken);
try
ICurve(action.routerContractAddress).exchange{value: value}(
action.routes,
action.swap_params,
_amount,
action.expected,
action.pools,
address(this)
)
returns (uint256) {
emit ActionDone(Interchain.ActionType.CURVE, action.routerContractAddress, true, "");
uint toBalanceAfter = LibSwapper.getBalanceOf(toToken);
if (_token != LibSwapper.ETH) {
SafeERC20.forceApprove(IERC20(_token), action.routerContractAddress, 0);
}
return (true, toBalanceAfter - toBalanceBefore, toToken);
} catch {
emit ActionDone(Interchain.ActionType.CURVE, action.routerContractAddress, false, "Curve call failed");
if (_token != LibSwapper.ETH) {
SafeERC20.forceApprove(IERC20(_token), action.routerContractAddress, 0);
}
return (false, _amount, _token);
}
}
function _handlePostAction(
address _token,
uint _amount,
Interchain.CallSubActionType _postAction
) private returns (bool ok, uint256 amountOut, address outToken) {
if (_postAction == Interchain.CallSubActionType.WRAP) {
if (_token != LibSwapper.ETH) {
return (false, _amount, _token);
}
(ok, amountOut, outToken) = _handleWrap(_token, _amount);
} else if (_postAction == Interchain.CallSubActionType.UNWRAP) {
if (_token != getWeth()) {
return (false, _amount, _token);
}
(ok, amountOut, outToken) = _handleUnwrap(_token, _amount);
} else {
return (false, _amount, _token);
}
if (!ok)
return (false, _amount, _token);
return (ok, amountOut, outToken);
}
function _handleWrap(
address _token,
uint _amount
) private returns (bool ok, uint256 amountOut, address outToken) {
if (_token != LibSwapper.ETH) {
return (false, _amount, _token);
}
address weth = getWeth();
IWETH(weth).deposit{value: _amount}();
emit SubActionDone(Interchain.CallSubActionType.WRAP, weth, true, "");
return (true, _amount, weth);
}
function _handleUnwrap(
address _token,
uint _amount
) private returns (bool ok, uint256 amountOut, address outToken) {
address weth = getWeth();
if (_token != weth)
return (false, _amount, _token);
IWETH(weth).withdraw(_amount);
emit SubActionDone(Interchain.CallSubActionType.UNWRAP, weth, true, "");
return (true, _amount, LibSwapper.ETH);
}
function _sendTokenWithDApp(
address _token,
uint256 _amount,
address _receiver,
bytes memory _dAppMessage,
address _dAppReceiverContract,
IRangoMessageReceiver.ProcessStatus processStatus
) internal {
bool thereIsAMessage = _dAppReceiverContract != LibSwapper.ETH;
address immediateReceiver = thereIsAMessage ? _dAppReceiverContract : _receiver;
emit LibSwapper.SendToken(_token, _amount, immediateReceiver);
if (_token == LibSwapper.ETH) {
LibSwapper._sendNative(immediateReceiver, _amount);
} else {
SafeERC20.safeTransfer(IERC20(_token), immediateReceiver, _amount);
}
if (thereIsAMessage) {
require(
isMessagingContractWhitelisted(_dAppReceiverContract),
"3rd-party contract not whitelisted"
);
try IRangoMessageReceiver(_dAppReceiverContract)
.handleRangoMessage(_token, _amount, processStatus, _dAppMessage)
{
emit CrossChainMessageCalled(_dAppReceiverContract, _token, _amount, processStatus, _dAppMessage, true, "");
} catch Error(string memory reason) {
emit CrossChainMessageCalled(_dAppReceiverContract, _token, _amount, processStatus, _dAppMessage, false, reason);
} catch (bytes memory lowLevelData) {
emit CrossChainMessageCalled(_dAppReceiverContract, _token, _amount, processStatus, _dAppMessage, false, LibSwapper._getRevertMsg(lowLevelData));
}
}
}
function getWeth() internal view returns(address) {
address whitelistsContractAddress = getLibInterchainStorage().whitelistsStorageContract;
return IRangoMiddlewareWhitelists(whitelistsContractAddress).getWeth();
}
function isMiddlewaresPaused(address _middleware) internal view returns (bool) {
address whitelistsContractAddress = getLibInterchainStorage().whitelistsStorageContract;
return IRangoMiddlewareWhitelists(whitelistsContractAddress).isMiddlewaresPaused(_middleware);
}
function getLibInterchainStorage() internal pure returns (BaseInterchainStorage storage s) {
bytes32 namespace = LIBINTERCHAIN_CONTRACT_NAMESPACE;
assembly {
s.slot := namespace
}
}
}
文件 15 的 19:LibSwapper.sol
pragma solidity 0.8.25;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IWETH.sol";
import "../interfaces/IRango.sol";
library LibSwapper {
bytes32 internal constant BASE_SWAPPER_NAMESPACE = keccak256("exchange.rango.library.swapper");
address payable constant ETH = payable(0x0000000000000000000000000000000000000000);
struct BaseSwapperStorage {
address payable feeContractAddress;
address WETH;
mapping(address => bool) whitelistContracts;
mapping(address => mapping(bytes4 => bool)) whitelistMethods;
}
event FeeInfo(
address token,
address indexed affiliatorAddress,
uint platformFee,
uint destinationExecutorFee,
uint affiliateFee,
uint16 indexed dAppTag
);
event CallResult(address target, bool success, bytes returnData);
event RangoSwap(
address indexed requestId,
address fromToken,
address toToken,
uint amountIn,
uint minimumAmountExpected,
uint16 indexed dAppTag,
uint outputAmount,
address receiver,
string dAppName
);
event DexOutput(address _token, uint amount);
event SendToken(address _token, uint256 _amount, address _receiver);
event FeeContractAddressUpdated(address _oldAddress, address _newAddress);
event WethContractAddressUpdated(address _oldAddress, address _newAddress);
event Refunded(address _token, uint _amount);
struct Call {
address spender;
address payable target;
address swapFromToken;
address swapToToken;
bool needsTransferFromUser;
uint amount;
bytes callData;
}
struct SwapRequest {
address requestId;
address fromToken;
address toToken;
uint amountIn;
uint platformFee;
uint destinationExecutorFee;
uint affiliateFee;
address payable affiliatorAddress;
uint minimumAmountExpected;
bool feeFromInputToken;
uint16 dAppTag;
string dAppName;
}
function setWeth(address _weth) internal {
BaseSwapperStorage storage baseStorage = getBaseSwapperStorage();
address oldAddress = baseStorage.WETH;
baseStorage.WETH = _weth;
require(_weth != address(0), "Invalid WETH!");
emit WethContractAddressUpdated(oldAddress, _weth);
}
function updateFeeContractAddress(address payable _address) internal {
BaseSwapperStorage storage baseSwapperStorage = getBaseSwapperStorage();
address oldAddress = baseSwapperStorage.feeContractAddress;
baseSwapperStorage.feeContractAddress = _address;
emit FeeContractAddressUpdated(oldAddress, _address);
}
function addWhitelist(address contractAddress) internal {
BaseSwapperStorage storage baseStorage = getBaseSwapperStorage();
baseStorage.whitelistContracts[contractAddress] = true;
}
function addMethodWhitelists(address contractAddress, bytes4[] calldata methodIds) internal {
BaseSwapperStorage storage baseStorage = getBaseSwapperStorage();
baseStorage.whitelistContracts[contractAddress] = true;
for (uint i = 0; i < methodIds.length; i++)
baseStorage.whitelistMethods[contractAddress][methodIds[i]] = true;
}
function addMethodWhitelist(address contractAddress, bytes4 methodId) internal {
BaseSwapperStorage storage baseStorage = getBaseSwapperStorage();
baseStorage.whitelistContracts[contractAddress] = true;
baseStorage.whitelistMethods[contractAddress][methodId] = true;
}
function removeWhitelist(address contractAddress) internal {
BaseSwapperStorage storage baseStorage = getBaseSwapperStorage();
delete baseStorage.whitelistContracts[contractAddress];
}
function removeMethodWhitelist(address contractAddress, bytes4 methodId) internal {
BaseSwapperStorage storage baseStorage = getBaseSwapperStorage();
delete baseStorage.whitelistMethods[contractAddress][methodId];
}
function onChainSwapsPreBridge(
SwapRequest memory request,
Call[] calldata calls,
uint extraFee
) internal returns (uint out) {
uint minimumRequiredValue = getPreBridgeMinAmount(request) + extraFee;
require(msg.value >= minimumRequiredValue, 'Send more ETH to cover input amount + fee');
(, out) = onChainSwapsInternal(request, calls, extraFee);
emitSwapEvent(request, out, ETH);
return out;
}
function onChainSwapsInternal(
SwapRequest memory request,
Call[] calldata calls,
uint256 extraNativeFee
) internal returns (bytes[] memory, uint) {
uint toBalanceBefore = getBalanceOf(request.toToken);
uint fromBalanceBefore = getBalanceOf(request.fromToken);
uint256[] memory initialBalancesList = getInitialBalancesList(calls);
transferTokensFromUserForSwapRequest(request);
transferTokensFromUserForCalls(calls);
bytes[] memory result = callSwapsAndFees(request, calls);
returnExcessAmounts(request, calls, initialBalancesList);
uint fromBalanceAfter = getBalanceOf(request.fromToken);
if (request.fromToken != ETH) {
require(fromBalanceAfter >= fromBalanceBefore, "Source token balance on contract must not decrease after swap");
if (fromBalanceAfter > fromBalanceBefore)
_sendToken(request.fromToken, fromBalanceAfter - fromBalanceBefore, msg.sender);
}
else {
require(fromBalanceAfter >= fromBalanceBefore - msg.value + extraNativeFee, "Source token balance on contract must not decrease after swap");
if (fromBalanceAfter > fromBalanceBefore - msg.value + extraNativeFee)
_sendToken(request.fromToken, fromBalanceAfter + msg.value - fromBalanceBefore - extraNativeFee, msg.sender);
}
uint toBalanceAfter = getBalanceOf(request.toToken);
uint secondaryBalance = toBalanceAfter - toBalanceBefore;
require(secondaryBalance >= request.minimumAmountExpected, "Output is less than minimum expected");
return (result, secondaryBalance);
}
function callSwapsAndFees(SwapRequest memory request, Call[] calldata calls) private returns (bytes[] memory) {
BaseSwapperStorage storage baseSwapperStorage = getBaseSwapperStorage();
for (uint256 i = 0; i < calls.length; i++) {
require(baseSwapperStorage.whitelistContracts[calls[i].spender], "Contract spender not whitelisted");
require(baseSwapperStorage.whitelistContracts[calls[i].target], "Contract target not whitelisted");
bytes4 sig = bytes4(calls[i].callData[: 4]);
require(baseSwapperStorage.whitelistMethods[calls[i].target][sig], "Unauthorized call data!");
}
collectFeesBeforeSwap(request);
bytes[] memory returnData = new bytes[](calls.length);
address tmpSwapFromToken;
for (uint256 i = 0; i < calls.length; i++) {
tmpSwapFromToken = calls[i].swapFromToken;
bool isTokenNative = tmpSwapFromToken == ETH;
if (isTokenNative == false)
approveMax(tmpSwapFromToken, calls[i].spender, calls[i].amount);
(bool success, bytes memory ret) = isTokenNative
? calls[i].target.call{value : calls[i].amount}(calls[i].callData)
: calls[i].target.call(calls[i].callData);
emit CallResult(calls[i].target, success, ret);
if (!success)
revert(_getRevertMsg(ret));
returnData[i] = ret;
}
collectFeesAfterSwap(request);
return returnData;
}
function approve(address token, address spender, uint value) internal {
SafeERC20.forceApprove(IERC20(token), spender, value);
}
function approveMax(address token, address spender, uint value) internal {
uint256 currentAllowance = IERC20(token).allowance(address(this), spender);
if (currentAllowance < value) {
SafeERC20.forceApprove(IERC20(token), spender, type(uint256).max);
}
}
function _sendToken(address _token, uint256 _amount, address _receiver) internal {
(_token == ETH) ? _sendNative(_receiver, _amount) : SafeERC20.safeTransfer(IERC20(_token), _receiver, _amount);
}
function sumFees(IRango.RangoBridgeRequest memory request) internal pure returns (uint256) {
return request.platformFee + request.affiliateFee + request.destinationExecutorFee;
}
function sumFees(SwapRequest memory request) internal pure returns (uint256) {
return request.platformFee + request.affiliateFee + request.destinationExecutorFee;
}
function getPreBridgeMinAmount(SwapRequest memory request) internal pure returns (uint256) {
bool isNative = request.fromToken == ETH;
if (request.feeFromInputToken) {
return (isNative ? request.platformFee + request.affiliateFee + request.amountIn + request.destinationExecutorFee : 0);
}
return (isNative ? request.amountIn : 0);
}
function collectFeesForSwap(SwapRequest memory request) internal {
BaseSwapperStorage storage baseSwapperStorage = getBaseSwapperStorage();
bool hasPlatformFee = request.platformFee > 0;
bool hasDestExecutorFee = request.destinationExecutorFee > 0;
bool hasAffiliateFee = request.affiliateFee > 0;
address feeToken = request.feeFromInputToken ? request.fromToken : request.toToken;
if (hasPlatformFee || hasDestExecutorFee) {
require(baseSwapperStorage.feeContractAddress != ETH, "Fee contract address not set");
_sendToken(feeToken, request.platformFee + request.destinationExecutorFee, baseSwapperStorage.feeContractAddress, false);
}
if (hasAffiliateFee) {
require(request.affiliatorAddress != ETH, "Invalid affiliatorAddress");
_sendToken(feeToken, request.affiliateFee, request.affiliatorAddress, false);
}
if (hasPlatformFee || hasDestExecutorFee || hasAffiliateFee) {
emit FeeInfo(
feeToken,
request.affiliatorAddress,
request.platformFee,
request.destinationExecutorFee,
request.affiliateFee,
request.dAppTag
);
}
}
function collectFees(IRango.RangoBridgeRequest memory request) internal {
bool hasPlatformFee = request.platformFee > 0;
bool hasDestExecutorFee = request.destinationExecutorFee > 0;
bool hasAffiliateFee = request.affiliateFee > 0;
bool hasAnyFee = hasPlatformFee || hasDestExecutorFee || hasAffiliateFee;
if (!hasAnyFee) {
return;
}
BaseSwapperStorage storage baseSwapperStorage = getBaseSwapperStorage();
if (hasPlatformFee || hasDestExecutorFee) {
require(baseSwapperStorage.feeContractAddress != ETH, "Fee contract address not set");
_sendToken(request.token, request.platformFee + request.destinationExecutorFee, baseSwapperStorage.feeContractAddress, false);
}
if (hasAffiliateFee) {
require(request.affiliatorAddress != ETH, "Invalid affiliatorAddress");
_sendToken(request.token, request.affiliateFee, request.affiliatorAddress, false);
}
emit FeeInfo(
request.token,
request.affiliatorAddress,
request.platformFee,
request.destinationExecutorFee,
request.affiliateFee,
request.dAppTag
);
}
function collectFeesBeforeSwap(SwapRequest memory request) internal {
if (request.feeFromInputToken) {
collectFeesForSwap(request);
}
}
function collectFeesAfterSwap(SwapRequest memory request) internal {
if (!request.feeFromInputToken) {
collectFeesForSwap(request);
}
}
function collectFeesFromSender(IRango.RangoBridgeRequest memory request) internal {
bool hasPlatformFee = request.platformFee > 0;
bool hasDestExecutorFee = request.destinationExecutorFee > 0;
bool hasAffiliateFee = request.affiliateFee > 0;
bool hasAnyFee = hasPlatformFee || hasDestExecutorFee || hasAffiliateFee;
if (!hasAnyFee) {
return;
}
bool isSourceNative = request.token == ETH;
BaseSwapperStorage storage baseSwapperStorage = getBaseSwapperStorage();
if (hasPlatformFee || hasDestExecutorFee) {
require(baseSwapperStorage.feeContractAddress != ETH, "Fee contract address not set");
if (isSourceNative)
_sendToken(request.token, request.platformFee + request.destinationExecutorFee, baseSwapperStorage.feeContractAddress, false);
else
SafeERC20.safeTransferFrom(
IERC20(request.token),
msg.sender,
baseSwapperStorage.feeContractAddress,
request.platformFee + request.destinationExecutorFee
);
}
if (hasAffiliateFee) {
require(request.affiliatorAddress != ETH, "Invalid affiliatorAddress");
if (isSourceNative)
_sendToken(request.token, request.affiliateFee, request.affiliatorAddress, false);
else
SafeERC20.safeTransferFrom(
IERC20(request.token),
msg.sender,
request.affiliatorAddress,
request.affiliateFee
);
}
emit FeeInfo(
request.token,
request.affiliatorAddress,
request.platformFee,
request.destinationExecutorFee,
request.affiliateFee,
request.dAppTag
);
}
function _sendToken(
address _token,
uint256 _amount,
address _receiver,
bool _withdraw
) internal {
BaseSwapperStorage storage baseStorage = getBaseSwapperStorage();
emit SendToken(_token, _amount, _receiver);
bool nativeOut = _token == LibSwapper.ETH;
if (_withdraw) {
require(_token == baseStorage.WETH, "token mismatch");
IWETH(baseStorage.WETH).withdraw(_amount);
nativeOut = true;
}
if (nativeOut) {
_sendNative(_receiver, _amount);
} else {
SafeERC20.safeTransfer(IERC20(_token), _receiver, _amount);
}
}
function _sendNative(address _receiver, uint _amount) internal {
(bool sent,) = _receiver.call{value : _amount}("");
require(sent, "failed to send native");
}
function getBaseSwapperStorage() internal pure returns (BaseSwapperStorage storage s) {
bytes32 namespace = BASE_SWAPPER_NAMESPACE;
assembly {
s.slot := namespace
}
}
function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
if (_returnData.length < 68) return 'Transaction reverted silently';
assembly {
_returnData := add(_returnData, 0x04)
}
return abi.decode(_returnData, (string));
}
function getBalanceOf(address token) internal view returns (uint) {
return token == ETH ? address(this).balance : IERC20(token).balanceOf(address(this));
}
function getInitialBalancesList(Call[] calldata calls) internal view returns (uint256[] memory) {
uint callsLength = calls.length;
uint256[] memory balancesList = new uint256[](callsLength);
address token;
for (uint256 i = 0; i < callsLength; i++) {
token = calls[i].swapToToken;
balancesList[i] = getBalanceOf(token);
if (token == ETH)
balancesList[i] -= msg.value;
}
return balancesList;
}
function transferTokensFromUserForSwapRequest(SwapRequest memory request) private {
uint transferAmount = request.amountIn + (request.feeFromInputToken ? sumFees(request) : 0);
if (request.fromToken != ETH)
SafeERC20.safeTransferFrom(IERC20(request.fromToken), msg.sender, address(this), transferAmount);
else
require(msg.value >= transferAmount);
}
function transferTokensFromUserForCalls(Call[] calldata calls) private {
uint callsLength = calls.length;
Call calldata call;
address token;
for (uint256 i = 0; i < callsLength; i++) {
call = calls[i];
token = call.swapFromToken;
if (call.needsTransferFromUser && token != ETH)
SafeERC20.safeTransferFrom(IERC20(call.swapFromToken), msg.sender, address(this), call.amount);
}
}
function returnExcessAmounts(
SwapRequest memory request,
Call[] calldata calls,
uint256[] memory initialBalancesList) internal {
uint excessAmountToToken;
address tmpSwapToToken;
uint currentBalanceTo;
for (uint256 i = 0; i < calls.length; i++) {
tmpSwapToToken = calls[i].swapToToken;
currentBalanceTo = getBalanceOf(tmpSwapToToken);
excessAmountToToken = currentBalanceTo - initialBalancesList[i];
if (excessAmountToToken > 0 && tmpSwapToToken != request.toToken) {
_sendToken(tmpSwapToToken, excessAmountToToken, msg.sender);
}
}
}
function emitSwapEvent(SwapRequest memory request, uint output, address receiver) internal {
emit RangoSwap(
request.requestId,
request.fromToken,
request.toToken,
request.amountIn,
request.minimumAmountExpected,
request.dAppTag,
output,
receiver,
request.dAppName
);
}
}
文件 16 的 19:RangoBaseInterchainMiddleware.sol
pragma solidity 0.8.25;
import "../../libraries/LibInterchain.sol";
import "../../interfaces/IRangoMiddlewareWhitelists.sol";
contract RangoBaseInterchainMiddleware {
bytes32 internal constant BASE_MIDDLEWARE_CONTRACT_NAMESPACE = keccak256("exchange.rango.middleware.base");
struct BaseInterchainMiddlewareStorage {
address owner;
}
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event Refunded(address _token, uint _amount);
constructor(){updateOwnerInternal(tx.origin);}
function initBaseMiddleware(
address _owner,
address _whitelistsContract
) public onlyOwner {
require(_owner != address(0));
updateOwnerInternal(_owner);
LibInterchain.updateWhitelistsContractAddress(_whitelistsContract);
}
modifier onlyOwner() {
require(msg.sender == getBaseInterchainMiddlewareStorage().owner, "should be called only by owner");
_;
}
modifier onlyWhenNotPaused() {
require(LibInterchain.isMiddlewaresPaused(address(this)) == false, "paused");
_;
}
modifier onlyDiamond() {
{
address s = LibInterchain.getLibInterchainStorage().whitelistsStorageContract;
address rangoDiamond = IRangoMiddlewareWhitelists(s).getRangoDiamond();
require(msg.sender == rangoDiamond, "should be called only from diamond");
}
_;
}
receive() external payable {}
function getOwner() external view returns (address) {
BaseInterchainMiddlewareStorage storage s = getBaseInterchainMiddlewareStorage();
return s.owner;
}
function getWhitelistsStorageContractAddress() external view returns (address) {
return LibInterchain.getLibInterchainStorage().whitelistsStorageContract;
}
function updateOwner(address newAddress) external onlyOwner {
updateOwnerInternal(newAddress);
}
function updateWhitelistsContractAddress(address newAddress) external onlyOwner {
LibInterchain.updateWhitelistsContractAddress(newAddress);
}
function refund(address _tokenAddress, uint256 _amount) external onlyOwner {
IERC20 ercToken = IERC20(_tokenAddress);
uint balance = ercToken.balanceOf(address(this));
require(balance >= _amount, 'Insufficient balance');
SafeERC20.safeTransfer(IERC20(_tokenAddress), msg.sender, _amount);
emit Refunded(_tokenAddress, _amount);
}
function refundNative(uint256 _amount) external onlyOwner {
uint balance = address(this).balance;
require(balance >= _amount, 'Insufficient balance');
(bool sent,) = msg.sender.call{value : _amount}("");
require(sent, "failed to send native");
emit Refunded(LibSwapper.ETH, _amount);
}
function updateOwnerInternal(address newAddress) private {
BaseInterchainMiddlewareStorage storage s = getBaseInterchainMiddlewareStorage();
address oldAddress = s.owner;
s.owner = newAddress;
emit OwnershipTransferred(oldAddress, newAddress);
}
function getBaseInterchainMiddlewareStorage() private pure returns (BaseInterchainMiddlewareStorage storage s) {
bytes32 namespace = BASE_MIDDLEWARE_CONTRACT_NAMESPACE;
assembly {
s.slot := namespace
}
}
function encodeIm(Interchain.RangoInterChainMessage memory im) external pure returns (bytes memory) {
return abi.encode(im);
}
}
文件 17 的 19:RangoSymbiosisMiddleware.sol
pragma solidity 0.8.25;
import "../../interfaces/IRango.sol";
import "../../interfaces/IAxelarExecutable.sol";
import "../../interfaces/IUniswapV2.sol";
import "../../interfaces/IRangoMessageReceiver.sol";
import "../../interfaces/Interchain.sol";
import "../../libraries/LibInterchain.sol";
import "../base/RangoBaseInterchainMiddleware.sol";
import "../../utils/ReentrancyGuard.sol";
contract RangoSymbiosisMiddleware is IRango, ReentrancyGuard, RangoBaseInterchainMiddleware {
bytes32 internal constant SYMBIOSIS_NAMESPACE = keccak256("exchange.rango.middleware.symbiosis");
function initSymbiosisMiddleware(
address _owner,
address _gatewayAddress,
address _routerAddress,
address whitelistsContract
) external onlyOwner {
initBaseMiddleware(_owner, whitelistsContract);
updateSymbiosisGatewayInternal(_routerAddress, _gatewayAddress);
}
struct SymbiosisStorage {
address symbiosisMetaRouter;
address symbiosisMetaRouterGateway;
}
event SymbiosisAddressUpdated(
address oldMetaRouter,
address oldMetaRouterGateway,
address indexed newMetaRouter,
address indexed newMetaRouterGateway
);
event SymbiosisSwapStatusUpdated(
address token,
uint256 outputAmount,
IRango.CrossChainOperationStatus status,
address source,
address destination
);
function updateSymbiosisGatewayAddress(address metaRouter, address metaRouterGateway) public onlyOwner {
updateSymbiosisGatewayInternal(metaRouter, metaRouterGateway);
}
function fetchTokenFromRouterAndRefund(
address _tokenAddress,
uint256 _amount,
address _refundReceiver
) external onlyOwner {
address refundAddr = _refundReceiver == LibSwapper.ETH ? msg.sender : _refundReceiver;
IERC20 ercToken = IERC20(_tokenAddress);
SafeERC20.safeTransferFrom(ercToken, getSymbiosisStorage().symbiosisMetaRouter, refundAddr, _amount);
emit Refunded(_tokenAddress, _amount);
}
function messageReceive(
uint256 amount,
address token,
Interchain.RangoInterChainMessage memory receivedMessage
) external payable nonReentrant onlyWhenNotPaused {
require(msg.sender == getSymbiosisStorage().symbiosisMetaRouter, "not meta router");
SafeERC20.safeTransferFrom(IERC20(token), msg.sender, address(this), amount);
(address receivedToken, uint dstAmount, IRango.CrossChainOperationStatus status) = LibInterchain.handleDestinationMessage(token, amount, receivedMessage);
emit SymbiosisSwapStatusUpdated(receivedToken, dstAmount, status, receivedMessage.originalSender, receivedMessage.recipient);
}
function updateSymbiosisGatewayInternal(address metaRouter, address metaRouterGateway) private {
require(metaRouter != LibSwapper.ETH, "Invalid metaRouter address");
require(metaRouterGateway != LibSwapper.ETH, "Invalid metaRouterGateway address");
SymbiosisStorage storage s = getSymbiosisStorage();
address oldMetaRouter = s.symbiosisMetaRouter;
address oldMetaRouterGateway = s.symbiosisMetaRouterGateway;
s.symbiosisMetaRouter = metaRouter;
s.symbiosisMetaRouterGateway = metaRouterGateway;
emit SymbiosisAddressUpdated(oldMetaRouter, oldMetaRouterGateway, metaRouter, metaRouterGateway);
}
function getSymbiosisStorage() private pure returns (SymbiosisStorage storage s) {
bytes32 namespace = SYMBIOSIS_NAMESPACE;
assembly {
s.slot := namespace
}
}
}
文件 18 的 19:ReentrancyGuard.sol
pragma solidity 0.8.25;
abstract contract ReentrancyGuard {
bytes32 private constant NAMESPACE = keccak256("exchange.rango.reentrancyguard");
struct ReentrancyStorage {
uint256 status;
}
error ReentrancyError();
uint256 private constant _NOT_ENTERED = 0;
uint256 private constant _ENTERED = 1;
modifier nonReentrant() {
ReentrancyStorage storage s = reentrancyStorage();
if (s.status == _ENTERED) revert ReentrancyError();
s.status = _ENTERED;
_;
s.status = _NOT_ENTERED;
}
function reentrancyStorage() private pure returns (ReentrancyStorage storage data) {
bytes32 position = NAMESPACE;
assembly {
data.slot := position
}
}
}
文件 19 的 19:SafeERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
error SafeERC20FailedOperation(address token);
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
bytes memory returndata = address(token).functionCall(abi.encodeCall(token.transfer, (to, value)));
if (address(token)!=0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C && returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
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(token).code.length > 0;
}
}
{
"compilationTarget": {
"contracts/facets/bridges/RangoSymbiosisMiddleware.sol": "RangoSymbiosisMiddleware"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"ReentrancyError","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum Interchain.ActionType","name":"actionType","type":"uint8"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"ActionDone","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_receiverContract","type":"address"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"enum IRangoMessageReceiver.ProcessStatus","name":"_status","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"_appMessage","type":"bytes"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"string","name":"failReason","type":"string"}],"name":"CrossChainMessageCalled","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":true,"internalType":"address","name":"requestId","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"originalSender","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"enum IRango.CrossChainOperationStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"uint16","name":"dAppTag","type":"uint16"}],"name":"RangoBridgeCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestId","type":"address"},{"indexed":false,"internalType":"address","name":"bridgeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"bridgeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"hasInterchainMessage","type":"bool"},{"indexed":false,"internalType":"bool","name":"hasDestinationSwap","type":"bool"},{"indexed":true,"internalType":"uint8","name":"bridgeId","type":"uint8"},{"indexed":true,"internalType":"uint16","name":"dAppTag","type":"uint16"},{"indexed":false,"internalType":"string","name":"dAppName","type":"string"}],"name":"RangoBridgeInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Refunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_receiver","type":"address"}],"name":"SendToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum Interchain.CallSubActionType","name":"subActionType","type":"uint8"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"SubActionDone","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldMetaRouter","type":"address"},{"indexed":false,"internalType":"address","name":"oldMetaRouterGateway","type":"address"},{"indexed":true,"internalType":"address","name":"newMetaRouter","type":"address"},{"indexed":true,"internalType":"address","name":"newMetaRouterGateway","type":"address"}],"name":"SymbiosisAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"outputAmount","type":"uint256"},{"indexed":false,"internalType":"enum IRango.CrossChainOperationStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"address","name":"source","type":"address"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"SymbiosisSwapStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_newAddress","type":"address"}],"name":"WhitelistStorageAddressUpdated","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"requestId","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"bridgeRealOutput","type":"address"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"address","name":"originalSender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"enum Interchain.ActionType","name":"actionType","type":"uint8"},{"internalType":"bytes","name":"action","type":"bytes"},{"internalType":"enum Interchain.CallSubActionType","name":"postAction","type":"uint8"},{"internalType":"uint16","name":"dAppTag","type":"uint16"},{"internalType":"bytes","name":"dAppMessage","type":"bytes"},{"internalType":"address","name":"dAppSourceContract","type":"address"},{"internalType":"address","name":"dAppDestContract","type":"address"}],"internalType":"struct Interchain.RangoInterChainMessage","name":"im","type":"tuple"}],"name":"encodeIm","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_refundReceiver","type":"address"}],"name":"fetchTokenFromRouterAndRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistsStorageContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_whitelistsContract","type":"address"}],"name":"initBaseMiddleware","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_gatewayAddress","type":"address"},{"internalType":"address","name":"_routerAddress","type":"address"},{"internalType":"address","name":"whitelistsContract","type":"address"}],"name":"initSymbiosisMiddleware","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"components":[{"internalType":"address","name":"requestId","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"address","name":"bridgeRealOutput","type":"address"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"address","name":"originalSender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"enum Interchain.ActionType","name":"actionType","type":"uint8"},{"internalType":"bytes","name":"action","type":"bytes"},{"internalType":"enum Interchain.CallSubActionType","name":"postAction","type":"uint8"},{"internalType":"uint16","name":"dAppTag","type":"uint16"},{"internalType":"bytes","name":"dAppMessage","type":"bytes"},{"internalType":"address","name":"dAppSourceContract","type":"address"},{"internalType":"address","name":"dAppDestContract","type":"address"}],"internalType":"struct Interchain.RangoInterChainMessage","name":"receivedMessage","type":"tuple"}],"name":"messageReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"refundNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"updateOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"metaRouter","type":"address"},{"internalType":"address","name":"metaRouterGateway","type":"address"}],"name":"updateSymbiosisGatewayAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"updateWhitelistsContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]