编译器
0.8.24+commit.e11b9ed9
文件 1 的 29:AbstractAdapter.sol
pragma solidity 0.8.24;
import {IAdapter} from "./IAdapter.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {IBridge, ILBTC} from "../IBridge.sol";
abstract contract AbstractAdapter is IAdapter, Context {
error Adapter_ZeroAddress();
error Adapter_AddressIsEOA();
error NotBridge();
event BridgeChanged(IBridge indexed oldBridge, IBridge indexed newBridge);
IBridge public override bridge;
constructor(IBridge bridge_) {
_notZero(address(bridge_));
bridge = bridge_;
}
function lbtc() public view returns (ILBTC) {
return bridge.lbtc();
}
modifier onlyBridge() {
_onlyBridge();
_;
}
function changeBridge(IBridge bridge_) external {
_onlyOwner();
_notZero(address(bridge_));
IBridge oldBridge = bridge;
bridge = bridge_;
emit BridgeChanged(oldBridge, bridge_);
}
function _onlyOwner() internal view virtual;
function _onlyBridge() internal view {
if (_msgSender() != address(bridge)) {
revert NotBridge();
}
}
function _notZero(address addr) internal pure {
if (addr == address(0)) {
revert Adapter_ZeroAddress();
}
}
function _receive(bytes32 fromChain, bytes memory payload) internal {
bridge.receivePayload(fromChain, payload);
}
function _deposit(
bytes32 _toChain,
bytes memory _payload,
address _refundAddress
) internal virtual {}
function deposit(
address _fromAddress,
bytes32 _toChain,
bytes32 ,
bytes32 ,
uint256 ,
bytes memory _payload
) external payable virtual override {
_deposit(_toChain, _payload, _fromAddress);
}
}
文件 2 的 29:Address.sol
pragma solidity ^0.8.20;
library Address {
error AddressInsufficientBalance(address account);
error AddressEmptyCode(address target);
error FailedInnerCall();
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
文件 3 的 29:CLAdapter.sol
pragma solidity 0.8.24;
import {IERC20} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
import {AbstractAdapter} from "./AbstractAdapter.sol";
import {IBridge} from "../IBridge.sol";
import {Pool} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Pool.sol";
import {LombardTokenPool} from "./TokenPool.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20 as OZIERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract CLAdapter is AbstractAdapter, Ownable, ReentrancyGuard {
error CLZeroChain();
error CLZeroChanSelector();
error CLAttemptToOverrideChainSelector();
error CLAttemptToOverrideChain();
error CLRefundFailed(address, uint256);
error CLUnauthorizedTokenPool(address);
error ZeroPayload();
error ReceiverTooBig();
error AmountOverflow();
error CLPayloadMismatch();
error CLWrongPayloadHashLength();
event CLChainSelectorSet(bytes32, uint64);
event CLTokenPoolDeployed(address);
mapping(bytes32 => uint64) public getRemoteChainSelector;
mapping(uint64 => bytes32) public getChain;
uint128 public getExecutionGasLimit;
LombardTokenPool public tokenPool;
uint256 internal _lastBurnedAmount;
bytes internal _lastPayload;
mapping(address => uint256) public refunds;
modifier onlyTokenPool() {
if (address(tokenPool) != _msgSender()) {
revert CLUnauthorizedTokenPool(_msgSender());
}
_;
}
constructor(
IBridge bridge_,
uint128 executionGasLimit_,
address ccipRouter_,
address[] memory allowlist_,
address rmnProxy_
) AbstractAdapter(bridge_) Ownable(_msgSender()) {
_setExecutionGasLimit(executionGasLimit_);
tokenPool = new LombardTokenPool(
IERC20(address(bridge_.lbtc())),
ccipRouter_,
allowlist_,
rmnProxy_,
CLAdapter(this)
);
tokenPool.transferOwnership(_msgSender());
emit CLTokenPoolDeployed(address(tokenPool));
}
function withdrawRefund() external nonReentrant {
uint256 refundAm = refunds[_msgSender()];
refunds[_msgSender()] = 0;
(bool success, ) = payable(_msgSender()).call{value: refundAm}("");
if (!success) {
revert CLRefundFailed(_msgSender(), refundAm);
}
}
function getFee(
bytes32 _toChain,
bytes32 ,
bytes32 _toAddress,
uint256 _amount,
bytes memory
) public view override returns (uint256) {
return
IRouterClient(tokenPool.getRouter()).getFee(
getRemoteChainSelector[_toChain],
_buildCCIPMessage(abi.encodePacked(_toAddress), _amount)
);
}
function initiateDeposit(
uint64 remoteChainSelector,
bytes calldata receiver,
uint256 amount
)
external
onlyTokenPool
returns (uint256 lastBurnedAmount, bytes memory lastPayload)
{
SafeERC20.safeTransferFrom(
OZIERC20(address(lbtc())),
_msgSender(),
address(this),
amount
);
if (_lastPayload.length > 0) {
lastBurnedAmount = _lastBurnedAmount;
lastPayload = _lastPayload;
_lastPayload = new bytes(0);
_lastBurnedAmount = 0;
} else {
if (receiver.length > 32) revert ReceiverTooBig();
if (amount >= 2 ** 64) revert AmountOverflow();
IERC20(address(lbtc())).approve(address(bridge), amount);
(lastBurnedAmount, lastPayload) = bridge.deposit(
getChain[remoteChainSelector],
bytes32(receiver),
uint64(amount)
);
}
bridge.lbtc().burn(lastBurnedAmount);
}
function deposit(
address fromAddress,
bytes32 _toChain,
bytes32,
bytes32 _toAddress,
uint256 _amount,
bytes memory _payload
) external payable virtual override {
_onlyBridge();
SafeERC20.safeTransferFrom(
OZIERC20(address(lbtc())),
_msgSender(),
address(this),
_amount
);
if (fromAddress == address(this)) {
return;
}
_lastBurnedAmount = _amount;
_lastPayload = _payload;
uint64 chainSelector = getRemoteChainSelector[_toChain];
Client.EVM2AnyMessage memory message = _buildCCIPMessage(
abi.encodePacked(_toAddress),
_amount
);
address router = tokenPool.getRouter();
uint256 fee = IRouterClient(router).getFee(chainSelector, message);
if (msg.value < fee) {
revert NotEnoughToPayFee(fee);
}
if (msg.value > fee) {
uint256 refundAm = msg.value - fee;
refunds[fromAddress] += refundAm;
}
IERC20(address(lbtc())).approve(router, _amount);
IRouterClient(router).ccipSend{value: fee}(chainSelector, message);
}
function initWithdrawalNoSignatures(
uint64 remoteSelector,
bytes calldata onChainData
) external onlyTokenPool returns (uint64) {
_receive(getChain[remoteSelector], onChainData);
return bridge.withdraw(onChainData);
}
function initiateWithdrawal(
uint64 remoteSelector,
bytes calldata payloadHash,
bytes calldata offchainData
) external onlyTokenPool returns (uint64) {
if (payloadHash.length != 32) {
revert CLWrongPayloadHashLength();
}
(bytes memory payload, bytes memory proof) = abi.decode(
offchainData,
(bytes, bytes)
);
if (bytes32(payloadHash[:32]) != sha256(payload)) {
revert CLPayloadMismatch();
}
_receive(getChain[remoteSelector], payload);
bridge.authNotary(payload, proof);
return bridge.withdraw(payload);
}
function setExecutionGasLimit(uint128 newVal) external onlyOwner {
_setExecutionGasLimit(newVal);
}
function _buildCCIPMessage(
bytes memory _receiver,
uint256 _amount
) private view returns (Client.EVM2AnyMessage memory) {
Client.EVMTokenAmount[]
memory tokenAmounts = new Client.EVMTokenAmount[](1);
tokenAmounts[0] = Client.EVMTokenAmount({
token: address(bridge.lbtc()),
amount: _amount
});
return
Client.EVM2AnyMessage({
receiver: _receiver,
data: "",
tokenAmounts: tokenAmounts,
extraArgs: Client._argsToBytes(
Client.EVMExtraArgsV2({
gasLimit: getExecutionGasLimit,
allowOutOfOrderExecution: true
})
),
feeToken: address(0)
});
}
function _onlyOwner() internal view override onlyOwner {}
function _setExecutionGasLimit(uint128 newVal) internal {
emit ExecutionGasLimitSet(getExecutionGasLimit, newVal);
getExecutionGasLimit = newVal;
}
function setRemoteChainSelector(
bytes32 chain,
uint64 chainSelector
) external onlyOwner {
if (chain == bytes32(0)) {
revert CLZeroChain();
}
if (chainSelector == 0) {
revert CLZeroChain();
}
if (getRemoteChainSelector[chain] != 0) {
revert CLAttemptToOverrideChainSelector();
}
if (getChain[chainSelector] != bytes32(0)) {
revert CLAttemptToOverrideChain();
}
getRemoteChainSelector[chain] = chainSelector;
getChain[chainSelector] = chain;
emit CLChainSelectorSet(chain, chainSelector);
}
}
文件 4 的 29:Client.sol
pragma solidity ^0.8.0;
library Client {
struct EVMTokenAmount {
address token;
uint256 amount;
}
struct Any2EVMMessage {
bytes32 messageId;
uint64 sourceChainSelector;
bytes sender;
bytes data;
EVMTokenAmount[] destTokenAmounts;
}
struct EVM2AnyMessage {
bytes receiver;
bytes data;
EVMTokenAmount[] tokenAmounts;
address feeToken;
bytes extraArgs;
}
bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9;
struct EVMExtraArgsV1 {
uint256 gasLimit;
}
function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs);
}
bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10;
struct EVMExtraArgsV2 {
uint256 gasLimit;
bool allowOutOfOrderExecution;
}
function _argsToBytes(EVMExtraArgsV2 memory extraArgs) internal pure returns (bytes memory bts) {
return abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs);
}
}
文件 5 的 29:ConfirmedOwner.sol
pragma solidity ^0.8.0;
import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol";
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}
文件 6 的 29:ConfirmedOwnerWithProposal.sol
pragma solidity ^0.8.0;
import {IOwnable} from "../interfaces/IOwnable.sol";
contract ConfirmedOwnerWithProposal is IOwnable {
address private s_owner;
address private s_pendingOwner;
event OwnershipTransferRequested(address indexed from, address indexed to);
event OwnershipTransferred(address indexed from, address indexed to);
constructor(address newOwner, address pendingOwner) {
require(newOwner != address(0), "Cannot set owner to zero");
s_owner = newOwner;
if (pendingOwner != address(0)) {
_transferOwnership(pendingOwner);
}
}
function transferOwnership(address to) public override onlyOwner {
_transferOwnership(to);
}
function acceptOwnership() external override {
require(msg.sender == s_pendingOwner, "Must be proposed owner");
address oldOwner = s_owner;
s_owner = msg.sender;
s_pendingOwner = address(0);
emit OwnershipTransferred(oldOwner, msg.sender);
}
function owner() public view override returns (address) {
return s_owner;
}
function _transferOwnership(address to) private {
require(to != msg.sender, "Cannot transfer to self");
s_pendingOwner = to;
emit OwnershipTransferRequested(s_owner, to);
}
function _validateOwnership() internal view {
require(msg.sender == s_owner, "Only callable by owner");
}
modifier onlyOwner() {
_validateOwnership();
_;
}
}
文件 7 的 29:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 8 的 29:ECDSA.sol
pragma solidity ^0.8.20;
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
error ECDSAInvalidSignature();
error ECDSAInvalidSignatureLength(uint256 length);
error ECDSAInvalidSignatureS(bytes32 s);
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError, bytes32) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
文件 9 的 29:EnumerableSet.sol
pragma solidity ^0.8.20;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 value => uint256) _positions;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 position = set._positions[value];
if (position != 0) {
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[valueIndex] = lastValue;
set._positions[lastValue] = position;
}
set._values.pop();
delete set._positions[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 10 的 29:IAdapter.sol
pragma solidity 0.8.24;
import {IBridge} from "../IBridge.sol";
interface IAdapter {
error NotEnoughToPayFee(uint256 fee);
event ExecutionGasLimitSet(uint128 indexed prevVal, uint128 indexed newVal);
function bridge() external view returns (IBridge);
function getFee(
bytes32 _toChain,
bytes32 _toContract,
bytes32 _toAddress,
uint256 _amount,
bytes memory _payload
) external view returns (uint256);
function deposit(
address _fromAddress,
bytes32 _toChain,
bytes32 _toContract,
bytes32 _toAddress,
uint256 _amount,
bytes memory _payload
) external payable;
}
文件 11 的 29:IBridge.sol
pragma solidity 0.8.24;
import {ILBTC} from "../LBTC/ILBTC.sol";
import "./adapters/IAdapter.sol";
import {IConsortiumConsumer, INotaryConsortium} from "../interfaces/IConsortiumConsumer.sol";
interface IBridge is IConsortiumConsumer {
error UnknownDestination();
error Bridge_ZeroAddress();
error Bridge_ZeroAmount();
error BadConfiguration();
error KnownDestination();
error ZeroContractHash();
error ZeroChainId();
error NotValidDestination();
error AmountLessThanCommission(uint256 commission);
error UnknownOriginContract(bytes32 fromChain, bytes32 fromContract);
error UnexpectedAction(bytes4 action);
error UnknownAdapter(address);
error PayloadAlreadyUsed(bytes32);
error AdapterNotConfirmed();
error ConsortiumNotConfirmed();
event DepositAbsoluteCommissionChanged(
uint64 newValue,
bytes32 indexed chain
);
event DepositRelativeCommissionChanged(
uint16 newValue,
bytes32 indexed chain
);
event BridgeDestinationAdded(
bytes32 indexed chain,
bytes32 indexed contractAddress
);
event BridgeDestinationRemoved(bytes32 indexed chain);
event AdapterChanged(address previousAdapter, IAdapter newAdapter);
event DepositToBridge(
address indexed fromAddress,
bytes32 indexed toAddress,
bytes32 indexed payloadHash,
bytes payload
);
event WithdrawFromBridge(
address indexed recipient,
bytes32 indexed payloadHash,
bytes payload,
uint64 amount
);
event PayloadReceived(
address indexed recipient,
bytes32 indexed payloadHash,
address indexed adapter
);
event PayloadNotarized(
address indexed recipient,
bytes32 indexed payloadHash
);
event RateLimitsChanged(
bytes32 indexed chainId,
uint256 limit,
uint256 window
);
event TreasuryChanged(address previousTreasury, address newTreasury);
function lbtc() external view returns (ILBTC);
function receivePayload(bytes32 fromChain, bytes calldata payload) external;
function deposit(
bytes32 toChain,
bytes32 toAddress,
uint64 amount
) external payable returns (uint256, bytes memory);
function authNotary(bytes calldata payload, bytes calldata proof) external;
function withdraw(bytes calldata payload) external returns (uint64);
}
文件 12 的 29:IConsortiumConsumer.sol
pragma solidity 0.8.24;
import {INotaryConsortium} from "../consortium/INotaryConsortium.sol";
interface IConsortiumConsumer {
event ConsortiumChanged(
INotaryConsortium indexed prevVal,
INotaryConsortium indexed newVal
);
function changeConsortium(INotaryConsortium newVal) external;
function consortium() external view returns (INotaryConsortium);
}
文件 13 的 29:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 14 的 29:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 15 的 29:IERC20Permit.sol
pragma solidity ^0.8.20;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 16 的 29:ILBTC.sol
pragma solidity 0.8.24;
interface ILBTC {
error ZeroAddress();
error ZeroContractHash();
error ZeroChainId();
error WithdrawalsDisabled();
error KnownDestination();
error UnknownDestination();
error ScriptPubkeyUnsupported();
error AmountLessThanCommission(uint256 fee);
error AmountBelowDustLimit(uint256 dustLimit);
error InvalidDustFeeRate();
error UnauthorizedAccount(address account);
error UnexpectedAction(bytes4 action);
error InvalidUserSignature();
error PayloadAlreadyUsed();
error InvalidInputLength();
error InvalidMintAmount();
event PauserRoleTransferred(
address indexed previousPauser,
address indexed newPauser
);
event OperatorRoleTransferred(
address indexed previousOperator,
address indexed newOperator
);
event UnstakeRequest(
address indexed fromAddress,
bytes scriptPubKey,
uint256 amount
);
event WithdrawalsEnabled(bool);
event NameAndSymbolChanged(string name, string symbol);
event ConsortiumChanged(address indexed prevVal, address indexed newVal);
event TreasuryAddressChanged(
address indexed prevValue,
address indexed newValue
);
event BurnCommissionChanged(
uint64 indexed prevValue,
uint64 indexed newValue
);
event DustFeeRateChanged(uint256 indexed oldRate, uint256 indexed newRate);
event BasculeChanged(address indexed prevVal, address indexed newVal);
event MinterUpdated(address indexed minter, bool isMinter);
event BridgeChanged(address indexed prevVal, address indexed newVal);
event ClaimerUpdated(address indexed claimer, bool isClaimer);
event FeeCharged(uint256 indexed fee, bytes userSignature);
event FeeChanged(uint256 indexed oldFee, uint256 indexed newFee);
error FeeGreaterThanAmount();
event MintProofConsumed(
address indexed recipient,
bytes32 indexed payloadHash,
bytes payload
);
event BatchMintSkipped(bytes32 indexed payloadHash, bytes payload);
function burn(uint256 amount) external;
function burn(address from, uint256 amount) external;
function mint(address to, uint256 amount) external;
}
文件 17 的 29:INotaryConsortium.sol
pragma solidity 0.8.24;
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
interface INotaryConsortium {
error PayloadAlreadyUsed();
error LengthMismatch();
error NotEnoughSignatures();
error UnexpectedAction(bytes4 action);
event ValidatorSetUpdated(
uint256 indexed epoch,
address[] validators,
uint256[] weights,
uint256 threshold
);
error ValSetAlreadySet();
error NoValidatorSet();
error InvalidEpoch();
function checkProof(
bytes32 _payloadHash,
bytes calldata _proof
) external view;
}
文件 18 的 29:IOwnable.sol
pragma solidity ^0.8.0;
interface IOwnable {
function owner() external returns (address);
function transferOwnership(address recipient) external;
function acceptOwnership() external;
}
文件 19 的 29:IPool.sol
pragma solidity ^0.8.0;
import {Pool} from "../libraries/Pool.sol";
import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol";
interface IPoolV1 is IERC165 {
function lockOrBurn(
Pool.LockOrBurnInV1 calldata lockOrBurnIn
) external returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut);
function releaseOrMint(
Pool.ReleaseOrMintInV1 calldata releaseOrMintIn
) external returns (Pool.ReleaseOrMintOutV1 memory);
function isSupportedChain(uint64 remoteChainSelector) external view returns (bool);
function isSupportedToken(address token) external view returns (bool);
}
文件 20 的 29:IRMN.sol
pragma solidity ^0.8.0;
interface IRMN {
struct TaggedRoot {
address commitStore;
bytes32 root;
}
function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool);
function isCursed() external view returns (bool);
function isCursed(bytes16 subject) external view returns (bool);
}
文件 21 的 29:IRouter.sol
pragma solidity ^0.8.0;
import {Client} from "../libraries/Client.sol";
interface IRouter {
error OnlyOffRamp();
function routeMessage(
Client.Any2EVMMessage calldata message,
uint16 gasForCallExactCheck,
uint256 gasLimit,
address receiver
) external returns (bool success, bytes memory retBytes, uint256 gasUsed);
function getOnRamp(uint64 destChainSelector) external view returns (address onRampAddress);
function isOffRamp(uint64 sourceChainSelector, address offRamp) external view returns (bool isOffRamp);
}
文件 22 的 29:IRouterClient.sol
pragma solidity ^0.8.4;
import {Client} from "../libraries/Client.sol";
interface IRouterClient {
error UnsupportedDestinationChain(uint64 destChainSelector);
error InsufficientFeeTokenAmount();
error InvalidMsgValue();
function isChainSupported(uint64 destChainSelector) external view returns (bool supported);
function getFee(
uint64 destinationChainSelector,
Client.EVM2AnyMessage memory message
) external view returns (uint256 fee);
function ccipSend(
uint64 destinationChainSelector,
Client.EVM2AnyMessage calldata message
) external payable returns (bytes32);
}
文件 23 的 29:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 24 的 29:OwnerIsCreator.sol
pragma solidity ^0.8.0;
import {ConfirmedOwner} from "./ConfirmedOwner.sol";
contract OwnerIsCreator is ConfirmedOwner {
constructor() ConfirmedOwner(msg.sender) {}
}
文件 25 的 29:Pool.sol
pragma solidity ^0.8.0;
library Pool {
bytes4 public constant CCIP_POOL_V1 = 0xaff2afbf;
uint16 public constant CCIP_POOL_V1_RET_BYTES = 32;
uint32 public constant CCIP_LOCK_OR_BURN_V1_RET_BYTES = 32;
struct LockOrBurnInV1 {
bytes receiver;
uint64 remoteChainSelector;
address originalSender;
uint256 amount;
address localToken;
}
struct LockOrBurnOutV1 {
bytes destTokenAddress;
bytes destPoolData;
}
struct ReleaseOrMintInV1 {
bytes originalSender;
uint64 remoteChainSelector;
address receiver;
uint256 amount;
address localToken;
bytes sourcePoolAddress;
bytes sourcePoolData;
bytes offchainTokenData;
}
struct ReleaseOrMintOutV1 {
uint256 destinationAmount;
}
}
文件 26 的 29:RateLimiter.sol
pragma solidity ^0.8.4;
library RateLimiter {
error BucketOverfilled();
error OnlyCallableByAdminOrOwner();
error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress);
error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress);
error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested);
error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available);
error InvalidRateLimitRate(Config rateLimiterConfig);
error DisabledNonZeroRateLimit(Config config);
error RateLimitMustBeDisabled();
event TokensConsumed(uint256 tokens);
event ConfigChanged(Config config);
struct TokenBucket {
uint128 tokens;
uint32 lastUpdated;
bool isEnabled;
uint128 capacity;
uint128 rate;
}
struct Config {
bool isEnabled;
uint128 capacity;
uint128 rate;
}
function _consume(TokenBucket storage s_bucket, uint256 requestTokens, address tokenAddress) internal {
if (!s_bucket.isEnabled || requestTokens == 0) {
return;
}
uint256 tokens = s_bucket.tokens;
uint256 capacity = s_bucket.capacity;
uint256 timeDiff = block.timestamp - s_bucket.lastUpdated;
if (timeDiff != 0) {
if (tokens > capacity) revert BucketOverfilled();
tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate);
s_bucket.lastUpdated = uint32(block.timestamp);
}
if (capacity < requestTokens) {
if (tokenAddress == address(0)) revert AggregateValueMaxCapacityExceeded(capacity, requestTokens);
revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress);
}
if (tokens < requestTokens) {
uint256 rate = s_bucket.rate;
uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate;
if (tokenAddress == address(0)) revert AggregateValueRateLimitReached(minWaitInSeconds, tokens);
revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress);
}
tokens -= requestTokens;
s_bucket.tokens = uint128(tokens);
emit TokensConsumed(requestTokens);
}
function _currentTokenBucketState(TokenBucket memory bucket) internal view returns (TokenBucket memory) {
bucket.tokens =
uint128(_calculateRefill(bucket.capacity, bucket.tokens, block.timestamp - bucket.lastUpdated, bucket.rate));
bucket.lastUpdated = uint32(block.timestamp);
return bucket;
}
function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal {
uint256 timeDiff = block.timestamp - s_bucket.lastUpdated;
if (timeDiff != 0) {
s_bucket.tokens = uint128(_calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate));
s_bucket.lastUpdated = uint32(block.timestamp);
}
s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens));
s_bucket.isEnabled = config.isEnabled;
s_bucket.capacity = config.capacity;
s_bucket.rate = config.rate;
emit ConfigChanged(config);
}
function _validateTokenBucketConfig(Config memory config, bool mustBeDisabled) internal pure {
if (config.isEnabled) {
if (config.rate >= config.capacity || config.rate == 0) {
revert InvalidRateLimitRate(config);
}
if (mustBeDisabled) {
revert RateLimitMustBeDisabled();
}
} else {
if (config.rate != 0 || config.capacity != 0) {
revert DisabledNonZeroRateLimit(config);
}
}
}
function _calculateRefill(
uint256 capacity,
uint256 tokens,
uint256 timeDiff,
uint256 rate
) private pure returns (uint256) {
return _min(capacity, tokens + timeDiff * rate);
}
function _min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
}
文件 27 的 29:ReentrancyGuard.sol
pragma solidity ^0.8.20;
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
文件 28 的 29:SafeERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
error SafeERC20FailedOperation(address token);
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
文件 29 的 29:TokenPool.sol
pragma solidity 0.8.24;
import {IERC20} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
import {IBridge} from "../IBridge.sol";
import {Pool} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Pool.sol";
import {TokenPool} from "@chainlink/contracts-ccip/src/v0.8/ccip/pools/TokenPool.sol";
import {CLAdapter} from "./CLAdapter.sol";
contract LombardTokenPool is TokenPool {
CLAdapter public adapter;
constructor(
IERC20 lbtc_,
address ccipRouter_,
address[] memory allowlist_,
address rmnProxy_,
CLAdapter adapter_
) TokenPool(lbtc_, allowlist_, rmnProxy_, ccipRouter_) {
adapter = adapter_;
}
function lockOrBurn(
Pool.LockOrBurnInV1 calldata lockOrBurnIn
) external virtual override returns (Pool.LockOrBurnOutV1 memory) {
_validateLockOrBurn(lockOrBurnIn);
i_token.approve(address(adapter), lockOrBurnIn.amount);
(uint256 burnedAmount, bytes memory payload) = adapter.initiateDeposit(
lockOrBurnIn.remoteChainSelector,
lockOrBurnIn.receiver,
lockOrBurnIn.amount
);
emit Burned(lockOrBurnIn.originalSender, burnedAmount);
bytes memory destPoolData = abi.encode(sha256(payload));
return
Pool.LockOrBurnOutV1({
destTokenAddress: getRemoteToken(
lockOrBurnIn.remoteChainSelector
),
destPoolData: destPoolData
});
}
function releaseOrMint(
Pool.ReleaseOrMintInV1 calldata releaseOrMintIn
) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) {
_validateReleaseOrMint(releaseOrMintIn);
uint64 amount = adapter.initiateWithdrawal(
releaseOrMintIn.remoteChainSelector,
releaseOrMintIn.sourcePoolData,
releaseOrMintIn.offchainTokenData
);
emit Minted(msg.sender, releaseOrMintIn.receiver, uint256(amount));
return Pool.ReleaseOrMintOutV1({destinationAmount: uint256(amount)});
}
}
{
"compilationTarget": {
"contracts/bridge/adapters/TokenPool.sol": "LombardTokenPool"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"lbtc_","type":"address"},{"internalType":"address","name":"ccipRouter_","type":"address"},{"internalType":"address[]","name":"allowlist_","type":"address[]"},{"internalType":"address","name":"rmnProxy_","type":"address"},{"internalType":"contract CLAdapter","name":"adapter_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"capacity","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"AggregateValueMaxCapacityExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"minWaitInSeconds","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"}],"name":"AggregateValueRateLimitReached","type":"error"},{"inputs":[],"name":"AllowListNotEnabled","type":"error"},{"inputs":[],"name":"BucketOverfilled","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerIsNotARampOnRouter","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainSelector","type":"uint64"}],"name":"ChainAlreadyExists","type":"error"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"ChainNotAllowed","type":"error"},{"inputs":[],"name":"CursedByRMN","type":"error"},{"inputs":[{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.Config","name":"config","type":"tuple"}],"name":"DisabledNonZeroRateLimit","type":"error"},{"inputs":[{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.Config","name":"rateLimiterConfig","type":"tuple"}],"name":"InvalidRateLimitRate","type":"error"},{"inputs":[{"internalType":"bytes","name":"sourcePoolAddress","type":"bytes"}],"name":"InvalidSourcePoolAddress","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"InvalidToken","type":"error"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"NonExistentChain","type":"error"},{"inputs":[],"name":"RateLimitMustBeDisabled","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderNotAllowed","type":"error"},{"inputs":[{"internalType":"uint256","name":"capacity","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenMaxCapacityExceeded","type":"error"},{"inputs":[{"internalType":"uint256","name":"minWaitInSeconds","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenRateLimitReached","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"AllowListAdd","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"AllowListRemove","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"remoteToken","type":"bytes"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"indexed":false,"internalType":"struct RateLimiter.Config","name":"outboundRateLimiterConfig","type":"tuple"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"indexed":false,"internalType":"struct RateLimiter.Config","name":"inboundRateLimiterConfig","type":"tuple"}],"name":"ChainAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"indexed":false,"internalType":"struct RateLimiter.Config","name":"outboundRateLimiterConfig","type":"tuple"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"indexed":false,"internalType":"struct RateLimiter.Config","name":"inboundRateLimiterConfig","type":"tuple"}],"name":"ChainConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"ChainRemoved","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"indexed":false,"internalType":"struct RateLimiter.Config","name":"config","type":"tuple"}],"name":"ConfigChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Released","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"previousPoolAddress","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"remotePoolAddress","type":"bytes"}],"name":"RemotePoolSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRouter","type":"address"},{"indexed":false,"internalType":"address","name":"newRouter","type":"address"}],"name":"RouterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"TokensConsumed","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adapter","outputs":[{"internalType":"contract CLAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"removes","type":"address[]"},{"internalType":"address[]","name":"adds","type":"address[]"}],"name":"applyAllowListUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"bytes","name":"remotePoolAddress","type":"bytes"},{"internalType":"bytes","name":"remoteTokenAddress","type":"bytes"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.Config","name":"outboundRateLimiterConfig","type":"tuple"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.Config","name":"inboundRateLimiterConfig","type":"tuple"}],"internalType":"struct TokenPool.ChainUpdate[]","name":"chains","type":"tuple[]"}],"name":"applyChainUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllowList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowListEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"getCurrentInboundRateLimiterState","outputs":[{"components":[{"internalType":"uint128","name":"tokens","type":"uint128"},{"internalType":"uint32","name":"lastUpdated","type":"uint32"},{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.TokenBucket","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"getCurrentOutboundRateLimiterState","outputs":[{"components":[{"internalType":"uint128","name":"tokens","type":"uint128"},{"internalType":"uint32","name":"lastUpdated","type":"uint32"},{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.TokenBucket","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRateLimitAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"getRemotePool","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"getRemoteToken","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRmnProxy","outputs":[{"internalType":"address","name":"rmnProxy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRouter","outputs":[{"internalType":"address","name":"router","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedChains","outputs":[{"internalType":"uint64[]","name":"","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getToken","outputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"}],"name":"isSupportedChain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isSupportedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"receiver","type":"bytes"},{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"internalType":"address","name":"originalSender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"localToken","type":"address"}],"internalType":"struct Pool.LockOrBurnInV1","name":"lockOrBurnIn","type":"tuple"}],"name":"lockOrBurn","outputs":[{"components":[{"internalType":"bytes","name":"destTokenAddress","type":"bytes"},{"internalType":"bytes","name":"destPoolData","type":"bytes"}],"internalType":"struct Pool.LockOrBurnOutV1","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"originalSender","type":"bytes"},{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"localToken","type":"address"},{"internalType":"bytes","name":"sourcePoolAddress","type":"bytes"},{"internalType":"bytes","name":"sourcePoolData","type":"bytes"},{"internalType":"bytes","name":"offchainTokenData","type":"bytes"}],"internalType":"struct Pool.ReleaseOrMintInV1","name":"releaseOrMintIn","type":"tuple"}],"name":"releaseOrMint","outputs":[{"components":[{"internalType":"uint256","name":"destinationAmount","type":"uint256"}],"internalType":"struct Pool.ReleaseOrMintOutV1","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.Config","name":"outboundConfig","type":"tuple"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"uint128","name":"capacity","type":"uint128"},{"internalType":"uint128","name":"rate","type":"uint128"}],"internalType":"struct RateLimiter.Config","name":"inboundConfig","type":"tuple"}],"name":"setChainRateLimiterConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rateLimitAdmin","type":"address"}],"name":"setRateLimitAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"remoteChainSelector","type":"uint64"},{"internalType":"bytes","name":"remotePoolAddress","type":"bytes"}],"name":"setRemotePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRouter","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]