编译器
0.8.19+commit.7dd6d404
文件 1 的 29: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);
}
}
文件 2 的 29:AssetSpenderRole.sol
pragma solidity 0.8.19;
import { RoleBearers } from './RoleBearers.sol';
abstract contract AssetSpenderRole is RoleBearers {
bytes32 private constant ROLE_KEY = keccak256('AssetSpender');
event SetAssetSpender(address indexed account, bool indexed value);
error OnlyAssetSpenderError();
modifier onlyAssetSpender() {
if (!isAssetSpender(msg.sender)) {
revert OnlyAssetSpenderError();
}
_;
}
function assetSpenderCount() external view returns (uint256) {
return _roleBearerCount(ROLE_KEY);
}
function fullAssetSpenderList() external view returns (address[] memory) {
return _fullRoleBearerList(ROLE_KEY);
}
function isAssetSpender(address _account) public view returns (bool) {
return _isRoleBearer(ROLE_KEY, _account);
}
function _setAssetSpender(address _account, bool _value) internal {
_setRoleBearer(ROLE_KEY, _account, _value);
emit SetAssetSpender(_account, _value);
}
}
文件 3 的 29: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 的 29: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 的 29:CircleCctpGateway.sol
pragma solidity 0.8.19;
import { IActionDataStructures } from '../../interfaces/IActionDataStructures.sol';
import { IMessageHandler } from './interfaces/IMessageHandler.sol';
import { IMessageTransmitter } from './interfaces/IMessageTransmitter.sol';
import { ITokenBalance } from '../../interfaces/ITokenBalance.sol';
import { ITokenMessenger } from './interfaces/ITokenMessenger.sol';
import { IVault } from '../../interfaces/IVault.sol';
import { AssetSpenderRole } from '../../roles/AssetSpenderRole.sol';
import { CallerGuard } from '../../CallerGuard.sol';
import { GatewayBase } from '../GatewayBase.sol';
import { SystemVersionId } from '../../SystemVersionId.sol';
import '../../helpers/GasReserveHelper.sol' as GasReserveHelper;
import '../../helpers/TransferHelper.sol' as TransferHelper;
import '../../DataStructures.sol' as DataStructures;
contract CircleCctpGateway is
SystemVersionId,
GatewayBase,
CallerGuard,
AssetSpenderRole,
IActionDataStructures,
IVault,
IMessageHandler
{
struct ChainDomain {
uint256 chainId;
uint32 domain;
}
struct SendMessageVariables {
bytes32 peerAddressBytes32;
uint32 targetDomain;
uint64 assetMessageNonce;
uint64 dataMessageNonce;
bool useTargetExecutor;
}
struct MessageHandlerContext {
address caller;
uint256 assetReceived;
}
ITokenMessenger public immutable cctpTokenMessenger;
IMessageTransmitter public immutable cctpMessageTransmitter;
address public immutable asset;
mapping(uint256 => DataStructures.OptionalValue ) public chainIdToDomain;
mapping(uint32 => uint256 ) public domainToChainId;
bool public variableRepaymentEnabled;
address public processingFeeCollector;
address public targetExecutor;
MessageHandlerContext private messageHandlerContext;
event SetChainDomain(uint256 indexed chainId, uint32 indexed domain);
event RemoveChainDomain(uint256 indexed chainId, uint32 indexed domain);
event SetVariableRepaymentEnabled(bool indexed variableRepaymentEnabled);
event SetProcessingFeeCollector(address indexed processingFeeCollector);
event SetTargetExecutor(address indexed targetExecutor);
event TargetCctpMessageFailure(uint256 indexed sourceChainId);
event GatewayActionSource(
uint256 indexed actionId,
uint256 indexed targetChainId,
bool indexed useTargetExecutor,
uint64 assetMessageNonce,
uint64 dataMessageNonce,
uint256 assetAmount,
uint256 processingFee,
uint256 processingGas,
uint256 timestamp
);
error DomainNotSetError();
error ExecutorError();
error ProcessingFeeError();
error VariableRepaymentNotEnabledError();
error VariableTokenNotSetError();
error OnlyCurrentVaultError();
error OnlyMessageTransmitterError();
error TargetClientNotSetError();
error AssetMessageError();
error DataMessageError();
error TargetFromAddressError(uint256 sourceChainId, address fromAddress);
error TargetCallerError();
error TargetAssetAmountMismatchError();
error TargetGasReserveError();
modifier onlyMessageTransmitter() {
if (msg.sender != address(cctpMessageTransmitter)) {
revert OnlyMessageTransmitterError();
}
_;
}
constructor(
ITokenMessenger _cctpTokenMessenger,
IMessageTransmitter _cctpMessageTransmitter,
ChainDomain[] memory _chainDomains,
address _asset,
bool _variableRepaymentEnabled,
uint256 _targetGasReserve,
address _processingFeeCollector,
address _targetExecutor,
address _owner,
address[] memory _managers,
bool _addOwnerToManagers
) {
cctpTokenMessenger = _cctpTokenMessenger;
cctpMessageTransmitter = _cctpMessageTransmitter;
for (uint256 index; index < _chainDomains.length; index++) {
ChainDomain memory chainDomain = _chainDomains[index];
_setChainDomain(chainDomain.chainId, chainDomain.domain);
}
asset = _asset;
_setVariableRepaymentEnabled(_variableRepaymentEnabled);
_setTargetGasReserve(_targetGasReserve);
_setProcessingFeeCollector(_processingFeeCollector);
_setTargetExecutor(_targetExecutor);
_initRoles(_owner, _managers, _addOwnerToManagers);
}
receive() external payable {}
function setAssetSpender(address _account, bool _value) external onlyManager {
_setAssetSpender(_account, _value);
}
function setChainDomains(ChainDomain[] calldata _chainDomains) external onlyManager {
for (uint256 index; index < _chainDomains.length; index++) {
ChainDomain calldata chainDomain = _chainDomains[index];
_setChainDomain(chainDomain.chainId, chainDomain.domain);
}
}
function removeChainDomains(uint256[] calldata _chainIds) external onlyManager {
for (uint256 index; index < _chainIds.length; index++) {
uint256 chainId = _chainIds[index];
_removeChainDomain(chainId);
}
}
function setProcessingFeeCollector(address _processingFeeCollector) external onlyManager {
_setProcessingFeeCollector(_processingFeeCollector);
}
function setTargetExecutor(address _targetExecutor) external onlyManager {
_setTargetExecutor(_targetExecutor);
}
function sendMessage(
uint256 _targetChainId,
bytes calldata _message,
bytes calldata _settings
) external payable onlyClient whenNotPaused {
(IVault vault, uint256 assetAmount) = client.getSourceGatewayContext();
if (address(vault) != address(this)) {
revert OnlyCurrentVaultError();
}
SendMessageVariables memory variables = _prepareSendMessageVariables();
variables.peerAddressBytes32 = _addressToBytes32(_checkPeerAddress(_targetChainId));
variables.targetDomain = _checkTargetDomain(_targetChainId);
uint256 processingFee;
uint256 processingGas;
(variables.useTargetExecutor, processingFee, processingGas) = _decodeSettings(_settings);
if (msg.value < processingFee) {
revert ProcessingFeeError();
}
if (processingFee > 0 && processingFeeCollector != address(0)) {
TransferHelper.safeTransferNative(processingFeeCollector, processingFee);
}
TargetMessage memory targetMessage = abi.decode(_message, (TargetMessage));
TransferHelper.safeApprove(asset, address(cctpTokenMessenger), assetAmount);
variables.assetMessageNonce = cctpTokenMessenger.depositForBurnWithCaller(
assetAmount,
variables.targetDomain,
variables.peerAddressBytes32,
asset,
variables.peerAddressBytes32
);
TransferHelper.safeApprove(asset, address(cctpTokenMessenger), 0);
variables.dataMessageNonce = cctpMessageTransmitter.sendMessageWithCaller(
variables.targetDomain,
variables.peerAddressBytes32,
variables.peerAddressBytes32,
_message
);
emit GatewayActionSource(
targetMessage.actionId,
_targetChainId,
variables.useTargetExecutor,
variables.assetMessageNonce,
variables.dataMessageNonce,
assetAmount,
processingFee,
processingGas,
block.timestamp
);
}
function executeTarget(
bytes calldata _assetMessage,
bytes calldata _assetAttestation,
bytes calldata _dataMessage,
bytes calldata _dataAttestation
) external whenNotPaused nonReentrant checkCaller {
if (address(client) == address(0)) {
revert TargetClientNotSetError();
}
uint256 assetBalanceBefore = tokenBalance(asset);
bool assetMessageSuccess = cctpMessageTransmitter.receiveMessage(
_assetMessage,
_assetAttestation
);
if (!assetMessageSuccess) {
revert AssetMessageError();
}
messageHandlerContext = MessageHandlerContext({
caller: msg.sender,
assetReceived: tokenBalance(asset) - assetBalanceBefore
});
bool dataMessageSuccess = cctpMessageTransmitter.receiveMessage(
_dataMessage,
_dataAttestation
);
if (!dataMessageSuccess) {
revert DataMessageError();
}
delete messageHandlerContext;
}
function handleReceiveMessage(
uint32 _sourceDomain,
bytes32 _sender,
bytes calldata _messageBody
) external whenNotPaused onlyMessageTransmitter returns (bool) {
uint256 sourceChainId = domainToChainId[_sourceDomain];
address fromAddress = _bytes32ToAddress(_sender);
{
bool fromAddressCondition = sourceChainId != 0 &&
fromAddress != address(0) &&
fromAddress == peerMap[sourceChainId];
if (!fromAddressCondition) {
revert TargetFromAddressError(sourceChainId, fromAddress);
}
}
TargetMessage memory targetMessage = abi.decode(_messageBody, (TargetMessage));
{
address caller = messageHandlerContext.caller;
bool targetCallerCondition = caller == targetExecutor ||
caller == targetMessage.sourceSender ||
caller == targetMessage.targetRecipient;
if (!targetCallerCondition) {
revert TargetCallerError();
}
}
if (targetMessage.targetSwapInfo.fromAmount != messageHandlerContext.assetReceived) {
revert TargetAssetAmountMismatchError();
}
(bool hasGasReserve, uint256 gasAllowed) = GasReserveHelper.checkGasReserve(
targetGasReserve
);
if (!hasGasReserve) {
revert TargetGasReserveError();
}
client.handleExecutionPayload{ gas: gasAllowed }(sourceChainId, _messageBody);
return true;
}
function extractCctpAsset(
bytes calldata _assetMessage,
bytes calldata _assetAttestation,
address _to
) external onlyManager {
uint256 tokenBalanceBefore = ITokenBalance(asset).balanceOf(address(this));
cctpMessageTransmitter.receiveMessage(_assetMessage, _assetAttestation);
uint256 tokenAmount = ITokenBalance(asset).balanceOf(address(this)) - tokenBalanceBefore;
if (tokenAmount > 0 && _to != address(this)) {
TransferHelper.safeTransfer(asset, _to, tokenAmount);
}
}
function requestAsset(
uint256 _amount,
address _to,
bool _forVariableBalance
) external whenNotPaused onlyAssetSpender returns (address assetAddress) {
if (_forVariableBalance && !variableRepaymentEnabled) {
revert VariableRepaymentNotEnabledError();
}
TransferHelper.safeTransfer(asset, _to, _amount);
return asset;
}
function messageFee(
uint256 ,
bytes calldata ,
bytes calldata _settings
) external pure returns (uint256) {
(, uint256 processingFee, ) = _decodeSettings(_settings);
return processingFee;
}
function checkVariableTokenState() external view returns (address) {
if (!variableRepaymentEnabled) {
revert VariableRepaymentNotEnabledError();
}
revert VariableTokenNotSetError();
}
function _setChainDomain(uint256 _chainId, uint32 _domain) private {
DataStructures.OptionalValue storage previousDomainEntry = chainIdToDomain[_chainId];
if (previousDomainEntry.isSet) {
delete domainToChainId[uint32(previousDomainEntry.value)];
}
chainIdToDomain[_chainId] = DataStructures.OptionalValue({ isSet: true, value: _domain });
domainToChainId[_domain] = _chainId;
emit SetChainDomain(_chainId, _domain);
}
function _removeChainDomain(uint256 _chainId) private {
DataStructures.OptionalValue storage domainEntry = chainIdToDomain[_chainId];
uint32 domain;
if (domainEntry.isSet) {
domain = uint32(domainEntry.value);
delete domainToChainId[uint32(domainEntry.value)];
}
delete chainIdToDomain[_chainId];
emit RemoveChainDomain(_chainId, domain);
}
function _setVariableRepaymentEnabled(bool _variableRepaymentEnabled) private {
variableRepaymentEnabled = _variableRepaymentEnabled;
emit SetVariableRepaymentEnabled(_variableRepaymentEnabled);
}
function _setProcessingFeeCollector(address _processingFeeCollector) private {
processingFeeCollector = _processingFeeCollector;
emit SetProcessingFeeCollector(_processingFeeCollector);
}
function _setTargetExecutor(address _targetExecutor) private {
targetExecutor = _targetExecutor;
emit SetTargetExecutor(_targetExecutor);
}
function _checkTargetDomain(uint256 _targetChainId) private view returns (uint32) {
DataStructures.OptionalValue storage domainEntry = chainIdToDomain[_targetChainId];
if (!domainEntry.isSet) {
revert DomainNotSetError();
}
return uint32(domainEntry.value);
}
function _prepareSendMessageVariables() private pure returns (SendMessageVariables memory) {
return
SendMessageVariables({
peerAddressBytes32: bytes32(0),
targetDomain: 0,
assetMessageNonce: 0,
dataMessageNonce: 0,
useTargetExecutor: false
});
}
function _decodeSettings(
bytes calldata _settings
) private pure returns (bool useTargetExecutor, uint256 processingFee, uint256 processingGas) {
return abi.decode(_settings, (bool, uint256, uint256));
}
function _addressToBytes32(address _address) private pure returns (bytes32) {
return bytes32(uint256(uint160(_address)));
}
function _bytes32ToAddress(bytes32 _buffer) private pure returns (address) {
return address(uint160(uint256(_buffer)));
}
}
文件 6 的 29: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;
文件 7 的 29: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;
}
}
文件 8 的 29: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);
}
文件 9 的 29:Errors.sol
pragma solidity 0.8.19;
error TokenBurnError();
error TokenMintError();
error ZeroAddressError();
文件 10 的 29: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 的 29:GatewayBase.sol
pragma solidity 0.8.19;
import { ReentrancyGuard } from '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import { IGateway } from './interfaces/IGateway.sol';
import { IGatewayClient } from './interfaces/IGatewayClient.sol';
import { BalanceManagement } from '../BalanceManagement.sol';
import { Pausable } from '../Pausable.sol';
import { TargetGasReserve } from './TargetGasReserve.sol';
import { ZeroAddressError } from '../Errors.sol';
import '../helpers/AddressHelper.sol' as AddressHelper;
import '../Constants.sol' as Constants;
import '../DataStructures.sol' as DataStructures;
abstract contract GatewayBase is
Pausable,
ReentrancyGuard,
TargetGasReserve,
BalanceManagement,
IGateway
{
IGatewayClient public client;
mapping(uint256 => address ) public peerMap;
uint256[] public peerChainIdList;
mapping(uint256 => DataStructures.OptionalValue )
public peerChainIdIndexMap;
event SetClient(address indexed clientAddress);
event SetPeer(uint256 indexed chainId, address indexed peerAddress);
event RemovePeer(uint256 indexed chainId);
event TargetPausedFailure();
event TargetClientNotSetFailure();
event TargetFromAddressFailure(uint256 indexed sourceChainId, address indexed fromAddress);
event TargetGasReserveFailure(uint256 indexed sourceChainId);
event TargetExecutionFailure();
error OnlyClientError();
error PeerAddressMismatchError();
error PeerNotSetError();
error ZeroChainIdError();
modifier onlyClient() {
if (msg.sender != address(client)) {
revert OnlyClientError();
}
_;
}
function setClient(address payable _clientAddress) external virtual onlyManager {
AddressHelper.requireContract(_clientAddress);
client = IGatewayClient(_clientAddress);
emit SetClient(_clientAddress);
}
function setPeers(
DataStructures.KeyToAddressValue[] calldata _peers
) external virtual onlyManager {
for (uint256 index; index < _peers.length; index++) {
DataStructures.KeyToAddressValue calldata item = _peers[index];
uint256 chainId = item.key;
address peerAddress = item.value;
if (chainId == block.chainid) {
if (peerAddress != address(this)) {
revert PeerAddressMismatchError();
}
} else {
_setPeer(chainId, peerAddress);
}
}
}
function removePeers(uint256[] calldata _chainIds) external virtual onlyManager {
for (uint256 index; index < _chainIds.length; index++) {
uint256 chainId = _chainIds[index];
if (chainId != block.chainid) {
_removePeer(chainId);
}
}
}
function peerCount() external view virtual returns (uint256) {
return peerChainIdList.length;
}
function fullPeerChainIdList() external view virtual returns (uint256[] memory) {
return peerChainIdList;
}
function _setPeer(uint256 _chainId, address _peerAddress) internal virtual {
if (_chainId == 0) {
revert ZeroChainIdError();
}
if (_peerAddress == address(0)) {
revert ZeroAddressError();
}
DataStructures.combinedMapSet(
peerMap,
peerChainIdList,
peerChainIdIndexMap,
_chainId,
_peerAddress,
Constants.LIST_SIZE_LIMIT_DEFAULT
);
emit SetPeer(_chainId, _peerAddress);
}
function _removePeer(uint256 _chainId) internal virtual {
if (_chainId == 0) {
revert ZeroChainIdError();
}
DataStructures.combinedMapRemove(peerMap, peerChainIdList, peerChainIdIndexMap, _chainId);
emit RemovePeer(_chainId);
}
function _checkPeerAddress(uint256 _chainId) internal virtual returns (address) {
address peerAddress = peerMap[_chainId];
if (peerAddress == address(0)) {
revert PeerNotSetError();
}
return peerAddress;
}
}
文件 12 的 29: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;
}
}
文件 13 的 29: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);
}
文件 14 的 29: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);
}
文件 15 的 29:IMessageHandler.sol
pragma solidity 0.8.19;
interface IMessageHandler {
function handleReceiveMessage(
uint32 _sourceDomain,
bytes32 _sender,
bytes calldata _messageBody
) external returns (bool);
}
文件 16 的 29:IMessageTransmitter.sol
pragma solidity 0.8.19;
import './IRelayer.sol';
import './IReceiver.sol';
interface IMessageTransmitter is IRelayer, IReceiver {
}
文件 17 的 29:IReceiver.sol
pragma solidity 0.8.19;
interface IReceiver {
function receiveMessage(
bytes calldata message,
bytes calldata signature
) external returns (bool success);
}
文件 18 的 29:IRelayer.sol
pragma solidity 0.8.19;
interface IRelayer {
function sendMessage(
uint32 destinationDomain,
bytes32 recipient,
bytes calldata messageBody
) external returns (uint64);
function sendMessageWithCaller(
uint32 destinationDomain,
bytes32 recipient,
bytes32 destinationCaller,
bytes calldata messageBody
) external returns (uint64);
function replaceMessage(
bytes calldata originalMessage,
bytes calldata originalAttestation,
bytes calldata newMessageBody,
bytes32 newDestinationCaller
) external;
}
文件 19 的 29:ITokenBalance.sol
pragma solidity 0.8.19;
interface ITokenBalance {
function balanceOf(address _account) external view returns (uint256);
}
文件 20 的 29:ITokenMessenger.sol
pragma solidity 0.8.19;
interface ITokenMessenger {
function depositForBurnWithCaller(
uint256 _amount,
uint32 _destinationDomain,
bytes32 _mintRecipient,
address _burnToken,
bytes32 _destinationCaller
) external returns (uint64 _nonce);
}
文件 21 的 29: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);
}
文件 22 的 29: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);
}
}
}
文件 23 的 29: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);
}
}
文件 24 的 29:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 25 的 29: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;
}
}
文件 26 的 29: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];
}
}
文件 27 的 29:SystemVersionId.sol
pragma solidity 0.8.19;
abstract contract SystemVersionId {
uint256 public constant SYSTEM_VERSION_ID = uint256(keccak256('Circle CCTP - 2023-06-26'));
}
文件 28 的 29:TargetGasReserve.sol
pragma solidity 0.8.19;
import { ManagerRole } from '../roles/ManagerRole.sol';
abstract contract TargetGasReserve is ManagerRole {
uint256 public targetGasReserve;
event SetTargetGasReserve(uint256 gasReserve);
function setTargetGasReserve(uint256 _gasReserve) external onlyManager {
_setTargetGasReserve(_gasReserve);
}
function _setTargetGasReserve(uint256 _gasReserve) internal virtual {
targetGasReserve = _gasReserve;
emit SetTargetGasReserve(_gasReserve);
}
}
文件 29 的 29: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/crosschain/circle-cctp/CircleCctpGateway.sol": "CircleCctpGateway"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ITokenMessenger","name":"_cctpTokenMessenger","type":"address"},{"internalType":"contract IMessageTransmitter","name":"_cctpMessageTransmitter","type":"address"},{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint32","name":"domain","type":"uint32"}],"internalType":"struct CircleCctpGateway.ChainDomain[]","name":"_chainDomains","type":"tuple[]"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"bool","name":"_variableRepaymentEnabled","type":"bool"},{"internalType":"uint256","name":"_targetGasReserve","type":"uint256"},{"internalType":"address","name":"_processingFeeCollector","type":"address"},{"internalType":"address","name":"_targetExecutor","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool","name":"_addOwnerToManagers","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetMessageError","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerGuardError","type":"error"},{"inputs":[],"name":"DataMessageError","type":"error"},{"inputs":[],"name":"DomainNotSetError","type":"error"},{"inputs":[],"name":"ExecutorError","type":"error"},{"inputs":[],"name":"ListSizeLimitError","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonContractAddressError","type":"error"},{"inputs":[],"name":"OnlyAssetSpenderError","type":"error"},{"inputs":[],"name":"OnlyClientError","type":"error"},{"inputs":[],"name":"OnlyCurrentVaultError","type":"error"},{"inputs":[],"name":"OnlyManagerError","type":"error"},{"inputs":[],"name":"OnlyMessageTransmitterError","type":"error"},{"inputs":[],"name":"PeerAddressMismatchError","type":"error"},{"inputs":[],"name":"PeerNotSetError","type":"error"},{"inputs":[],"name":"ProcessingFeeError","type":"error"},{"inputs":[],"name":"ReservedTokenError","type":"error"},{"inputs":[],"name":"SafeApproveError","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"inputs":[],"name":"TargetAssetAmountMismatchError","type":"error"},{"inputs":[],"name":"TargetCallerError","type":"error"},{"inputs":[],"name":"TargetClientNotSetError","type":"error"},{"inputs":[{"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"internalType":"address","name":"fromAddress","type":"address"}],"name":"TargetFromAddressError","type":"error"},{"inputs":[],"name":"TargetGasReserveError","type":"error"},{"inputs":[],"name":"VariableRepaymentNotEnabledError","type":"error"},{"inputs":[],"name":"VariableTokenNotSetError","type":"error"},{"inputs":[],"name":"ZeroAddressError","type":"error"},{"inputs":[],"name":"ZeroChainIdError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"targetChainId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"useTargetExecutor","type":"bool"},{"indexed":false,"internalType":"uint64","name":"assetMessageNonce","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"dataMessageNonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processingFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"processingGas","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"GatewayActionSource","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":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"}],"name":"RemoveChainDomain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"RemovePeer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RenounceManagerRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetAssetSpender","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":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"}],"name":"SetChainDomain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"clientAddress","type":"address"}],"name":"SetClient","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":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"peerAddress","type":"address"}],"name":"SetPeer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"processingFeeCollector","type":"address"}],"name":"SetProcessingFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"targetExecutor","type":"address"}],"name":"SetTargetExecutor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"gasReserve","type":"uint256"}],"name":"SetTargetGasReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"variableRepaymentEnabled","type":"bool"}],"name":"SetVariableRepaymentEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"}],"name":"TargetCctpMessageFailure","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetClientNotSetFailure","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetExecutionFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"}],"name":"TargetFromAddressFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"}],"name":"TargetGasReserveFailure","type":"event"},{"anonymous":false,"inputs":[],"name":"TargetPausedFailure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"SYSTEM_VERSION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetSpenderCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callerGuardMode","outputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cctpMessageTransmitter","outputs":[{"internalType":"contract IMessageTransmitter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cctpTokenMessenger","outputs":[{"internalType":"contract ITokenMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainIdToDomain","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkVariableTokenState","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"client","outputs":[{"internalType":"contract IGatewayClient","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"domainToChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_assetMessage","type":"bytes"},{"internalType":"bytes","name":"_assetAttestation","type":"bytes"},{"internalType":"bytes","name":"_dataMessage","type":"bytes"},{"internalType":"bytes","name":"_dataAttestation","type":"bytes"}],"name":"executeTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_assetMessage","type":"bytes"},{"internalType":"bytes","name":"_assetAttestation","type":"bytes"},{"internalType":"address","name":"_to","type":"address"}],"name":"extractCctpAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fullAssetSpenderList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","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":"fullPeerChainIdList","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_sourceDomain","type":"uint32"},{"internalType":"bytes32","name":"_sender","type":"bytes32"},{"internalType":"bytes","name":"_messageBody","type":"bytes"}],"name":"handleReceiveMessage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isAssetSpender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"_settings","type":"bytes"}],"name":"messageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","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":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"peerChainIdIndexMap","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"peerChainIdList","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"peerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"peerMap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"processingFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_chainIds","type":"uint256[]"}],"name":"removeChainDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_chainIds","type":"uint256[]"}],"name":"removePeers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"bool","name":"_forVariableBalance","type":"bool"}],"name":"requestAsset","outputs":[{"internalType":"address","name":"assetAddress","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_targetChainId","type":"uint256"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"bytes","name":"_settings","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setAssetSpender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"_callerGuardMode","type":"uint8"}],"name":"setCallerGuardMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"uint32","name":"domain","type":"uint32"}],"internalType":"struct CircleCctpGateway.ChainDomain[]","name":"_chainDomains","type":"tuple[]"}],"name":"setChainDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_clientAddress","type":"address"}],"name":"setClient","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":[{"components":[{"internalType":"uint256","name":"key","type":"uint256"},{"internalType":"address","name":"value","type":"address"}],"internalType":"struct KeyToAddressValue[]","name":"_peers","type":"tuple[]"}],"name":"setPeers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_processingFeeCollector","type":"address"}],"name":"setProcessingFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_targetExecutor","type":"address"}],"name":"setTargetExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasReserve","type":"uint256"}],"name":"setTargetGasReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetExecutor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetGasReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"variableRepaymentEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]