Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 23 from a total of 23 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer Ownersh... | 13186025 | 543 days ago | IN | 0 ETH | 0.000001590457 | ||||
| Apply Ramp Updat... | 12913326 | 549 days ago | IN | 0 ETH | 0.000000330817 | ||||
| Apply Ramp Updat... | 10860723 | 596 days ago | IN | 0 ETH | 0.000004251205 | ||||
| Apply Ramp Updat... | 10860359 | 596 days ago | IN | 0 ETH | 0.000005344551 | ||||
| Accept Ownership | 9349018 | 631 days ago | IN | 0 ETH | 0.000009475913 | ||||
| Transfer Ownersh... | 9348971 | 631 days ago | IN | 0 ETH | 0.000011115139 | ||||
| Transfer Ownersh... | 9347876 | 631 days ago | IN | 0 ETH | 0.000010050251 | ||||
| Apply Ramp Updat... | 8732939 | 646 days ago | IN | 0 ETH | 0.000003930209 | ||||
| Apply Ramp Updat... | 8732908 | 646 days ago | IN | 0 ETH | 0.000004241183 | ||||
| Apply Ramp Updat... | 7130442 | 683 days ago | IN | 0 ETH | 0.000139195996 | ||||
| Apply Ramp Updat... | 7130416 | 683 days ago | IN | 0 ETH | 0.000153600907 | ||||
| Apply Ramp Updat... | 7046175 | 685 days ago | IN | 0 ETH | 0.00000040549 | ||||
| Apply Ramp Updat... | 7046068 | 685 days ago | IN | 0 ETH | 0.000000515946 | ||||
| Apply Ramp Updat... | 7045927 | 685 days ago | IN | 0 ETH | 0.000000481101 | ||||
| Apply Ramp Updat... | 7045884 | 685 days ago | IN | 0 ETH | 0.00000036846 | ||||
| Apply Ramp Updat... | 7045648 | 685 days ago | IN | 0 ETH | 0.000000429764 | ||||
| Apply Ramp Updat... | 7045608 | 685 days ago | IN | 0 ETH | 0.000000516861 | ||||
| Apply Ramp Updat... | 7045431 | 685 days ago | IN | 0 ETH | 0.000000482243 | ||||
| Apply Ramp Updat... | 7045302 | 685 days ago | IN | 0 ETH | 0.000000532891 | ||||
| Apply Ramp Updat... | 7045091 | 685 days ago | IN | 0 ETH | 0.000000440544 | ||||
| Apply Ramp Updat... | 7044804 | 685 days ago | IN | 0 ETH | 0.000000404516 | ||||
| Apply Ramp Updat... | 7044675 | 685 days ago | IN | 0 ETH | 0.000000528159 | ||||
| Apply Ramp Updat... | 7044406 | 685 days ago | IN | 0 ETH | 0.000000454765 |
Loading...
Loading
Contract Name:
BurnMintTokenPool
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 26000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol";
import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol";
import {TokenPool} from "./TokenPool.sol";
import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol";
/// @notice This pool mints and burns a 3rd-party token.
/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later.
/// It either accepts any address as originalSender, or only accepts whitelisted originalSender.
/// The only way to change whitelisting mode is to deploy a new pool.
/// If that is expected, please make sure the token's burner/minter roles are adjustable.
contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion {
// solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables
string public constant override typeAndVersion = "BurnMintTokenPool 1.2.0";
constructor(
IBurnMintERC20 token,
address[] memory allowlist,
address armProxy
) TokenPool(token, allowlist, armProxy) {}
/// @inheritdoc BurnMintTokenPoolAbstract
function _burn(uint256 amount) internal virtual override {
IBurnMintERC20(address(i_token)).burn(amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ITypeAndVersion {
function typeAndVersion() external pure returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
interface IBurnMintERC20 is IERC20 {
/// @notice Mints new tokens for a given address.
/// @param account The address to mint the new tokens to.
/// @param amount The number of tokens to be minted.
/// @dev this function increases the total supply.
function mint(address account, uint256 amount) external;
/// @notice Burns tokens from the sender.
/// @param amount The number of tokens to be burned.
/// @dev this function decreases the total supply.
function burn(uint256 amount) external;
/// @notice Burns tokens from a given address..
/// @param account The address to burn tokens from.
/// @param amount The number of tokens to be burned.
/// @dev this function decreases the total supply.
function burn(address account, uint256 amount) external;
/// @notice Burns tokens from a given address..
/// @param account The address to burn tokens from.
/// @param amount The number of tokens to be burned.
/// @dev this function decreases the total supply.
function burnFrom(address account, uint256 amount) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
import {IPool} from "../interfaces/pools/IPool.sol";
import {IARM} from "../interfaces/IARM.sol";
import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol";
import {RateLimiter} from "../libraries/RateLimiter.sol";
import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol";
import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol";
/// @notice Base abstract class with common functions for all token pools.
/// A token pool serves as isolated place for holding tokens and token specific logic
/// that may execute as tokens move across the bridge.
abstract contract TokenPool is IPool, OwnerIsCreator, IERC165 {
using EnumerableSet for EnumerableSet.AddressSet;
using RateLimiter for RateLimiter.TokenBucket;
error PermissionsError();
error ZeroAddressNotAllowed();
error SenderNotAllowed(address sender);
error AllowListNotEnabled();
error NonExistentRamp(address ramp);
error BadARMSignal();
error RampAlreadyExists(address ramp);
event Locked(address indexed sender, uint256 amount);
event Burned(address indexed sender, uint256 amount);
event Released(address indexed sender, address indexed recipient, uint256 amount);
event Minted(address indexed sender, address indexed recipient, uint256 amount);
event OnRampAdded(address onRamp, RateLimiter.Config rateLimiterConfig);
event OnRampConfigured(address onRamp, RateLimiter.Config rateLimiterConfig);
event OnRampRemoved(address onRamp);
event OffRampAdded(address offRamp, RateLimiter.Config rateLimiterConfig);
event OffRampConfigured(address offRamp, RateLimiter.Config rateLimiterConfig);
event OffRampRemoved(address offRamp);
event AllowListAdd(address sender);
event AllowListRemove(address sender);
struct RampUpdate {
address ramp;
bool allowed;
RateLimiter.Config rateLimiterConfig;
}
/// @dev The bridgeable token that is managed by this pool.
IERC20 internal immutable i_token;
/// @dev The address of the arm proxy
address internal immutable i_armProxy;
/// @dev The immutable flag that indicates if the pool is access-controlled.
bool internal immutable i_allowlistEnabled;
/// @dev A set of addresses allowed to trigger lockOrBurn as original senders.
/// Only takes effect if i_allowlistEnabled is true.
/// This can be used to ensure only token-issuer specified addresses can
/// move tokens.
EnumerableSet.AddressSet internal s_allowList;
/// @dev A set of allowed onRamps. We want the whitelist to be enumerable to
/// be able to quickly determine (without parsing logs) who can access the pool.
EnumerableSet.AddressSet internal s_onRamps;
/// @dev Inbound rate limits. This allows per destination chain
/// token issuer specified rate limiting (e.g. issuers may trust chains to varying
/// degrees and prefer different limits)
mapping(address => RateLimiter.TokenBucket) internal s_onRampRateLimits;
/// @dev A set of allowed offRamps.
EnumerableSet.AddressSet internal s_offRamps;
/// @dev Outbound rate limits. Corresponds to the inbound rate limit for the pool
/// on the remote chain.
mapping(address => RateLimiter.TokenBucket) internal s_offRampRateLimits;
constructor(IERC20 token, address[] memory allowlist, address armProxy) {
if (address(token) == address(0)) revert ZeroAddressNotAllowed();
i_token = token;
i_armProxy = armProxy;
// Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas.
i_allowlistEnabled = allowlist.length > 0;
if (i_allowlistEnabled) {
_applyAllowListUpdates(new address[](0), allowlist);
}
}
/// @notice Get ARM proxy address
/// @return armProxy Address of arm proxy
function getArmProxy() public view returns (address armProxy) {
return i_armProxy;
}
/// @inheritdoc IPool
function getToken() public view override returns (IERC20 token) {
return i_token;
}
/// @inheritdoc IERC165
function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
return interfaceId == type(IPool).interfaceId || interfaceId == type(IERC165).interfaceId;
}
// ================================================================
// │ Ramp permissions │
// ================================================================
/// @notice Checks whether something is a permissioned onRamp on this contract.
/// @return true if the given address is a permissioned onRamp.
function isOnRamp(address onRamp) public view returns (bool) {
return s_onRamps.contains(onRamp);
}
/// @notice Checks whether something is a permissioned offRamp on this contract.
/// @return true if the given address is a permissioned offRamp.
function isOffRamp(address offRamp) public view returns (bool) {
return s_offRamps.contains(offRamp);
}
/// @notice Get onRamp whitelist
/// @return list of onRamps.
function getOnRamps() public view returns (address[] memory) {
return s_onRamps.values();
}
/// @notice Get offRamp whitelist
/// @return list of offramps
function getOffRamps() public view returns (address[] memory) {
return s_offRamps.values();
}
/// @notice Sets permissions for all on and offRamps.
/// @dev Only callable by the owner
/// @param onRamps A list of onRamps and their new permission status/rate limits
/// @param offRamps A list of offRamps and their new permission status/rate limits
function applyRampUpdates(RampUpdate[] calldata onRamps, RampUpdate[] calldata offRamps) external virtual onlyOwner {
_applyRampUpdates(onRamps, offRamps);
}
function _applyRampUpdates(RampUpdate[] calldata onRamps, RampUpdate[] calldata offRamps) internal onlyOwner {
for (uint256 i = 0; i < onRamps.length; ++i) {
RampUpdate memory update = onRamps[i];
if (update.allowed) {
if (s_onRamps.add(update.ramp)) {
s_onRampRateLimits[update.ramp] = RateLimiter.TokenBucket({
rate: update.rateLimiterConfig.rate,
capacity: update.rateLimiterConfig.capacity,
tokens: update.rateLimiterConfig.capacity,
lastUpdated: uint32(block.timestamp),
isEnabled: update.rateLimiterConfig.isEnabled
});
emit OnRampAdded(update.ramp, update.rateLimiterConfig);
} else {
revert RampAlreadyExists(update.ramp);
}
} else {
if (s_onRamps.remove(update.ramp)) {
delete s_onRampRateLimits[update.ramp];
emit OnRampRemoved(update.ramp);
} else {
// Cannot remove a non-existent onRamp.
revert NonExistentRamp(update.ramp);
}
}
}
for (uint256 i = 0; i < offRamps.length; ++i) {
RampUpdate memory update = offRamps[i];
if (update.allowed) {
if (s_offRamps.add(update.ramp)) {
s_offRampRateLimits[update.ramp] = RateLimiter.TokenBucket({
rate: update.rateLimiterConfig.rate,
capacity: update.rateLimiterConfig.capacity,
tokens: update.rateLimiterConfig.capacity,
lastUpdated: uint32(block.timestamp),
isEnabled: update.rateLimiterConfig.isEnabled
});
emit OffRampAdded(update.ramp, update.rateLimiterConfig);
} else {
revert RampAlreadyExists(update.ramp);
}
} else {
if (s_offRamps.remove(update.ramp)) {
delete s_offRampRateLimits[update.ramp];
emit OffRampRemoved(update.ramp);
} else {
// Cannot remove a non-existent offRamp.
revert NonExistentRamp(update.ramp);
}
}
}
}
// ================================================================
// │ Rate limiting │
// ================================================================
/// @notice Consumes outbound rate limiting capacity in this pool
function _consumeOnRampRateLimit(uint256 amount) internal {
s_onRampRateLimits[msg.sender]._consume(amount, address(i_token));
}
/// @notice Consumes inbound rate limiting capacity in this pool
function _consumeOffRampRateLimit(uint256 amount) internal {
s_offRampRateLimits[msg.sender]._consume(amount, address(i_token));
}
/// @notice Gets the token bucket with its values for the block it was requested at.
/// @return The token bucket.
function currentOnRampRateLimiterState(address onRamp) external view returns (RateLimiter.TokenBucket memory) {
return s_onRampRateLimits[onRamp]._currentTokenBucketState();
}
/// @notice Gets the token bucket with its values for the block it was requested at.
/// @return The token bucket.
function currentOffRampRateLimiterState(address offRamp) external view returns (RateLimiter.TokenBucket memory) {
return s_offRampRateLimits[offRamp]._currentTokenBucketState();
}
/// @notice Sets the onramp rate limited config.
/// @param config The new rate limiter config.
function setOnRampRateLimiterConfig(address onRamp, RateLimiter.Config memory config) external onlyOwner {
if (!isOnRamp(onRamp)) revert NonExistentRamp(onRamp);
s_onRampRateLimits[onRamp]._setTokenBucketConfig(config);
emit OnRampConfigured(onRamp, config);
}
/// @notice Sets the offramp rate limited config.
/// @param config The new rate limiter config.
function setOffRampRateLimiterConfig(address offRamp, RateLimiter.Config memory config) external onlyOwner {
if (!isOffRamp(offRamp)) revert NonExistentRamp(offRamp);
s_offRampRateLimits[offRamp]._setTokenBucketConfig(config);
emit OffRampConfigured(offRamp, config);
}
// ================================================================
// │ Access │
// ================================================================
/// @notice Checks whether the msg.sender is a permissioned onRamp on this contract
/// @dev Reverts with a PermissionsError if check fails
modifier onlyOnRamp() {
if (!isOnRamp(msg.sender)) revert PermissionsError();
_;
}
/// @notice Checks whether the msg.sender is a permissioned offRamp on this contract
/// @dev Reverts with a PermissionsError if check fails
modifier onlyOffRamp() {
if (!isOffRamp(msg.sender)) revert PermissionsError();
_;
}
// ================================================================
// │ Allowlist │
// ================================================================
modifier checkAllowList(address sender) {
if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender);
_;
}
/// @notice Gets whether the allowList functionality is enabled.
/// @return true is enabled, false if not.
function getAllowListEnabled() external view returns (bool) {
return i_allowlistEnabled;
}
/// @notice Gets the allowed addresses.
/// @return The allowed addresses.
function getAllowList() external view returns (address[] memory) {
return s_allowList.values();
}
/// @notice Apply updates to the allow list.
/// @param removes The addresses to be removed.
/// @param adds The addresses to be added.
/// @dev allowListing will be removed before public launch
function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner {
_applyAllowListUpdates(removes, adds);
}
/// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor.
function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal {
if (!i_allowlistEnabled) revert AllowListNotEnabled();
for (uint256 i = 0; i < removes.length; ++i) {
address toRemove = removes[i];
if (s_allowList.remove(toRemove)) {
emit AllowListRemove(toRemove);
}
}
for (uint256 i = 0; i < adds.length; ++i) {
address toAdd = adds[i];
if (toAdd == address(0)) {
continue;
}
if (s_allowList.add(toAdd)) {
emit AllowListAdd(toAdd);
}
}
}
/// @notice Ensure that there is no active curse.
modifier whenHealthy() {
if (IARM(i_armProxy).isCursed()) revert BadARMSignal();
_;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.19;
import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol";
import {TokenPool} from "./TokenPool.sol";
abstract contract BurnMintTokenPoolAbstract is TokenPool {
/// @notice Contains the specific burn call for a pool.
/// @dev overriding this method allows us to create pools with different burn signatures
/// without duplicating the underlying logic.
function _burn(uint256 amount) internal virtual;
/// @notice Burn the token in the pool
/// @param amount Amount to burn
/// @dev The whenHealthy check is important to ensure that even if a ramp is compromised
/// we're able to stop token movement via ARM.
function lockOrBurn(
address originalSender,
bytes calldata,
uint256 amount,
uint64,
bytes calldata
) external virtual override onlyOnRamp checkAllowList(originalSender) whenHealthy returns (bytes memory) {
_consumeOnRampRateLimit(amount);
_burn(amount);
emit Burned(msg.sender, amount);
return "";
}
/// @notice Mint tokens from the pool to the recipient
/// @param receiver Recipient address
/// @param amount Amount to mint
/// @dev The whenHealthy check is important to ensure that even if a ramp is compromised
/// we're able to stop token movement via ARM.
function releaseOrMint(
bytes memory,
address receiver,
uint256 amount,
uint64,
bytes memory
) external virtual override whenHealthy onlyOffRamp {
_consumeOffRampRateLimit(amount);
IBurnMintERC20(address(i_token)).mint(receiver, amount);
emit Minted(msg.sender, receiver, amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
// Shared public interface for multiple pool types.
// Each pool type handles a different child token model (lock/unlock, mint/burn.)
interface IPool {
/// @notice Lock tokens into the pool or burn the tokens.
/// @param originalSender Original sender of the tokens.
/// @param receiver Receiver of the tokens on destination chain.
/// @param amount Amount to lock or burn.
/// @param destChainSelector Destination chain Id.
/// @param extraArgs Additional data passed in by sender for lockOrBurn processing
/// in custom pools on source chain.
/// @return retData Optional field that contains bytes. Unused for now but already
/// implemented to allow future upgrades while preserving the interface.
function lockOrBurn(
address originalSender,
bytes calldata receiver,
uint256 amount,
uint64 destChainSelector,
bytes calldata extraArgs
) external returns (bytes memory);
/// @notice Releases or mints tokens to the receiver address.
/// @param originalSender Original sender of the tokens.
/// @param receiver Receiver of the tokens.
/// @param amount Amount to release or mint.
/// @param sourceChainSelector Source chain Id.
/// @param extraData Additional data supplied offchain for releaseOrMint processing in
/// custom pools on dest chain. This could be an attestation that was retrieved through a
/// third party API.
/// @dev offchainData can come from any untrusted source.
function releaseOrMint(
bytes memory originalSender,
address receiver,
uint256 amount,
uint64 sourceChainSelector,
bytes memory extraData
) external;
/// @notice Gets the IERC20 token that this pool can lock or burn.
/// @return token The IERC20 token representation.
function getToken() external view returns (IERC20 token);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice This interface contains the only ARM-related functions that might be used on-chain by other CCIP contracts.
interface IARM {
/// @notice A Merkle root tagged with the address of the commit store contract it is destined for.
struct TaggedRoot {
address commitStore;
bytes32 root;
}
/// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed.
function isBlessed(TaggedRoot calldata taggedRoot) external view returns (bool);
/// @notice When the ARM is "cursed", CCIP pauses until the curse is lifted.
function isCursed() external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {ConfirmedOwner} from "./ConfirmedOwner.sol";
/// @title The OwnerIsCreator contract
/// @notice A contract with helpers for basic contract ownership.
contract OwnerIsCreator is ConfirmedOwner {
constructor() ConfirmedOwner(msg.sender) {}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/// @notice Implements Token Bucket rate limiting.
/// @dev uint128 is safe for rate limiter state.
/// For USD value rate limiting, it can adequately store USD value in 18 decimals.
/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most
/// a supply of uint128.max tokens, and it will therefore not overflow the bucket.
/// In exceptional scenarios where tokens consumed may be larger than uint128,
/// e.g. compromised issuer, an enabled RateLimiter will check and revert.
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);
event TokensConsumed(uint256 tokens);
event ConfigChanged(Config config);
struct TokenBucket {
uint128 tokens; // ──────╮ Current number of tokens that are in the bucket.
uint32 lastUpdated; // │ Timestamp in seconds of the last token refill, good for 100+ years.
bool isEnabled; // ──────╯ Indication whether the rate limiting is enabled or not
uint128 capacity; // ────╮ Maximum number of tokens that can be in the bucket.
uint128 rate; // ────────╯ Number of tokens per second that the bucket is refilled.
}
struct Config {
bool isEnabled; // Indication whether the rate limiting should be enabled
uint128 capacity; // ────╮ Specifies the capacity of the rate limiter
uint128 rate; // ───────╯ Specifies the rate of the rate limiter
}
/// @notice _consume removes the given tokens from the pool, lowering the
/// rate tokens allowed to be consumed for subsequent calls.
/// @param requestTokens The total tokens to be consumed from the bucket.
/// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity.
/// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket
/// @dev emits removal of requestTokens if requestTokens is > 0
function _consume(TokenBucket storage s_bucket, uint256 requestTokens, address tokenAddress) internal {
// If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage
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();
// Refill tokens when arriving at a new block time
tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate);
s_bucket.lastUpdated = uint32(block.timestamp);
}
if (capacity < requestTokens) {
// Token address 0 indicates consuming aggregate value rate limit capacity.
if (tokenAddress == address(0)) revert AggregateValueMaxCapacityExceeded(capacity, requestTokens);
revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress);
}
if (tokens < requestTokens) {
uint256 rate = s_bucket.rate;
// Wait required until the bucket is refilled enough to accept this value, round up to next higher second
// Consume is not guaranteed to succeed after wait time passes if there is competing traffic.
// This acts as a lower bound of wait time.
uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate;
if (tokenAddress == address(0)) revert AggregateValueRateLimitReached(minWaitInSeconds, tokens);
revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress);
}
tokens -= requestTokens;
// Downcast is safe here, as tokens is not larger than capacity
s_bucket.tokens = uint128(tokens);
emit TokensConsumed(requestTokens);
}
/// @notice Gets the token bucket with its values for the block it was requested at.
/// @return The token bucket.
function _currentTokenBucketState(TokenBucket memory bucket) internal view returns (TokenBucket memory) {
// We update the bucket to reflect the status at the exact time of the
// call. This means we might need to refill a part of the bucket based
// on the time that has passed since the last update.
bucket.tokens = uint128(
_calculateRefill(bucket.capacity, bucket.tokens, block.timestamp - bucket.lastUpdated, bucket.rate)
);
bucket.lastUpdated = uint32(block.timestamp);
return bucket;
}
/// @notice Sets the rate limited config.
/// @param s_bucket The token bucket
/// @param config The new config
function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal {
// First update the bucket to make sure the proper rate is used for all the time
// up until the config change.
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);
}
/// @notice Calculate refilled tokens
/// @param capacity bucket capacity
/// @param tokens current bucket tokens
/// @param timeDiff block time difference since last refill
/// @param rate bucket refill rate
/// @return the value of tokens after refill
function _calculateRefill(
uint256 capacity,
uint256 tokens,
uint256 timeDiff,
uint256 rate
) private pure returns (uint256) {
return _min(capacity, tokens + timeDiff * rate);
}
/// @notice Return the smallest of two integers
/// @param a first int
/// @param b second int
/// @return smallest
function _min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol";
/// @title The ConfirmedOwner contract
/// @notice A contract with helpers for basic contract ownership.
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IOwnable} from "../interfaces/IOwnable.sol";
/// @title The ConfirmedOwner contract
/// @notice A contract with helpers for basic contract ownership.
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) {
// solhint-disable-next-line custom-errors
require(newOwner != address(0), "Cannot set owner to zero");
s_owner = newOwner;
if (pendingOwner != address(0)) {
_transferOwnership(pendingOwner);
}
}
/// @notice Allows an owner to begin transferring ownership to a new address.
function transferOwnership(address to) public override onlyOwner {
_transferOwnership(to);
}
/// @notice Allows an ownership transfer to be completed by the recipient.
function acceptOwnership() external override {
// solhint-disable-next-line custom-errors
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);
}
/// @notice Get the current owner
function owner() public view override returns (address) {
return s_owner;
}
/// @notice validate, transfer ownership, and emit relevant events
function _transferOwnership(address to) private {
// solhint-disable-next-line custom-errors
require(to != msg.sender, "Cannot transfer to self");
s_pendingOwner = to;
emit OwnershipTransferRequested(s_owner, to);
}
/// @notice validate access
function _validateOwnership() internal view {
// solhint-disable-next-line custom-errors
require(msg.sender == s_owner, "Only callable by owner");
}
/// @notice Reverts if called by anyone other than the contract owner.
modifier onlyOwner() {
_validateOwnership();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOwnable {
function owner() external returns (address);
function transferOwnership(address recipient) external;
function acceptOwnership() external;
}{
"remappings": [
"ds-test/=foundry-lib/forge-std/lib/ds-test/src/",
"forge-std/=foundry-lib/forge-std/src/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@arbitrum/=node_modules/@arbitrum/",
"hardhat/=node_modules/hardhat/",
"@eth-optimism/=node_modules/@eth-optimism/",
"@scroll-tech/=node_modules/@scroll-tech/",
"@ensdomains/=node_modules/@ensdomains/",
"@offchainlabs/=node_modules/@offchainlabs/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/"
],
"optimizer": {
"enabled": true,
"runs": 26000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {}
}Contract ABI
API[{"inputs":[{"internalType":"contract IBurnMintERC20","name":"token","type":"address"},{"internalType":"address[]","name":"allowlist","type":"address[]"},{"internalType":"address","name":"armProxy","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":"BadARMSignal","type":"error"},{"inputs":[],"name":"BucketOverfilled","type":"error"},{"inputs":[{"internalType":"address","name":"ramp","type":"address"}],"name":"NonExistentRamp","type":"error"},{"inputs":[],"name":"PermissionsError","type":"error"},{"inputs":[{"internalType":"address","name":"ramp","type":"address"}],"name":"RampAlreadyExists","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":[],"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":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":false,"internalType":"address","name":"offRamp","type":"address"},{"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":"rateLimiterConfig","type":"tuple"}],"name":"OffRampAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"offRamp","type":"address"},{"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":"rateLimiterConfig","type":"tuple"}],"name":"OffRampConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"offRamp","type":"address"}],"name":"OffRampRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"onRamp","type":"address"},{"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":"rateLimiterConfig","type":"tuple"}],"name":"OnRampAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"onRamp","type":"address"},{"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":"rateLimiterConfig","type":"tuple"}],"name":"OnRampConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"onRamp","type":"address"}],"name":"OnRampRemoved","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"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","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":"address","name":"ramp","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"},{"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"}],"internalType":"struct TokenPool.RampUpdate[]","name":"onRamps","type":"tuple[]"},{"components":[{"internalType":"address","name":"ramp","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"},{"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"}],"internalType":"struct TokenPool.RampUpdate[]","name":"offRamps","type":"tuple[]"}],"name":"applyRampUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"offRamp","type":"address"}],"name":"currentOffRampRateLimiterState","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":"address","name":"onRamp","type":"address"}],"name":"currentOnRampRateLimiterState","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":"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":[],"name":"getArmProxy","outputs":[{"internalType":"address","name":"armProxy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOffRamps","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOnRamps","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getToken","outputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"offRamp","type":"address"}],"name":"isOffRamp","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"onRamp","type":"address"}],"name":"isOnRamp","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"originalSender","type":"address"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"lockOrBurn","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"releaseOrMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"offRamp","type":"address"},{"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":"setOffRampRateLimiterConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"onRamp","type":"address"},{"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":"setOnRampRateLimiterConfig","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"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60e06040523480156200001157600080fd5b5060405162002f3338038062002f3383398101604081905262000034916200051d565b82828233806000816200008e5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c157620000c18162000133565b5050506001600160a01b038316620000ec576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808416608052811660a052815115801560c0526200012757604080516000815260208101909152620001279083620001de565b5050505050506200068e565b336001600160a01b038216036200018d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000085565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620001ff576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002945760008382815181106200022357620002236200061a565b602090810291909101015190506200023d6002826200034f565b1562000280576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506200028c8162000646565b905062000202565b5060005b81518110156200034a576000828281518110620002b957620002b96200061a565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002e5575062000337565b620002f26002826200036f565b1562000335576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b620003428162000646565b905062000298565b505050565b600062000366836001600160a01b03841662000386565b90505b92915050565b600062000366836001600160a01b0384166200048a565b600081815260018301602052604081205480156200047f576000620003ad60018362000662565b8554909150600090620003c39060019062000662565b90508181146200042f576000866000018281548110620003e757620003e76200061a565b90600052602060002001549050808760000184815481106200040d576200040d6200061a565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000443576200044362000678565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000369565b600091505062000369565b6000818152600183016020526040812054620004d35750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000369565b50600062000369565b6001600160a01b0381168114620004f257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b80516200051881620004dc565b919050565b6000806000606084860312156200053357600080fd5b83516200054081620004dc565b602085810151919450906001600160401b03808211156200056057600080fd5b818701915087601f8301126200057557600080fd5b8151818111156200058a576200058a620004f5565b8060051b604051601f19603f83011681018181108582111715620005b257620005b2620004f5565b60405291825284820192508381018501918a831115620005d157600080fd5b938501935b82851015620005fa57620005ea856200050b565b84529385019392850192620005d6565b80975050505050505062000611604085016200050b565b90509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016200065b576200065b62000630565b5060010190565b8181038181111562000369576200036962000630565b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05161283d620006f6600039600081816103c301528181610a320152610e71015260008181610249015281816107d50152610ab60152600081816102020152818161092d015281816112b1015281816112f8015261134b015261283d6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c80638627fad6116100d8578063a7cd63b71161008c578063d612b94511610066578063d612b945146103ae578063e0351e13146103c1578063f2fde38b146103e757600080fd5b8063a7cd63b714610380578063b3a3fb4114610388578063c49907b51461039b57600080fd5b80638da5cb5b116100bd5780638da5cb5b146103475780639687544514610365578063a40e69c71461037857600080fd5b80638627fad61461031f578063873813141461033257600080fd5b806354c8a4f31161012f5780637448b3c7116101145780637448b3c7146102955780637787e7ab146102a857806379ba50971461031757600080fd5b806354c8a4f31461026d5780636f32b8721461028257600080fd5b80631d7a74a0116101605780631d7a74a0146101ed57806321df0da7146102005780635246492f1461024757600080fd5b806301ffc9a71461017c578063181f5a77146101a4575b600080fd5b61018f61018a366004612000565b6103fa565b60405190151581526020015b60405180910390f35b6101e06040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e322e3000000000000000000081525081565b60405161019b91906120a6565b61018f6101fb3660046120e2565b610493565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b7f0000000000000000000000000000000000000000000000000000000000000000610222565b61028061027b366004612149565b6104a0565b005b61018f6102903660046120e2565b61051b565b6102806102a336600461228c565b610528565b6102bb6102b63660046120e2565b6105f8565b60405161019b919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b6102806106d6565b61028061032d366004612383565b6107d3565b61033a6109dd565b60405161019b9190612412565b60005473ffffffffffffffffffffffffffffffffffffffff16610222565b6101e06103733660046124ae565b6109ee565b61033a610bdd565b61033a610be9565b6102bb6103963660046120e2565b610bf5565b6102806103a9366004612591565b610cd3565b6102806103bc36600461228c565b610ce7565b7f000000000000000000000000000000000000000000000000000000000000000061018f565b6102806103f53660046120e2565b610da6565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f317fa33400000000000000000000000000000000000000000000000000000000148061048d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600061048d600783610dba565b6104a8610dec565b61051584848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250610e6f92505050565b50505050565b600061048d600483610dba565b610530610dec565b6105398261051b565b61058c576040517f498f12f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602052604090206105bb908261103a565b7f578db78e348076074dbff64a94073a83e9a65aa6766b8c75fdc89282b0e30ed682826040516105ec9291906125f1565b60405180910390a15050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915273ffffffffffffffffffffffffffffffffffffffff8216600090815260066020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261048d906111e9565b60015473ffffffffffffffffffffffffffffffffffffffff163314610757576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610583565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561083e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108629190612649565b15610899576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108a233610493565b6108d8576040517f5307f5ab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108e18361129b565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590527f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b15801561097157600080fd5b505af1158015610985573d6000803e3d6000fd5b505060405185815273ffffffffffffffffffffffffffffffffffffffff871692503391507f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f09060200160405180910390a35050505050565b60606109e960046112d5565b905090565b60606109f93361051b565b610a2f576040517f5307f5ab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b877f00000000000000000000000000000000000000000000000000000000000000008015610a655750610a63600282610dba565b155b15610ab4576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610583565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b439190612649565b15610b7a576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b83866112e2565b610b8c8661131c565b60405186815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a25050604080516020810190915260008152979650505050505050565b60606109e960076112d5565b60606109e960026112d5565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915273ffffffffffffffffffffffffffffffffffffffff8216600090815260096020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261048d906111e9565b610cdb610dec565b610515848484846113bf565b610cef610dec565b610cf882610493565b610d46576040517f498f12f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610583565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020610d75908261103a565b7fb3ba339cfbb8ef80d7a29ce5493051cb90e64fcfa85d7124efc1adfa4c68399f82826040516105ec9291906125f1565b610dae610dec565b610db781611968565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610583565b565b7f0000000000000000000000000000000000000000000000000000000000000000610ec6576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015610f64576000838281518110610ee657610ee6612666565b60200260200101519050610f04816002611a5d90919063ffffffff16565b15610f535760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50610f5d816126c4565b9050610ec9565b5060005b8151811015611035576000828281518110610f8557610f85612666565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610fc95750611025565b610fd4600282611a7f565b156110235760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b61102e816126c4565b9050610f68565b505050565b815460009061106390700100000000000000000000000000000000900463ffffffff16426126fc565b9050801561110557600183015483546110ab916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416611aa1565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461112b916fffffffffffffffffffffffffffffffff9081169116611ac9565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906111dc90849061270f565b60405180910390a1505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261127782606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261125b91906126fc565b85608001516fffffffffffffffffffffffffffffffff16611aa1565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b336000908152600960205260409020610db790827f0000000000000000000000000000000000000000000000000000000000000000611adf565b60606000610de583611e62565b336000908152600660205260409020610db790827f0000000000000000000000000000000000000000000000000000000000000000611adf565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b1580156113a457600080fd5b505af11580156113b8573d6000803e3d6000fd5b5050505050565b6113c7610dec565b60005b838110156116e45760008585838181106113e6576113e6612666565b905060a002018036038101906113fc919061274b565b90508060200151156115d457805161141690600490611a7f565b15611587576040805160a08101825282820180516020908101516fffffffffffffffffffffffffffffffff908116845263ffffffff4281168386019081528451511515868801908152855185015184166060880190815286518901518516608089019081528a5173ffffffffffffffffffffffffffffffffffffffff1660009081526006909752958990209751885493519251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff939095167001000000000000000000000000000000009081027fffffffffffffffffffffffff0000000000000000000000000000000000000000909516918716919091179390931791909116929092178655905192518216029116176001909201919091558251905191517f0b594bb0555ff7b252e0c789ccc9d8903fec294172064308727d570505cee1ac9261157a92916125f1565b60405180910390a16116d3565b80516040517fd3eb6bc500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610583565b80516115e290600490611a5d565b1561168657805173ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604080822080547fffffffffffffffffffffff00000000000000000000000000000000000000000016815560010191909155815190517f7fd064821314ad863a0714a3f1229375ace6b6427ed5544b7b2ba1c47b1b52949161157a9173ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b80516040517f498f12f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610583565b506116dd816126c4565b90506113ca565b5060005b818110156113b857600083838381811061170457611704612666565b905060a0020180360381019061171a919061274b565b90508060200151156118a557805161173490600790611a7f565b15611587576040805160a08101825282820180516020908101516fffffffffffffffffffffffffffffffff908116845263ffffffff4281168386019081528451511515868801908152855185015184166060880190815286518901518516608089019081528a5173ffffffffffffffffffffffffffffffffffffffff1660009081526009909752958990209751885493519251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff939095167001000000000000000000000000000000009081027fffffffffffffffffffffffff0000000000000000000000000000000000000000909516918716919091179390931791909116929092178655905192518216029116176001909201919091558251905191517f395b7374909d2b54e5796f53c898ebf41d767c86c78ea86519acf2b805852d889261189892916125f1565b60405180910390a1611957565b80516118b390600790611a5d565b1561168657805173ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604080822080547fffffffffffffffffffffff00000000000000000000000000000000000000000016815560010191909155815190517fcf91daec21e3510e2f2aea4b09d08c235d5c6844980be709f282ef591dbf420c916118989173ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b50611961816126c4565b90506116e8565b3373ffffffffffffffffffffffffffffffffffffffff8216036119e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610583565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000610de58373ffffffffffffffffffffffffffffffffffffffff8416611ebe565b6000610de58373ffffffffffffffffffffffffffffffffffffffff8416611fb1565b6000611ac085611ab1848661279c565b611abb90876127b3565b611ac9565b95945050505050565b6000818310611ad85781610de5565b5090919050565b825474010000000000000000000000000000000000000000900460ff161580611b06575081155b15611b1057505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090611b5690700100000000000000000000000000000000900463ffffffff16426126fc565b90508015611c165781831115611b98576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154611bd29083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16611aa1565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015611ccd5773ffffffffffffffffffffffffffffffffffffffff8416611c75576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610583565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610583565b84831015611de05760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290611d1190826126fc565b611d1b878a6126fc565b611d2591906127b3565b611d2f91906127c6565b905073ffffffffffffffffffffffffffffffffffffffff8616611d88576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610583565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610583565b611dea85846126fc565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611eb257602002820191906000526020600020905b815481526020019060010190808311611e9e575b50505050509050919050565b60008181526001830160205260408120548015611fa7576000611ee26001836126fc565b8554909150600090611ef6906001906126fc565b9050818114611f5b576000866000018281548110611f1657611f16612666565b9060005260206000200154905080876000018481548110611f3957611f39612666565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611f6c57611f6c612801565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061048d565b600091505061048d565b6000818152600183016020526040812054611ff85750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561048d565b50600061048d565b60006020828403121561201257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610de557600080fd5b6000815180845260005b818110156120685760208185018101518683018201520161204c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610de56020830184612042565b803573ffffffffffffffffffffffffffffffffffffffff811681146120dd57600080fd5b919050565b6000602082840312156120f457600080fd5b610de5826120b9565b60008083601f84011261210f57600080fd5b50813567ffffffffffffffff81111561212757600080fd5b6020830191508360208260051b850101111561214257600080fd5b9250929050565b6000806000806040858703121561215f57600080fd5b843567ffffffffffffffff8082111561217757600080fd5b612183888389016120fd565b9096509450602087013591508082111561219c57600080fd5b506121a9878288016120fd565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715612207576122076121b5565b60405290565b8015158114610db757600080fd5b80356fffffffffffffffffffffffffffffffff811681146120dd57600080fd5b60006060828403121561224d57600080fd5b6122556121e4565b905081356122628161220d565b81526122706020830161221b565b60208201526122816040830161221b565b604082015292915050565b6000806080838503121561229f57600080fd5b6122a8836120b9565b91506122b7846020850161223b565b90509250929050565b600082601f8301126122d157600080fd5b813567ffffffffffffffff808211156122ec576122ec6121b5565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612332576123326121b5565b8160405283815286602085880101111561234b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803567ffffffffffffffff811681146120dd57600080fd5b600080600080600060a0868803121561239b57600080fd5b853567ffffffffffffffff808211156123b357600080fd5b6123bf89838a016122c0565b96506123cd602089016120b9565b9550604088013594506123e26060890161236b565b935060808801359150808211156123f857600080fd5b50612405888289016122c0565b9150509295509295909350565b6020808252825182820181905260009190848201906040850190845b8181101561246057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161242e565b50909695505050505050565b60008083601f84011261247e57600080fd5b50813567ffffffffffffffff81111561249657600080fd5b60208301915083602082850101111561214257600080fd5b600080600080600080600060a0888a0312156124c957600080fd5b6124d2886120b9565b9650602088013567ffffffffffffffff808211156124ef57600080fd5b6124fb8b838c0161246c565b909850965060408a0135955086915061251660608b0161236b565b945060808a013591508082111561252c57600080fd5b506125398a828b0161246c565b989b979a50959850939692959293505050565b60008083601f84011261255e57600080fd5b50813567ffffffffffffffff81111561257657600080fd5b60208301915083602060a08302850101111561214257600080fd5b600080600080604085870312156125a757600080fd5b843567ffffffffffffffff808211156125bf57600080fd5b6125cb8883890161254c565b909650945060208701359150808211156125e457600080fd5b506121a98782880161254c565b73ffffffffffffffffffffffffffffffffffffffff8316815260808101610de560208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561265b57600080fd5b8151610de58161220d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036126f5576126f5612695565b5060010190565b8181038181111561048d5761048d612695565b6060810161048d82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060a0828403121561275d57600080fd5b6127656121e4565b61276e836120b9565b8152602083013561277e8161220d565b6020820152612790846040850161223b565b60408201529392505050565b808202811582820484141761048d5761048d612695565b8082018082111561048d5761048d612695565b6000826127fc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000b40a3109075965cc09e93719e33e748abf680dae0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101775760003560e01c80638627fad6116100d8578063a7cd63b71161008c578063d612b94511610066578063d612b945146103ae578063e0351e13146103c1578063f2fde38b146103e757600080fd5b8063a7cd63b714610380578063b3a3fb4114610388578063c49907b51461039b57600080fd5b80638da5cb5b116100bd5780638da5cb5b146103475780639687544514610365578063a40e69c71461037857600080fd5b80638627fad61461031f578063873813141461033257600080fd5b806354c8a4f31161012f5780637448b3c7116101145780637448b3c7146102955780637787e7ab146102a857806379ba50971461031757600080fd5b806354c8a4f31461026d5780636f32b8721461028257600080fd5b80631d7a74a0116101605780631d7a74a0146101ed57806321df0da7146102005780635246492f1461024757600080fd5b806301ffc9a71461017c578063181f5a77146101a4575b600080fd5b61018f61018a366004612000565b6103fa565b60405190151581526020015b60405180910390f35b6101e06040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e322e3000000000000000000081525081565b60405161019b91906120a6565b61018f6101fb3660046120e2565b610493565b7f000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a5b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b7f000000000000000000000000b40a3109075965cc09e93719e33e748abf680dae610222565b61028061027b366004612149565b6104a0565b005b61018f6102903660046120e2565b61051b565b6102806102a336600461228c565b610528565b6102bb6102b63660046120e2565b6105f8565b60405161019b919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b6102806106d6565b61028061032d366004612383565b6107d3565b61033a6109dd565b60405161019b9190612412565b60005473ffffffffffffffffffffffffffffffffffffffff16610222565b6101e06103733660046124ae565b6109ee565b61033a610bdd565b61033a610be9565b6102bb6103963660046120e2565b610bf5565b6102806103a9366004612591565b610cd3565b6102806103bc36600461228c565b610ce7565b7f000000000000000000000000000000000000000000000000000000000000000061018f565b6102806103f53660046120e2565b610da6565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f317fa33400000000000000000000000000000000000000000000000000000000148061048d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600061048d600783610dba565b6104a8610dec565b61051584848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250610e6f92505050565b50505050565b600061048d600483610dba565b610530610dec565b6105398261051b565b61058c576040517f498f12f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602052604090206105bb908261103a565b7f578db78e348076074dbff64a94073a83e9a65aa6766b8c75fdc89282b0e30ed682826040516105ec9291906125f1565b60405180910390a15050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915273ffffffffffffffffffffffffffffffffffffffff8216600090815260066020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261048d906111e9565b60015473ffffffffffffffffffffffffffffffffffffffff163314610757576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610583565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b7f000000000000000000000000b40a3109075965cc09e93719e33e748abf680dae73ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561083e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108629190612649565b15610899576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108a233610493565b6108d8576040517f5307f5ab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108e18361129b565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590527f000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a16906340c10f1990604401600060405180830381600087803b15801561097157600080fd5b505af1158015610985573d6000803e3d6000fd5b505060405185815273ffffffffffffffffffffffffffffffffffffffff871692503391507f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f09060200160405180910390a35050505050565b60606109e960046112d5565b905090565b60606109f93361051b565b610a2f576040517f5307f5ab00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b877f00000000000000000000000000000000000000000000000000000000000000008015610a655750610a63600282610dba565b155b15610ab4576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610583565b7f000000000000000000000000b40a3109075965cc09e93719e33e748abf680dae73ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b439190612649565b15610b7a576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b83866112e2565b610b8c8661131c565b60405186815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a25050604080516020810190915260008152979650505050505050565b60606109e960076112d5565b60606109e960026112d5565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915273ffffffffffffffffffffffffffffffffffffffff8216600090815260096020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261048d906111e9565b610cdb610dec565b610515848484846113bf565b610cef610dec565b610cf882610493565b610d46576040517f498f12f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610583565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020610d75908261103a565b7fb3ba339cfbb8ef80d7a29ce5493051cb90e64fcfa85d7124efc1adfa4c68399f82826040516105ec9291906125f1565b610dae610dec565b610db781611968565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610583565b565b7f0000000000000000000000000000000000000000000000000000000000000000610ec6576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015610f64576000838281518110610ee657610ee6612666565b60200260200101519050610f04816002611a5d90919063ffffffff16565b15610f535760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50610f5d816126c4565b9050610ec9565b5060005b8151811015611035576000828281518110610f8557610f85612666565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610fc95750611025565b610fd4600282611a7f565b156110235760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b61102e816126c4565b9050610f68565b505050565b815460009061106390700100000000000000000000000000000000900463ffffffff16426126fc565b9050801561110557600183015483546110ab916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416611aa1565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461112b916fffffffffffffffffffffffffffffffff9081169116611ac9565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906111dc90849061270f565b60405180910390a1505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261127782606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261125b91906126fc565b85608001516fffffffffffffffffffffffffffffffff16611aa1565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b336000908152600960205260409020610db790827f000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a611adf565b60606000610de583611e62565b336000908152600660205260409020610db790827f000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a611adf565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a73ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b1580156113a457600080fd5b505af11580156113b8573d6000803e3d6000fd5b5050505050565b6113c7610dec565b60005b838110156116e45760008585838181106113e6576113e6612666565b905060a002018036038101906113fc919061274b565b90508060200151156115d457805161141690600490611a7f565b15611587576040805160a08101825282820180516020908101516fffffffffffffffffffffffffffffffff908116845263ffffffff4281168386019081528451511515868801908152855185015184166060880190815286518901518516608089019081528a5173ffffffffffffffffffffffffffffffffffffffff1660009081526006909752958990209751885493519251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff939095167001000000000000000000000000000000009081027fffffffffffffffffffffffff0000000000000000000000000000000000000000909516918716919091179390931791909116929092178655905192518216029116176001909201919091558251905191517f0b594bb0555ff7b252e0c789ccc9d8903fec294172064308727d570505cee1ac9261157a92916125f1565b60405180910390a16116d3565b80516040517fd3eb6bc500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610583565b80516115e290600490611a5d565b1561168657805173ffffffffffffffffffffffffffffffffffffffff1660009081526006602052604080822080547fffffffffffffffffffffff00000000000000000000000000000000000000000016815560010191909155815190517f7fd064821314ad863a0714a3f1229375ace6b6427ed5544b7b2ba1c47b1b52949161157a9173ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b80516040517f498f12f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610583565b506116dd816126c4565b90506113ca565b5060005b818110156113b857600083838381811061170457611704612666565b905060a0020180360381019061171a919061274b565b90508060200151156118a557805161173490600790611a7f565b15611587576040805160a08101825282820180516020908101516fffffffffffffffffffffffffffffffff908116845263ffffffff4281168386019081528451511515868801908152855185015184166060880190815286518901518516608089019081528a5173ffffffffffffffffffffffffffffffffffffffff1660009081526009909752958990209751885493519251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff939095167001000000000000000000000000000000009081027fffffffffffffffffffffffff0000000000000000000000000000000000000000909516918716919091179390931791909116929092178655905192518216029116176001909201919091558251905191517f395b7374909d2b54e5796f53c898ebf41d767c86c78ea86519acf2b805852d889261189892916125f1565b60405180910390a1611957565b80516118b390600790611a5d565b1561168657805173ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604080822080547fffffffffffffffffffffff00000000000000000000000000000000000000000016815560010191909155815190517fcf91daec21e3510e2f2aea4b09d08c235d5c6844980be709f282ef591dbf420c916118989173ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b50611961816126c4565b90506116e8565b3373ffffffffffffffffffffffffffffffffffffffff8216036119e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610583565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000610de58373ffffffffffffffffffffffffffffffffffffffff8416611ebe565b6000610de58373ffffffffffffffffffffffffffffffffffffffff8416611fb1565b6000611ac085611ab1848661279c565b611abb90876127b3565b611ac9565b95945050505050565b6000818310611ad85781610de5565b5090919050565b825474010000000000000000000000000000000000000000900460ff161580611b06575081155b15611b1057505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090611b5690700100000000000000000000000000000000900463ffffffff16426126fc565b90508015611c165781831115611b98576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154611bd29083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16611aa1565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015611ccd5773ffffffffffffffffffffffffffffffffffffffff8416611c75576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610583565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610583565b84831015611de05760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290611d1190826126fc565b611d1b878a6126fc565b611d2591906127b3565b611d2f91906127c6565b905073ffffffffffffffffffffffffffffffffffffffff8616611d88576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610583565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610583565b611dea85846126fc565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611eb257602002820191906000526020600020905b815481526020019060010190808311611e9e575b50505050509050919050565b60008181526001830160205260408120548015611fa7576000611ee26001836126fc565b8554909150600090611ef6906001906126fc565b9050818114611f5b576000866000018281548110611f1657611f16612666565b9060005260206000200154905080876000018481548110611f3957611f39612666565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611f6c57611f6c612801565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061048d565b600091505061048d565b6000818152600183016020526040812054611ff85750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561048d565b50600061048d565b60006020828403121561201257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610de557600080fd5b6000815180845260005b818110156120685760208185018101518683018201520161204c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610de56020830184612042565b803573ffffffffffffffffffffffffffffffffffffffff811681146120dd57600080fd5b919050565b6000602082840312156120f457600080fd5b610de5826120b9565b60008083601f84011261210f57600080fd5b50813567ffffffffffffffff81111561212757600080fd5b6020830191508360208260051b850101111561214257600080fd5b9250929050565b6000806000806040858703121561215f57600080fd5b843567ffffffffffffffff8082111561217757600080fd5b612183888389016120fd565b9096509450602087013591508082111561219c57600080fd5b506121a9878288016120fd565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715612207576122076121b5565b60405290565b8015158114610db757600080fd5b80356fffffffffffffffffffffffffffffffff811681146120dd57600080fd5b60006060828403121561224d57600080fd5b6122556121e4565b905081356122628161220d565b81526122706020830161221b565b60208201526122816040830161221b565b604082015292915050565b6000806080838503121561229f57600080fd5b6122a8836120b9565b91506122b7846020850161223b565b90509250929050565b600082601f8301126122d157600080fd5b813567ffffffffffffffff808211156122ec576122ec6121b5565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612332576123326121b5565b8160405283815286602085880101111561234b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803567ffffffffffffffff811681146120dd57600080fd5b600080600080600060a0868803121561239b57600080fd5b853567ffffffffffffffff808211156123b357600080fd5b6123bf89838a016122c0565b96506123cd602089016120b9565b9550604088013594506123e26060890161236b565b935060808801359150808211156123f857600080fd5b50612405888289016122c0565b9150509295509295909350565b6020808252825182820181905260009190848201906040850190845b8181101561246057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161242e565b50909695505050505050565b60008083601f84011261247e57600080fd5b50813567ffffffffffffffff81111561249657600080fd5b60208301915083602082850101111561214257600080fd5b600080600080600080600060a0888a0312156124c957600080fd5b6124d2886120b9565b9650602088013567ffffffffffffffff808211156124ef57600080fd5b6124fb8b838c0161246c565b909850965060408a0135955086915061251660608b0161236b565b945060808a013591508082111561252c57600080fd5b506125398a828b0161246c565b989b979a50959850939692959293505050565b60008083601f84011261255e57600080fd5b50813567ffffffffffffffff81111561257657600080fd5b60208301915083602060a08302850101111561214257600080fd5b600080600080604085870312156125a757600080fd5b843567ffffffffffffffff808211156125bf57600080fd5b6125cb8883890161254c565b909650945060208701359150808211156125e457600080fd5b506121a98782880161254c565b73ffffffffffffffffffffffffffffffffffffffff8316815260808101610de560208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561265b57600080fd5b8151610de58161220d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036126f5576126f5612695565b5060010190565b8181038181111561048d5761048d612695565b6060810161048d82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060a0828403121561275d57600080fd5b6127656121e4565b61276e836120b9565b8152602083013561277e8161220d565b6020820152612790846040850161223b565b60408201529392505050565b808202811582820484141761048d5761048d612695565b8082018082111561048d5761048d612695565b6000826127fc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000b40a3109075965cc09e93719e33e748abf680dae0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : token (address): 0x044a6B4b561af69D2319A2f4be5Ec327a6975D0a
Arg [1] : allowlist (address[]):
Arg [2] : armProxy (address): 0xb40A3109075965cc09E93719e33E748abf680dAe
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000044a6b4b561af69d2319a2f4be5ec327a6975d0a
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 000000000000000000000000b40a3109075965cc09e93719e33e748abf680dae
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.