编译器
0.8.19+commit.7dd6d404
文件 1 的 27:ActionExecutor.sol
pragma solidity 0.8.19;
import { ReentrancyGuard } from '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import { IActionDataStructures } from './interfaces/IActionDataStructures.sol';
import { IGateway } from './crosschain/interfaces/IGateway.sol';
import { IGatewayClient } from './crosschain/interfaces/IGatewayClient.sol';
import { IRegistry } from './interfaces/IRegistry.sol';
import { ISettings } from './interfaces/ISettings.sol';
import { ITokenMint } from './interfaces/ITokenMint.sol';
import { IVariableBalanceRecords } from './interfaces/IVariableBalanceRecords.sol';
import { IVault } from './interfaces/IVault.sol';
import { BalanceManagement } from './BalanceManagement.sol';
import { CallerGuard } from './CallerGuard.sol';
import { Pausable } from './Pausable.sol';
import { SystemVersionId } from './SystemVersionId.sol';
import { TokenMintError, ZeroAddressError } from './Errors.sol';
import './helpers/AddressHelper.sol' as AddressHelper;
import './helpers/DecimalsHelper.sol' as DecimalsHelper;
import './helpers/GasReserveHelper.sol' as GasReserveHelper;
import './helpers/RefundHelper.sol' as RefundHelper;
import './helpers/TransferHelper.sol' as TransferHelper;
import './Constants.sol' as Constants;
contract ActionExecutor is
SystemVersionId,
Pausable,
ReentrancyGuard,
CallerGuard,
BalanceManagement,
IGatewayClient,
ISettings,
IActionDataStructures
{
struct SourceGatewayContext {
IVault vault;
uint256 assetAmount;
}
IRegistry public registry;
IVariableBalanceRecords public variableBalanceRecords;
uint256 private lastActionId = block.chainid * 1e7 + 555 ** 2;
SourceGatewayContext private sourceGatewayContext;
event ActionSource(
uint256 indexed actionId,
uint256 indexed targetChainId,
address indexed sourceSender,
address targetRecipient,
uint256 gatewayType,
address sourceToken,
address targetToken,
uint256 amount,
uint256 fee,
uint256 timestamp
);
event ActionTarget(
uint256 indexed actionId,
uint256 indexed sourceChainId,
bool indexed isSuccess,
uint256 timestamp
);
event ActionLocal(
uint256 indexed actionId,
address indexed sender,
address recipient,
address fromToken,
address toToken,
uint256 fromAmount,
uint256 toAmount,
uint256 toTokenFee,
uint256 timestamp
);
event SourceProcessed(
uint256 indexed actionId,
bool indexed isLocal,
address indexed sender,
uint256 routerType,
address fromTokenAddress,
address toTokenAddress,
uint256 fromAmount,
uint256 resultAmount
);
event TargetProcessed(
uint256 indexed actionId,
address indexed recipient,
uint256 routerType,
address fromTokenAddress,
address toTokenAddress,
uint256 fromAmount,
uint256 resultAmount
);
event VariableBalanceAllocated(
uint256 indexed actionId,
address indexed recipient,
uint256 vaultType,
uint256 amount
);
event SetRegistry(address indexed registryAddress);
event SetVariableBalanceRecords(address indexed recordsAddress);
error OnlyGatewayError();
error OnlySelfError();
error SameChainIdError();
error SameTokenError();
error NativeTokenValueError();
error GatewayNotSetError();
error RouterNotSetError();
error VaultNotSetError();
error MessageFeeError();
error SwapAmountMaxError();
error SwapAmountMinError();
error SwapError();
error TargetSwapInfoError();
error VariableBalanceSwapTokenError();
error VariableBalanceSwapAmountError();
modifier onlyGateway() {
if (!registry.isGatewayAddress(msg.sender)) {
revert OnlyGatewayError();
}
_;
}
modifier onlySelf() {
if (msg.sender != address(this)) {
revert OnlySelfError();
}
_;
}
constructor(
IRegistry _registry,
IVariableBalanceRecords _variableBalanceRecords,
uint256 _actionIdOffset,
address _owner,
address[] memory _managers,
bool _addOwnerToManagers
) {
_setRegistry(_registry);
_setVariableBalanceRecords(_variableBalanceRecords);
lastActionId += _actionIdOffset;
_initRoles(_owner, _managers, _addOwnerToManagers);
}
receive() external payable {}
function setRegistry(IRegistry _registry) external onlyManager {
_setRegistry(_registry);
}
function executeLocal(
LocalAction calldata _localAction
) external payable whenNotPaused nonReentrant checkCaller returns (uint256 actionId) {
return _executeLocal(_localAction, false);
}
function execute(
Action calldata _action
) external payable whenNotPaused nonReentrant checkCaller returns (uint256 actionId) {
if (_action.targetChainId == block.chainid) {
revert SameChainIdError();
}
if (
_action.sourceTokenAddress == Constants.NATIVE_TOKEN_ADDRESS &&
msg.value < _action.sourceSwapInfo.fromAmount
) {
revert NativeTokenValueError();
}
uint256 initialBalance = address(this).balance - msg.value;
lastActionId++;
actionId = lastActionId;
SourceSettings memory settings = registry.sourceSettings(
msg.sender,
_action.targetChainId,
_action.gatewayType,
_action.sourceSwapInfo.routerType,
_action.vaultType
);
if (settings.vault == address(0)) {
revert VaultNotSetError();
}
address vaultAsset = IVault(settings.vault).asset();
(uint256 processedAmount, uint256 nativeTokenSpent) = _processSource(
actionId,
false,
_action.sourceTokenAddress,
vaultAsset,
_action.sourceSwapInfo,
settings.router,
settings.routerTransfer,
false
);
uint256 targetVaultAmountMax = _calculateVaultAmount(
settings.sourceVaultDecimals,
settings.targetVaultDecimals,
processedAmount,
true,
settings.systemFee,
settings.isWhitelist
);
SwapInfo memory targetSwapInfo;
uint256 targetOptionsLength = _action.targetSwapInfoOptions.length;
if (targetOptionsLength == 0) {
targetSwapInfo = SwapInfo({
fromAmount: targetVaultAmountMax,
routerType: uint256(0),
routerData: new bytes(0)
});
} else {
for (uint256 index; index < targetOptionsLength; index++) {
SwapInfo memory targetSwapInfoOption = _action.targetSwapInfoOptions[index];
if (targetSwapInfoOption.fromAmount <= targetVaultAmountMax) {
targetSwapInfo = targetSwapInfoOption;
break;
}
}
if (targetSwapInfo.fromAmount == 0) {
revert TargetSwapInfoError();
}
}
uint256 sourceVaultAmount = DecimalsHelper.convertDecimals(
settings.targetVaultDecimals,
settings.sourceVaultDecimals,
targetSwapInfo.fromAmount
);
uint256 normalizedAmount = DecimalsHelper.convertDecimals(
settings.sourceVaultDecimals,
Constants.DECIMALS_DEFAULT,
sourceVaultAmount
);
if (!settings.isWhitelist) {
_checkSwapAmountLimits(
normalizedAmount,
settings.swapAmountMin,
settings.swapAmountMax
);
}
TransferHelper.safeTransfer(vaultAsset, settings.vault, sourceVaultAmount);
bytes memory targetMessageData = abi.encode(
TargetMessage({
actionId: actionId,
sourceSender: msg.sender,
vaultType: _action.vaultType,
targetTokenAddress: _action.targetTokenAddress,
targetSwapInfo: targetSwapInfo,
targetRecipient: _action.targetRecipient == address(0)
? msg.sender
: _action.targetRecipient
})
);
_sendMessage(
settings,
_action,
targetMessageData,
msg.value - nativeTokenSpent,
sourceVaultAmount
);
uint256 systemFeeAmount = processedAmount - sourceVaultAmount;
if (systemFeeAmount > 0 && settings.feeCollector != address(0)) {
TransferHelper.safeTransfer(vaultAsset, settings.feeCollector, systemFeeAmount);
}
RefundHelper.refundExtraBalance(address(this), initialBalance, payable(msg.sender));
_emitActionSourceEvent(
actionId,
_action,
normalizedAmount,
DecimalsHelper.convertDecimals(
settings.sourceVaultDecimals,
Constants.DECIMALS_DEFAULT,
systemFeeAmount
)
);
}
function claimVariableToken(
uint256 _vaultType
) external whenNotPaused nonReentrant checkCaller {
_processVariableBalanceRepayment(_vaultType, false, _blankLocalAction());
}
function convertVariableBalanceToVaultAsset(
uint256 _vaultType
) external whenNotPaused nonReentrant checkCaller {
_processVariableBalanceRepayment(_vaultType, true, _blankLocalAction());
}
function convertVariableBalanceWithSwap(
uint256 _vaultType,
LocalAction calldata _localAction
) external whenNotPaused nonReentrant checkCaller {
_processVariableBalanceRepayment(_vaultType, true, _localAction);
}
function handleExecutionPayload(
uint256 _messageSourceChainId,
bytes calldata _payloadData
) external whenNotPaused onlyGateway {
TargetMessage memory targetMessage = abi.decode(_payloadData, (TargetMessage));
TargetSettings memory settings = registry.targetSettings(
targetMessage.vaultType,
targetMessage.targetSwapInfo.routerType
);
bool selfCallSuccess;
(bool hasGasReserve, uint256 gasAllowed) = GasReserveHelper.checkGasReserve(
settings.gasReserve
);
if (hasGasReserve) {
try this.selfCallTarget{ gas: gasAllowed }(settings, targetMessage) {
selfCallSuccess = true;
} catch {}
}
if (!selfCallSuccess) {
_targetAllocateVariableBalance(targetMessage);
}
emit ActionTarget(
targetMessage.actionId,
_messageSourceChainId,
selfCallSuccess,
block.timestamp
);
}
function selfCallTarget(
TargetSettings calldata _settings,
TargetMessage calldata _targetMessage
) external onlySelf {
if (_settings.vault == address(0)) {
revert VaultNotSetError();
}
address assetAddress = IVault(_settings.vault).requestAsset(
_targetMessage.targetSwapInfo.fromAmount,
address(this),
false
);
_processTarget(
_settings,
_targetMessage.actionId,
assetAddress,
_targetMessage.targetTokenAddress,
_targetMessage.targetSwapInfo,
_targetMessage.targetRecipient
);
}
function getSourceGatewayContext() external view returns (IVault vault, uint256 assetAmount) {
vault = sourceGatewayContext.vault;
assetAmount = sourceGatewayContext.assetAmount;
}
function messageFeeEstimate(
uint256 _gatewayType,
uint256 _targetChainId,
bytes[] calldata _targetRouterDataOptions,
bytes calldata _gatewaySettings
) external view returns (uint256) {
if (_targetChainId == block.chainid) {
return 0;
}
MessageFeeEstimateSettings memory settings = registry.messageFeeEstimateSettings(
_gatewayType
);
if (settings.gateway == address(0)) {
revert GatewayNotSetError();
}
uint256 result = 0;
if (_targetRouterDataOptions.length == 0) {
result = IGateway(settings.gateway).messageFee(
_targetChainId,
_blankMessage(new bytes(0)),
_gatewaySettings
);
} else {
for (uint256 index; index < _targetRouterDataOptions.length; index++) {
bytes memory messageData = _blankMessage(_targetRouterDataOptions[index]);
uint256 value = IGateway(settings.gateway).messageFee(
_targetChainId,
messageData,
_gatewaySettings
);
if (value > result) {
result = value;
}
}
}
return result;
}
function calculateLocalAmount(
uint256 _fromAmount,
bool _isForward
) external view returns (uint256 result) {
LocalAmountCalculationSettings memory settings = registry.localAmountCalculationSettings(
msg.sender
);
return
_calculateLocalAmount(
_fromAmount,
_isForward,
settings.systemFeeLocal,
settings.isWhitelist
);
}
function calculateVaultAmount(
uint256 _vaultType,
uint256 _fromChainId,
uint256 _toChainId,
uint256 _fromAmount,
bool _isForward
) external view returns (uint256 result) {
VaultAmountCalculationSettings memory settings = registry.vaultAmountCalculationSettings(
msg.sender,
_vaultType,
_fromChainId,
_toChainId
);
return
_calculateVaultAmount(
settings.fromDecimals,
settings.toDecimals,
_fromAmount,
_isForward,
settings.systemFee,
settings.isWhitelist
);
}
function variableBalance(address _account, uint256 _vaultType) external view returns (uint256) {
return variableBalanceRecords.getAccountBalance(_account, _vaultType);
}
function calculateLocalAmountFromVariableBalance(
uint256 _fromAmount,
bool
) external pure returns (uint256 result) {
return _fromAmount;
}
function _executeLocal(
LocalAction memory _localAction,
bool _fromVariableBalance
) private returns (uint256 actionId) {
if (_localAction.fromTokenAddress == _localAction.toTokenAddress) {
revert SameTokenError();
}
if (
_localAction.fromTokenAddress == Constants.NATIVE_TOKEN_ADDRESS &&
msg.value != _localAction.swapInfo.fromAmount
) {
revert NativeTokenValueError();
}
uint256 initialBalance = address(this).balance - msg.value;
lastActionId++;
actionId = lastActionId;
LocalSettings memory settings = registry.localSettings(
msg.sender,
_localAction.swapInfo.routerType
);
(uint256 processedAmount, ) = _processSource(
actionId,
true,
_localAction.fromTokenAddress,
_localAction.toTokenAddress,
_localAction.swapInfo,
settings.router,
settings.routerTransfer,
_fromVariableBalance
);
address recipient = _localAction.recipient == address(0)
? msg.sender
: _localAction.recipient;
uint256 recipientAmount = _fromVariableBalance
? processedAmount
: _calculateLocalAmount(
processedAmount,
true,
settings.systemFeeLocal,
settings.isWhitelist
);
if (_localAction.toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
TransferHelper.safeTransferNative(recipient, recipientAmount);
} else {
TransferHelper.safeTransfer(_localAction.toTokenAddress, recipient, recipientAmount);
}
uint256 systemFeeAmount = processedAmount - recipientAmount;
if (systemFeeAmount > 0) {
address feeCollector = settings.feeCollectorLocal;
if (feeCollector != address(0)) {
if (_localAction.toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
TransferHelper.safeTransferNative(feeCollector, systemFeeAmount);
} else {
TransferHelper.safeTransfer(
_localAction.toTokenAddress,
feeCollector,
systemFeeAmount
);
}
} else if (_localAction.toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
initialBalance += systemFeeAmount;
}
}
RefundHelper.refundExtraBalance(address(this), initialBalance, payable(msg.sender));
emit ActionLocal(
actionId,
msg.sender,
recipient,
_localAction.fromTokenAddress,
_localAction.toTokenAddress,
_localAction.swapInfo.fromAmount,
recipientAmount,
systemFeeAmount,
block.timestamp
);
}
function _processSource(
uint256 _actionId,
bool _isLocal,
address _fromTokenAddress,
address _toTokenAddress,
SwapInfo memory _sourceSwapInfo,
address _routerAddress,
address _routerTransferAddress,
bool _fromVariableBalance
) private returns (uint256 resultAmount, uint256 nativeTokenSpent) {
uint256 toTokenBalanceBefore = tokenBalance(_toTokenAddress);
if (_fromTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
if (_routerAddress == address(0)) {
revert RouterNotSetError();
}
(bool routerCallSuccess, ) = payable(_routerAddress).call{
value: _sourceSwapInfo.fromAmount
}(_sourceSwapInfo.routerData);
if (!routerCallSuccess) {
revert SwapError();
}
nativeTokenSpent = _sourceSwapInfo.fromAmount;
} else {
if (!_fromVariableBalance) {
TransferHelper.safeTransferFrom(
_fromTokenAddress,
msg.sender,
address(this),
_sourceSwapInfo.fromAmount
);
}
if (_fromTokenAddress != _toTokenAddress) {
if (_routerAddress == address(0)) {
revert RouterNotSetError();
}
TransferHelper.safeApprove(
_fromTokenAddress,
_routerTransferAddress,
_sourceSwapInfo.fromAmount
);
(bool routerCallSuccess, ) = _routerAddress.call(_sourceSwapInfo.routerData);
if (!routerCallSuccess) {
revert SwapError();
}
TransferHelper.safeApprove(_fromTokenAddress, _routerTransferAddress, 0);
}
nativeTokenSpent = 0;
}
resultAmount = tokenBalance(_toTokenAddress) - toTokenBalanceBefore;
emit SourceProcessed(
_actionId,
_isLocal,
msg.sender,
_sourceSwapInfo.routerType,
_fromTokenAddress,
_toTokenAddress,
_sourceSwapInfo.fromAmount,
resultAmount
);
}
function _processTarget(
TargetSettings memory settings,
uint256 _actionId,
address _fromTokenAddress,
address _toTokenAddress,
SwapInfo memory _targetSwapInfo,
address _targetRecipient
) private {
uint256 resultAmount;
if (_toTokenAddress == _fromTokenAddress) {
resultAmount = _targetSwapInfo.fromAmount;
} else {
if (settings.router == address(0)) {
revert RouterNotSetError();
}
uint256 toTokenBalanceBefore = tokenBalance(_toTokenAddress);
TransferHelper.safeApprove(
_fromTokenAddress,
settings.routerTransfer,
_targetSwapInfo.fromAmount
);
(bool success, ) = settings.router.call(_targetSwapInfo.routerData);
if (!success) {
revert SwapError();
}
TransferHelper.safeApprove(_fromTokenAddress, settings.routerTransfer, 0);
resultAmount = tokenBalance(_toTokenAddress) - toTokenBalanceBefore;
}
if (_toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
TransferHelper.safeTransferNative(_targetRecipient, resultAmount);
} else {
TransferHelper.safeTransfer(_toTokenAddress, _targetRecipient, resultAmount);
}
emit TargetProcessed(
_actionId,
_targetRecipient,
_targetSwapInfo.routerType,
_fromTokenAddress,
_toTokenAddress,
_targetSwapInfo.fromAmount,
resultAmount
);
}
function _targetAllocateVariableBalance(TargetMessage memory _targetMessage) private {
address tokenRecipient = _targetMessage.targetRecipient;
uint256 vaultType = _targetMessage.vaultType;
uint256 tokenAmount = _targetMessage.targetSwapInfo.fromAmount;
variableBalanceRecords.increaseBalance(tokenRecipient, vaultType, tokenAmount);
emit VariableBalanceAllocated(
_targetMessage.actionId,
tokenRecipient,
vaultType,
tokenAmount
);
}
function _processVariableBalanceRepayment(
uint256 _vaultType,
bool _convertToVaultAsset,
LocalAction memory _localAction
) private {
VariableBalanceRepaymentSettings memory settings = registry
.variableBalanceRepaymentSettings(_vaultType);
if (settings.vault == address(0)) {
revert VaultNotSetError();
}
uint256 tokenAmount = variableBalanceRecords.getAccountBalance(msg.sender, _vaultType);
variableBalanceRecords.clearBalance(msg.sender, _vaultType);
if (tokenAmount > 0) {
if (_convertToVaultAsset) {
if (_localAction.fromTokenAddress == address(0)) {
IVault(settings.vault).requestAsset(tokenAmount, msg.sender, true);
} else {
if (_localAction.fromTokenAddress != IVault(settings.vault).asset()) {
revert VariableBalanceSwapTokenError();
}
if (_localAction.swapInfo.fromAmount != tokenAmount) {
revert VariableBalanceSwapAmountError();
}
IVault(settings.vault).requestAsset(tokenAmount, address(this), true);
_executeLocal(_localAction, true);
}
} else {
address variableTokenAddress = IVault(settings.vault).checkVariableTokenState();
bool mintSuccess = ITokenMint(variableTokenAddress).mint(msg.sender, tokenAmount);
if (!mintSuccess) {
revert TokenMintError();
}
}
}
}
function _setRegistry(IRegistry _registry) private {
AddressHelper.requireContract(address(_registry));
registry = _registry;
emit SetRegistry(address(_registry));
}
function _setVariableBalanceRecords(IVariableBalanceRecords _variableBalanceRecords) private {
AddressHelper.requireContract(address(_variableBalanceRecords));
variableBalanceRecords = _variableBalanceRecords;
emit SetVariableBalanceRecords(address(_variableBalanceRecords));
}
function _sendMessage(
SourceSettings memory _settings,
Action calldata _action,
bytes memory _messageData,
uint256 _availableValue,
uint256 _assetAmount
) private {
if (_settings.gateway == address(0)) {
revert GatewayNotSetError();
}
uint256 messageFee = IGateway(_settings.gateway).messageFee(
_action.targetChainId,
_messageData,
_action.gatewaySettings
);
if (_availableValue < messageFee) {
revert MessageFeeError();
}
sourceGatewayContext = SourceGatewayContext({
vault: IVault(_settings.vault),
assetAmount: _assetAmount
});
IGateway(_settings.gateway).sendMessage{ value: messageFee }(
_action.targetChainId,
_messageData,
_action.gatewaySettings
);
delete sourceGatewayContext;
}
function _emitActionSourceEvent(
uint256 _actionId,
Action calldata _action,
uint256 _amount,
uint256 _fee
) private {
emit ActionSource(
_actionId,
_action.targetChainId,
msg.sender,
_action.targetRecipient,
_action.gatewayType,
_action.sourceTokenAddress,
_action.targetTokenAddress,
_amount,
_fee,
block.timestamp
);
}
function _checkSwapAmountLimits(
uint256 _normalizedAmount,
uint256 _swapAmountMin,
uint256 _swapAmountMax
) private pure {
if (_normalizedAmount < _swapAmountMin) {
revert SwapAmountMinError();
}
if (_normalizedAmount > _swapAmountMax) {
revert SwapAmountMaxError();
}
}
function _calculateLocalAmount(
uint256 _fromAmount,
bool _isForward,
uint256 _systemFeeLocal,
bool _isWhitelist
) private pure returns (uint256 result) {
if (_isWhitelist || _systemFeeLocal == 0) {
return _fromAmount;
}
return
_isForward
? (_fromAmount * (Constants.MILLIPERCENT_FACTOR - _systemFeeLocal)) /
Constants.MILLIPERCENT_FACTOR
: (_fromAmount * Constants.MILLIPERCENT_FACTOR) /
(Constants.MILLIPERCENT_FACTOR - _systemFeeLocal);
}
function _calculateVaultAmount(
uint256 _fromDecimals,
uint256 _toDecimals,
uint256 _fromAmount,
bool _isForward,
uint256 _systemFee,
bool _isWhitelist
) private pure returns (uint256 result) {
bool isZeroFee = _isWhitelist || _systemFee == 0;
uint256 amountToConvert = (!_isForward || isZeroFee)
? _fromAmount
: (_fromAmount * (Constants.MILLIPERCENT_FACTOR - _systemFee)) /
Constants.MILLIPERCENT_FACTOR;
uint256 convertedAmount = DecimalsHelper.convertDecimals(
_fromDecimals,
_toDecimals,
amountToConvert
);
result = (_isForward || isZeroFee)
? convertedAmount
: (convertedAmount * Constants.MILLIPERCENT_FACTOR) /
(Constants.MILLIPERCENT_FACTOR - _systemFee);
}
function _blankMessage(bytes memory _targetRouterData) private pure returns (bytes memory) {
bytes memory messageData = abi.encode(
TargetMessage({
actionId: uint256(0),
sourceSender: address(0),
vaultType: uint256(0),
targetTokenAddress: address(0),
targetSwapInfo: SwapInfo({
fromAmount: uint256(0),
routerType: uint256(0),
routerData: _targetRouterData
}),
targetRecipient: address(0)
})
);
return messageData;
}
function _blankLocalAction() private pure returns (LocalAction memory) {
return
LocalAction({
fromTokenAddress: address(0),
toTokenAddress: address(0),
swapInfo: SwapInfo({ fromAmount: 0, routerType: 0, routerData: '' }),
recipient: address(0)
});
}
}
文件 2 的 27:AddressHelper.sol
pragma solidity 0.8.19;
error NonContractAddressError(address account);
function isContract(address _account) view returns (bool) {
return _account.code.length > 0;
}
function requireContract(address _account) view {
if (!isContract(_account)) {
revert NonContractAddressError(_account);
}
}
function requireContractOrZeroAddress(address _account) view {
if (_account != address(0)) {
requireContract(_account);
}
}
文件 3 的 27:BalanceManagement.sol
pragma solidity 0.8.19;
import { ITokenBalance } from './interfaces/ITokenBalance.sol';
import { ManagerRole } from './roles/ManagerRole.sol';
import './helpers/TransferHelper.sol' as TransferHelper;
import './Constants.sol' as Constants;
abstract contract BalanceManagement is ManagerRole {
error ReservedTokenError();
function cleanup(address _tokenAddress, uint256 _tokenAmount) external onlyManager {
if (isReservedToken(_tokenAddress)) {
revert ReservedTokenError();
}
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
TransferHelper.safeTransferNative(msg.sender, _tokenAmount);
} else {
TransferHelper.safeTransfer(_tokenAddress, msg.sender, _tokenAmount);
}
}
function tokenBalance(address _tokenAddress) public view returns (uint256) {
if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
return address(this).balance;
} else {
return ITokenBalance(_tokenAddress).balanceOf(address(this));
}
}
function isReservedToken(address _tokenAddress) public view virtual returns (bool) {
}
}
文件 4 的 27:CallerGuard.sol
pragma solidity 0.8.19;
import { ManagerRole } from './roles/ManagerRole.sol';
import './helpers/AddressHelper.sol' as AddressHelper;
import './Constants.sol' as Constants;
import './DataStructures.sol' as DataStructures;
abstract contract CallerGuard is ManagerRole {
enum CallerGuardMode {
ContractForbidden,
ContractList,
ContractAllowed
}
CallerGuardMode public callerGuardMode = CallerGuardMode.ContractForbidden;
address[] public listedCallerGuardContractList;
mapping(address => DataStructures.OptionalValue )
public listedCallerGuardContractIndexMap;
event SetCallerGuardMode(CallerGuardMode indexed callerGuardMode);
event SetListedCallerGuardContract(address indexed contractAddress, bool indexed isListed);
error CallerGuardError(address caller);
modifier checkCaller() {
if (msg.sender != tx.origin) {
bool condition = (callerGuardMode == CallerGuardMode.ContractAllowed ||
(callerGuardMode == CallerGuardMode.ContractList &&
isListedCallerGuardContract(msg.sender)));
if (!condition) {
revert CallerGuardError(msg.sender);
}
}
_;
}
function setCallerGuardMode(CallerGuardMode _callerGuardMode) external onlyManager {
callerGuardMode = _callerGuardMode;
emit SetCallerGuardMode(_callerGuardMode);
}
function setListedCallerGuardContracts(
DataStructures.AccountToFlag[] calldata _items
) external onlyManager {
for (uint256 index; index < _items.length; index++) {
DataStructures.AccountToFlag calldata item = _items[index];
if (item.flag) {
AddressHelper.requireContract(item.account);
}
DataStructures.uniqueAddressListUpdate(
listedCallerGuardContractList,
listedCallerGuardContractIndexMap,
item.account,
item.flag,
Constants.LIST_SIZE_LIMIT_DEFAULT
);
emit SetListedCallerGuardContract(item.account, item.flag);
}
}
function listedCallerGuardContractCount() external view returns (uint256) {
return listedCallerGuardContractList.length;
}
function fullListedCallerGuardContractList() external view returns (address[] memory) {
return listedCallerGuardContractList;
}
function isListedCallerGuardContract(address _account) public view returns (bool) {
return listedCallerGuardContractIndexMap[_account].isSet;
}
}
文件 5 的 27:Constants.sol
pragma solidity 0.8.19;
uint256 constant DECIMALS_DEFAULT = 18;
uint256 constant INFINITY = type(uint256).max;
uint256 constant LIST_SIZE_LIMIT_DEFAULT = 100;
uint256 constant LIST_SIZE_LIMIT_ROUTERS = 200;
uint256 constant MILLIPERCENT_FACTOR = 100_000;
address constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
文件 6 的 27: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;
}
}
文件 7 的 27:DataStructures.sol
pragma solidity 0.8.19;
struct OptionalValue {
bool isSet;
uint256 value;
}
struct KeyToValue {
uint256 key;
uint256 value;
}
struct KeyToAddressValue {
uint256 key;
address value;
}
struct AccountToFlag {
address account;
bool flag;
}
error ListSizeLimitError();
function combinedMapSet(
mapping(uint256 => address) storage _map,
uint256[] storage _keyList,
mapping(uint256 => OptionalValue) storage _keyIndexMap,
uint256 _key,
address _value,
uint256 _sizeLimit
) returns (bool isNewKey) {
isNewKey = !_keyIndexMap[_key].isSet;
if (isNewKey) {
uniqueListAdd(_keyList, _keyIndexMap, _key, _sizeLimit);
}
_map[_key] = _value;
}
function combinedMapRemove(
mapping(uint256 => address) storage _map,
uint256[] storage _keyList,
mapping(uint256 => OptionalValue) storage _keyIndexMap,
uint256 _key
) returns (bool isChanged) {
isChanged = _keyIndexMap[_key].isSet;
if (isChanged) {
delete _map[_key];
uniqueListRemove(_keyList, _keyIndexMap, _key);
}
}
function uniqueListAdd(
uint256[] storage _list,
mapping(uint256 => OptionalValue) storage _indexMap,
uint256 _value,
uint256 _sizeLimit
) returns (bool isChanged) {
isChanged = !_indexMap[_value].isSet;
if (isChanged) {
if (_list.length >= _sizeLimit) {
revert ListSizeLimitError();
}
_indexMap[_value] = OptionalValue(true, _list.length);
_list.push(_value);
}
}
function uniqueListRemove(
uint256[] storage _list,
mapping(uint256 => OptionalValue) storage _indexMap,
uint256 _value
) returns (bool isChanged) {
OptionalValue storage indexItem = _indexMap[_value];
isChanged = indexItem.isSet;
if (isChanged) {
uint256 itemIndex = indexItem.value;
uint256 lastIndex = _list.length - 1;
if (itemIndex != lastIndex) {
uint256 lastValue = _list[lastIndex];
_list[itemIndex] = lastValue;
_indexMap[lastValue].value = itemIndex;
}
_list.pop();
delete _indexMap[_value];
}
}
function uniqueAddressListAdd(
address[] storage _list,
mapping(address => OptionalValue) storage _indexMap,
address _value,
uint256 _sizeLimit
) returns (bool isChanged) {
isChanged = !_indexMap[_value].isSet;
if (isChanged) {
if (_list.length >= _sizeLimit) {
revert ListSizeLimitError();
}
_indexMap[_value] = OptionalValue(true, _list.length);
_list.push(_value);
}
}
function uniqueAddressListRemove(
address[] storage _list,
mapping(address => OptionalValue) storage _indexMap,
address _value
) returns (bool isChanged) {
OptionalValue storage indexItem = _indexMap[_value];
isChanged = indexItem.isSet;
if (isChanged) {
uint256 itemIndex = indexItem.value;
uint256 lastIndex = _list.length - 1;
if (itemIndex != lastIndex) {
address lastValue = _list[lastIndex];
_list[itemIndex] = lastValue;
_indexMap[lastValue].value = itemIndex;
}
_list.pop();
delete _indexMap[_value];
}
}
function uniqueAddressListUpdate(
address[] storage _list,
mapping(address => OptionalValue) storage _indexMap,
address _value,
bool _flag,
uint256 _sizeLimit
) returns (bool isChanged) {
return
_flag
? uniqueAddressListAdd(_list, _indexMap, _value, _sizeLimit)
: uniqueAddressListRemove(_list, _indexMap, _value);
}
文件 8 的 27:DecimalsHelper.sol
pragma solidity 0.8.19;
function convertDecimals(
uint256 _fromDecimals,
uint256 _toDecimals,
uint256 _fromAmount
) pure returns (uint256) {
if (_toDecimals == _fromDecimals) {
return _fromAmount;
} else if (_toDecimals > _fromDecimals) {
return _fromAmount * 10 ** (_toDecimals - _fromDecimals);
} else {
return _fromAmount / 10 ** (_fromDecimals - _toDecimals);
}
}
文件 9 的 27:Errors.sol
pragma solidity 0.8.19;
error TokenBurnError();
error TokenMintError();
error ZeroAddressError();
文件 10 的 27:GasReserveHelper.sol
pragma solidity 0.8.19;
function checkGasReserve(
uint256 _gasReserve
) view returns (bool hasGasReserve, uint256 gasAllowed) {
uint256 gasLeft = gasleft();
hasGasReserve = gasLeft >= _gasReserve;
gasAllowed = hasGasReserve ? gasLeft - _gasReserve : 0;
}
文件 11 的 27:IActionDataStructures.sol
pragma solidity 0.8.19;
interface IActionDataStructures {
struct LocalAction {
address fromTokenAddress;
address toTokenAddress;
SwapInfo swapInfo;
address recipient;
}
struct Action {
uint256 gatewayType;
uint256 vaultType;
address sourceTokenAddress;
SwapInfo sourceSwapInfo;
uint256 targetChainId;
address targetTokenAddress;
SwapInfo[] targetSwapInfoOptions;
address targetRecipient;
bytes gatewaySettings;
}
struct SwapInfo {
uint256 fromAmount;
uint256 routerType;
bytes routerData;
}
struct TargetMessage {
uint256 actionId;
address sourceSender;
uint256 vaultType;
address targetTokenAddress;
SwapInfo targetSwapInfo;
address targetRecipient;
}
}
文件 12 的 27:IGateway.sol
pragma solidity 0.8.19;
interface IGateway {
function sendMessage(
uint256 _targetChainId,
bytes calldata _message,
bytes calldata _settings
) external payable;
function messageFee(
uint256 _targetChainId,
bytes calldata _message,
bytes calldata _settings
) external view returns (uint256);
}
文件 13 的 27:IGatewayClient.sol
pragma solidity 0.8.19;
import { IVault } from '../../interfaces/IVault.sol';
interface IGatewayClient {
receive() external payable;
function handleExecutionPayload(
uint256 _messageSourceChainId,
bytes calldata _payloadData
) external;
function getSourceGatewayContext() external view returns (IVault vault, uint256 assetAmount);
}
文件 14 的 27:IRegistry.sol
pragma solidity 0.8.19;
import { ISettings } from './ISettings.sol';
interface IRegistry is ISettings {
function isGatewayAddress(address _account) external view returns (bool);
function localSettings(
address _caller,
uint256 _routerType
) external view returns (LocalSettings memory);
function sourceSettings(
address _caller,
uint256 _targetChainId,
uint256 _gatewayType,
uint256 _routerType,
uint256 _vaultType
) external view returns (SourceSettings memory);
function targetSettings(
uint256 _vaultType,
uint256 _routerType
) external view returns (TargetSettings memory);
function variableBalanceRepaymentSettings(
uint256 _vaultType
) external view returns (VariableBalanceRepaymentSettings memory);
function messageFeeEstimateSettings(
uint256 _gatewayType
) external view returns (MessageFeeEstimateSettings memory);
function localAmountCalculationSettings(
address _caller
) external view returns (LocalAmountCalculationSettings memory);
function vaultAmountCalculationSettings(
address _caller,
uint256 _vaultType,
uint256 _fromChainId,
uint256 _toChainId
) external view returns (VaultAmountCalculationSettings memory);
function swapAmountLimits(uint256 _vaultType) external view returns (uint256 min, uint256 max);
}
文件 15 的 27:ISettings.sol
pragma solidity 0.8.19;
interface ISettings {
struct LocalSettings {
address router;
address routerTransfer;
uint256 systemFeeLocal;
address feeCollectorLocal;
bool isWhitelist;
}
struct SourceSettings {
address gateway;
address router;
address routerTransfer;
address vault;
uint256 sourceVaultDecimals;
uint256 targetVaultDecimals;
uint256 systemFee;
address feeCollector;
bool isWhitelist;
uint256 swapAmountMin;
uint256 swapAmountMax;
}
struct TargetSettings {
address router;
address routerTransfer;
address vault;
uint256 gasReserve;
}
struct VariableBalanceRepaymentSettings {
address vault;
}
struct MessageFeeEstimateSettings {
address gateway;
}
struct LocalAmountCalculationSettings {
uint256 systemFeeLocal;
bool isWhitelist;
}
struct VaultAmountCalculationSettings {
uint256 fromDecimals;
uint256 toDecimals;
uint256 systemFee;
bool isWhitelist;
}
}
文件 16 的 27:ITokenBalance.sol
pragma solidity 0.8.19;
interface ITokenBalance {
function balanceOf(address _account) external view returns (uint256);
}
文件 17 的 27:ITokenMint.sol
pragma solidity 0.8.19;
interface ITokenMint {
function mint(address _to, uint256 _amount) external returns (bool);
}
文件 18 的 27:IVariableBalanceRecords.sol
pragma solidity 0.8.19;
interface IVariableBalanceRecords {
function increaseBalance(address _account, uint256 _vaultType, uint256 _amount) external;
function clearBalance(address _account, uint256 _vaultType) external;
function getAccountBalance(
address _account,
uint256 _vaultType
) external view returns (uint256);
}
文件 19 的 27:IVault.sol
pragma solidity 0.8.19;
interface IVault {
function asset() external view returns (address);
function checkVariableTokenState() external view returns (address);
function requestAsset(
uint256 _amount,
address _to,
bool _forVariableBalance
) external returns (address assetAddress);
}
文件 20 的 27:ManagerRole.sol
pragma solidity 0.8.19;
import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol';
import { RoleBearers } from './RoleBearers.sol';
abstract contract ManagerRole is Ownable, RoleBearers {
bytes32 private constant ROLE_KEY = keccak256('Manager');
event SetManager(address indexed account, bool indexed value);
event RenounceManagerRole(address indexed account);
error OnlyManagerError();
modifier onlyManager() {
if (!isManager(msg.sender)) {
revert OnlyManagerError();
}
_;
}
function setManager(address _account, bool _value) public onlyOwner {
_setRoleBearer(ROLE_KEY, _account, _value);
emit SetManager(_account, _value);
}
function renounceManagerRole() external onlyManager {
_setRoleBearer(ROLE_KEY, msg.sender, false);
emit RenounceManagerRole(msg.sender);
}
function managerCount() external view returns (uint256) {
return _roleBearerCount(ROLE_KEY);
}
function fullManagerList() external view returns (address[] memory) {
return _fullRoleBearerList(ROLE_KEY);
}
function isManager(address _account) public view returns (bool) {
return _isRoleBearer(ROLE_KEY, _account);
}
function _initRoles(
address _owner,
address[] memory _managers,
bool _addOwnerToManagers
) internal {
address ownerAddress = _owner == address(0) ? msg.sender : _owner;
for (uint256 index; index < _managers.length; index++) {
setManager(_managers[index], true);
}
if (_addOwnerToManagers && !isManager(ownerAddress)) {
setManager(ownerAddress, true);
}
if (ownerAddress != msg.sender) {
transferOwnership(ownerAddress);
}
}
}
文件 21 的 27: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);
}
}
文件 22 的 27:Pausable.sol
pragma solidity 0.8.19;
import { Pausable as PausableBase } from '@openzeppelin/contracts/security/Pausable.sol';
import { ManagerRole } from './roles/ManagerRole.sol';
abstract contract Pausable is PausableBase, ManagerRole {
function pause() external onlyManager whenNotPaused {
_pause();
}
function unpause() external onlyManager whenPaused {
_unpause();
}
}
文件 23 的 27: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;
}
}
文件 24 的 27:RefundHelper.sol
pragma solidity 0.8.19;
import './TransferHelper.sol' as TransferHelper;
function refundExtraBalance(address _self, uint256 _expectedBalance, address payable _to) {
uint256 extraBalance = _self.balance - _expectedBalance;
if (extraBalance > 0) {
TransferHelper.safeTransferNative(_to, extraBalance);
}
}
文件 25 的 27:RoleBearers.sol
pragma solidity 0.8.19;
import '../Constants.sol' as Constants;
import '../DataStructures.sol' as DataStructures;
abstract contract RoleBearers {
mapping(bytes32 => address[] ) private roleBearerTable;
mapping(bytes32 => mapping(address => DataStructures.OptionalValue ))
private roleBearerIndexTable;
function _setRoleBearer(bytes32 _roleKey, address _account, bool _value) internal {
DataStructures.uniqueAddressListUpdate(
roleBearerTable[_roleKey],
roleBearerIndexTable[_roleKey],
_account,
_value,
Constants.LIST_SIZE_LIMIT_DEFAULT
);
}
function _isRoleBearer(bytes32 _roleKey, address _account) internal view returns (bool) {
return roleBearerIndexTable[_roleKey][_account].isSet;
}
function _roleBearerCount(bytes32 _roleKey) internal view returns (uint256) {
return roleBearerTable[_roleKey].length;
}
function _fullRoleBearerList(bytes32 _roleKey) internal view returns (address[] memory) {
return roleBearerTable[_roleKey];
}
}
文件 26 的 27:SystemVersionId.sol
pragma solidity 0.8.19;
abstract contract SystemVersionId {
uint256 public constant SYSTEM_VERSION_ID = uint256(keccak256('Circle CCTP - 2023-06-24'));
}
文件 27 的 27:TransferHelper.sol
pragma solidity 0.8.19;
error SafeApproveError();
error SafeTransferError();
error SafeTransferFromError();
error SafeTransferNativeError();
function safeApprove(address _token, address _to, uint256 _value) {
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0x095ea7b3, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeApproveError();
}
}
function safeTransfer(address _token, address _to, uint256 _value) {
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0xa9059cbb, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeTransferError();
}
}
function safeTransferFrom(address _token, address _from, address _to, uint256 _value) {
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(0x23b872dd, _from, _to, _value)
);
bool condition = success && (data.length == 0 || abi.decode(data, (bool)));
if (!condition) {
revert SafeTransferFromError();
}
}
function safeTransferNative(address _to, uint256 _value) {
(bool success, ) = _to.call{ value: _value }(new bytes(0));
if (!success) {
revert SafeTransferNativeError();
}
}
{
"compilationTarget": {
"contracts/ActionExecutor.sol": "ActionExecutor"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IRegistry","name":"_registry","type":"address"},{"internalType":"contract IVariableBalanceRecords","name":"_variableBalanceRecords","type":"address"},{"internalType":"uint256","name":"_actionIdOffset","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool","name":"_addOwnerToManagers","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerGuardError","type":"error"},{"inputs":[],"name":"GatewayNotSetError","type":"error"},{"inputs":[],"name":"ListSizeLimitError","type":"error"},{"inputs":[],"name":"MessageFeeError","type":"error"},{"inputs":[],"name":"NativeTokenValueError","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonContractAddressError","type":"error"},{"inputs":[],"name":"OnlyGatewayError","type":"error"},{"inputs":[],"name":"OnlyManagerError","type":"error"},{"inputs":[],"name":"OnlySelfError","type":"error"},{"inputs":[],"name":"ReservedTokenError","type":"error"},{"inputs":[],"name":"RouterNotSetError","type":"error"},{"inputs":[],"name":"SafeApproveError","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferFromError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"inputs":[],"name":"SameChainIdError","type":"error"},{"inputs":[],"name":"SameTokenError","type":"error"},{"inputs":[],"name":"SwapAmountMaxError","type":"error"},{"inputs":[],"name":"SwapAmountMinError","type":"error"},{"inputs":[],"name":"SwapError","type":"error"},{"inputs":[],"name":"TargetSwapInfoError","type":"error"},{"inputs":[],"name":"TokenMintError","type":"error"},{"inputs":[],"name":"VariableBalanceSwapAmountError","type":"error"},{"inputs":[],"name":"VariableBalanceSwapTokenError","type":"error"},{"inputs":[],"name":"VaultNotSetError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"fromToken","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ActionLocal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"targetChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sourceSender","type":"address"},{"indexed":false,"internalType":"address","name":"targetRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"gatewayType","type":"uint256"},{"indexed":false,"internalType":"address","name":"sourceToken","type":"address"},{"indexed":false,"internalType":"address","name":"targetToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ActionSource","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"isSuccess","type":"bool"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ActionTarget","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":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RenounceManagerRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum CallerGuard.CallerGuardMode","name":"callerGuardMode","type":"uint8"}],"name":"SetCallerGuardMode","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"bool","name":"isListed","type":"bool"}],"name":"SetListedCallerGuardContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registryAddress","type":"address"}],"name":"SetRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recordsAddress","type":"address"}],"name":"SetVariableBalanceRecords","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"isLocal","type":"bool"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"routerType","type":"uint256"},{"indexed":false,"internalType":"address","name":"fromTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"toTokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"resultAmount","type":"uint256"}],"name":"SourceProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"routerType","type":"uint256"},{"indexed":false,"internalType":"address","name":"fromTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"toTokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"resultAmount","type":"uint256"}],"name":"TargetProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VariableBalanceAllocated","type":"event"},{"inputs":[],"name":"SYSTEM_VERSION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromAmount","type":"uint256"},{"internalType":"bool","name":"_isForward","type":"bool"}],"name":"calculateLocalAmount","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromAmount","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"calculateLocalAmountFromVariableBalance","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultType","type":"uint256"},{"internalType":"uint256","name":"_fromChainId","type":"uint256"},{"internalType":"uint256","name":"_toChainId","type":"uint256"},{"internalType":"uint256","name":"_fromAmount","type":"uint256"},{"internalType":"bool","name":"_isForward","type":"bool"}],"name":"calculateVaultAmount","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callerGuardMode","outputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultType","type":"uint256"}],"name":"claimVariableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultType","type":"uint256"}],"name":"convertVariableBalanceToVaultAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultType","type":"uint256"},{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo","name":"swapInfo","type":"tuple"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IActionDataStructures.LocalAction","name":"_localAction","type":"tuple"}],"name":"convertVariableBalanceWithSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"gatewayType","type":"uint256"},{"internalType":"uint256","name":"vaultType","type":"uint256"},{"internalType":"address","name":"sourceTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo","name":"sourceSwapInfo","type":"tuple"},{"internalType":"uint256","name":"targetChainId","type":"uint256"},{"internalType":"address","name":"targetTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo[]","name":"targetSwapInfoOptions","type":"tuple[]"},{"internalType":"address","name":"targetRecipient","type":"address"},{"internalType":"bytes","name":"gatewaySettings","type":"bytes"}],"internalType":"struct IActionDataStructures.Action","name":"_action","type":"tuple"}],"name":"execute","outputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo","name":"swapInfo","type":"tuple"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IActionDataStructures.LocalAction","name":"_localAction","type":"tuple"}],"name":"executeLocal","outputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"fullListedCallerGuardContractList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullManagerList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSourceGatewayContext","outputs":[{"internalType":"contract IVault","name":"vault","type":"address"},{"internalType":"uint256","name":"assetAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_messageSourceChainId","type":"uint256"},{"internalType":"bytes","name":"_payloadData","type":"bytes"}],"name":"handleExecutionPayload","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isListedCallerGuardContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"isReservedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listedCallerGuardContractCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"listedCallerGuardContractIndexMap","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"listedCallerGuardContractList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gatewayType","type":"uint256"},{"internalType":"uint256","name":"_targetChainId","type":"uint256"},{"internalType":"bytes[]","name":"_targetRouterDataOptions","type":"bytes[]"},{"internalType":"bytes","name":"_gatewaySettings","type":"bytes"}],"name":"messageFeeEstimate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"routerTransfer","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"gasReserve","type":"uint256"}],"internalType":"struct ISettings.TargetSettings","name":"_settings","type":"tuple"},{"components":[{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"address","name":"sourceSender","type":"address"},{"internalType":"uint256","name":"vaultType","type":"uint256"},{"internalType":"address","name":"targetTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo","name":"targetSwapInfo","type":"tuple"},{"internalType":"address","name":"targetRecipient","type":"address"}],"internalType":"struct IActionDataStructures.TargetMessage","name":"_targetMessage","type":"tuple"}],"name":"selfCallTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"_callerGuardMode","type":"uint8"}],"name":"setCallerGuardMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"flag","type":"bool"}],"internalType":"struct AccountToFlag[]","name":"_items","type":"tuple[]"}],"name":"setListedCallerGuardContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRegistry","name":"_registry","type":"address"}],"name":"setRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"tokenBalance","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":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_vaultType","type":"uint256"}],"name":"variableBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"variableBalanceRecords","outputs":[{"internalType":"contract IVariableBalanceRecords","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]