Overview
GLMR Balance
GLMR Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
10577810 | 3 hrs ago | 12.83136843 GLMR | ||||
10574955 | 8 hrs ago | 12.80226974 GLMR | ||||
10573329 | 11 hrs ago | 14.3554261 GLMR | ||||
10572336 | 12 hrs ago | 14.3554261 GLMR | ||||
10570081 | 16 hrs ago | 14.33141432 GLMR | ||||
10569085 | 18 hrs ago | 14.33141432 GLMR | ||||
10567594 | 21 hrs ago | 14.33141432 GLMR | ||||
10566969 | 22 hrs ago | 13.76036597 GLMR | ||||
10566346 | 23 hrs ago | 14.17459996 GLMR | ||||
10566214 | 23 hrs ago | 14.17459996 GLMR | ||||
10564184 | 26 hrs ago | 14.17459996 GLMR | ||||
10559203 | 35 hrs ago | 14.23999439 GLMR | ||||
10555286 | 41 hrs ago | 13.9041594 GLMR | ||||
10555115 | 42 hrs ago | 13.9041594 GLMR | ||||
10555033 | 42 hrs ago | 13.9041594 GLMR | ||||
10550724 | 2 days ago | 13.78440488 GLMR | ||||
10550529 | 2 days ago | 13.78440488 GLMR | ||||
10549838 | 2 days ago | 13.78440488 GLMR | ||||
10549102 | 2 days ago | 13.78440488 GLMR | ||||
10546487 | 2 days ago | 13.78440488 GLMR | ||||
10546375 | 2 days ago | 13.78440488 GLMR | ||||
10545039 | 2 days ago | 13.75671401 GLMR | ||||
10542876 | 2 days ago | 13.75671401 GLMR | ||||
10542561 | 2 days ago | 13.75671401 GLMR | ||||
10535351 | 3 days ago | 14.30686383 GLMR |
Loading...
Loading
Contract Name:
WormholeUnwrapperAdapter
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; import {IERC20} from "@openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {XERC20Lockbox} from "@protocol/xWELL/XERC20Lockbox.sol"; import {WormholeBridgeAdapter} from "@protocol/xWELL/WormholeBridgeAdapter.sol"; /// @notice Wormhole Unwrapper xERC20 Token Bridge adapter /// Allows users coming from an external chain back to Moonbeam /// to unwrap their xWELL tokens into the underling WELL token. contract WormholeUnwrapperAdapter is WormholeBridgeAdapter { /// @notice lockbox for xERC20, can only be set one time address public lockbox; /// @notice emitted when the lockbox is set /// @param lockbox address of the lockbox event LockboxSet(address lockbox); /// @notice set the lockbox contract address /// @param _lockbox address of the lockbox function setLockbox(address _lockbox) external onlyOwner { require( lockbox == address(0), "WormholeUnwrapperAdapter: lockbox already set" ); lockbox = _lockbox; emit LockboxSet(_lockbox); } /// @notice Bridge in funds from the chain to the given user /// by minting tokens to this contract, then using those tokens to withdraw from the lockbox /// @param chainId chain id funds are bridged from /// @param user to bridge in funds to /// @param amount of xERC20 tokens to bridge in function _bridgeIn( uint256 chainId, address user, uint256 amount ) internal override { /// mint tokens to this address super._bridgeIn(chainId, address(this), amount); /// approve lockbox to burn tokens from this address IERC20(address(xERC20)).approve(lockbox, amount); /// withdraw tokens to the user XERC20Lockbox(lockbox).withdrawTo(user, amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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); }
pragma solidity 0.8.19; import {SafeERC20} from "@openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20} from "@openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import {IXERC20} from "@protocol/xWELL/interfaces/IXERC20.sol"; import {IXERC20Lockbox} from "@protocol/xWELL/interfaces/IXERC20Lockbox.sol"; /// Invariants: /// xERC20 token can only have total supply of max 5b tokens /// xERC20 token can only have total supply lte WELL ERC20 token balance of this contract contract XERC20Lockbox is IXERC20Lockbox { using SafeERC20 for IERC20; /// @notice The XERC20 token of this contract IXERC20 public immutable XERC20; /// @notice The ERC20 token of this contract IERC20 public immutable ERC20; /// @param xerc20 The address of the XERC20 contract /// @param erc20 The address of the ERC20 contract constructor(address xerc20, address erc20) { XERC20 = IXERC20(xerc20); ERC20 = IERC20(erc20); } /// @notice Deposit ERC20 tokens into the lockbox /// @param amount The amount of tokens to deposit function deposit(uint256 amount) external { _deposit(msg.sender, amount); } /// @notice Deposit ERC20 tokens into the lockbox, and send the XERC20 to a user /// @param to The user to send the XERC20 to /// @param amount The amount of tokens to deposit function depositTo(address to, uint256 amount) external { _deposit(to, amount); } /// @notice Withdraw ERC20 tokens from the lockbox /// @param amount The amount of tokens to withdraw function withdraw(uint256 amount) external { _withdraw(msg.sender, amount); } /// @notice Withdraw tokens from the lockbox /// @param to The user to withdraw to /// @param amount The amount of tokens to withdraw function withdrawTo(address to, uint256 amount) external { _withdraw(to, amount); } /// @notice Withdraw tokens from the lockbox /// @param to The user to withdraw to /// @param amount The amount of tokens to withdraw function _withdraw(address to, uint256 amount) internal { emit Withdraw(to, amount); XERC20.burn(msg.sender, amount); ERC20.safeTransfer(to, amount); } /// @notice Deposit tokens into the lockbox /// @param to The address to send the XERC20 to /// @param amount The amount of tokens to deposit function _deposit(address to, uint256 amount) internal { ERC20.safeTransferFrom(msg.sender, address(this), amount); XERC20.mint(to, amount); emit Deposit(to, amount); } }
pragma solidity 0.8.19; import {xERC20BridgeAdapter} from "@protocol/xWELL/xERC20BridgeAdapter.sol"; import {SafeERC20} from "@openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {SafeCast} from "@openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; import {IERC20} from "@openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IXERC20} from "@protocol/xWELL/interfaces/IXERC20.sol"; import {IWormhole} from "@protocol/wormhole/IWormhole.sol"; import {IWormholeRelayer} from "@protocol/wormhole/IWormholeRelayer.sol"; import {IWormholeReceiver} from "@protocol/wormhole/IWormholeReceiver.sol"; import {WormholeTrustedSender} from "@protocol/Governance/WormholeTrustedSender.sol"; /// @notice Wormhole xERC20 Token Bridge adapter contract WormholeBridgeAdapter is IWormholeReceiver, xERC20BridgeAdapter, WormholeTrustedSender { using SafeCast for uint256; /// --------------------------------------------------------- /// --------------------------------------------------------- /// ------------------ SINGLE STORAGE SLOT ------------------ /// --------------------------------------------------------- /// --------------------------------------------------------- /// @dev packing these variables into a single slot saves a /// COLD SLOAD on bridge out operations. /// @notice gas limit for wormhole relayer, changeable incase gas prices change on external network uint96 public gasLimit = 300_000; /// @notice address of the wormhole relayer cannot be changed by owner /// because the relayer contract is a proxy and should never change its address IWormholeRelayer public wormholeRelayer; /// --------------------------------------------------------- /// --------------------------------------------------------- /// ----------------------- MAPPINGS ------------------------ /// --------------------------------------------------------- /// --------------------------------------------------------- /// @notice nonces that have already been processed mapping(bytes32 => bool) public processedNonces; /// @notice chain id of the target chain to address for bridging /// starts off mapped to itself, but can be changed by governance mapping(uint16 => address) public targetAddress; /// --------------------------------------------------------- /// --------------------------------------------------------- /// ------------------------ EVENTS ------------------------- /// --------------------------------------------------------- /// --------------------------------------------------------- /// @notice chain id of the target chain to address for bridging /// @param dstChainId source chain id tokens were bridged from /// @param tokenReceiver address to receive tokens on destination chain /// @param amount of tokens bridged in event TokensSent( uint16 indexed dstChainId, address indexed tokenReceiver, uint256 amount ); /// @notice chain id of the target chain to address for bridging /// @param dstChainId destination chain id to send tokens to /// @param target address to send tokens to event TargetAddressUpdated( uint16 indexed dstChainId, address indexed target ); /// @notice emitted when the gas limit changes on external chains /// @param oldGasLimit old gas limit /// @param newGasLimit new gas limit event GasLimitUpdated(uint96 oldGasLimit, uint96 newGasLimit); /// --------------------------------------------------------- /// --------------------------------------------------------- /// ---------------------- INITIALIZE ----------------------- /// --------------------------------------------------------- /// --------------------------------------------------------- /// @notice Initialize the Wormhole bridge /// @param newxerc20 xERC20 token address /// @param newOwner contract owner address /// @param wormholeRelayerAddress address of the wormhole relayer /// @param targetChain chain id of the target chain to address for bridging function initialize( address newxerc20, address newOwner, address wormholeRelayerAddress, uint16 targetChain ) public initializer { __Ownable_init(); _transferOwnership(newOwner); _setxERC20(newxerc20); wormholeRelayer = IWormholeRelayer(wormholeRelayerAddress); /// initialize contract to trust this exact same address on an external chain /// @dev the external chain contracts MUST HAVE THE SAME ADDRESS on the external chain targetAddress[targetChain] = address(this); _addTrustedSender(address(this), targetChain); gasLimit = 300_000; /// @dev default starting gas limit for relayer } /// -------------------------------------------------------- /// -------------------------------------------------------- /// ---------------- Admin Only Functions ------------------ /// -------------------------------------------------------- /// -------------------------------------------------------- /// @notice set a gas limit for the relayer on the external chain /// should only be called if there is a change in gas prices on the external chain /// @param newGasLimit new gas limit to set function setGasLimit(uint96 newGasLimit) external onlyOwner { uint96 oldGasLimit = gasLimit; gasLimit = newGasLimit; emit GasLimitUpdated(oldGasLimit, newGasLimit); } /// @notice remove trusted senders from external chains /// @param _trustedSenders array of trusted senders to remove function removeTrustedSenders( WormholeTrustedSender.TrustedSender[] memory _trustedSenders ) external onlyOwner { _removeTrustedSenders(_trustedSenders); } /// @notice add trusted senders from external chains /// @param _trustedSenders array of trusted senders to add function addTrustedSenders( WormholeTrustedSender.TrustedSender[] memory _trustedSenders ) external onlyOwner { _addTrustedSenders(_trustedSenders); } /// @notice add map of target addresses for external chains /// @dev there is no check here to ensure there isn't an existing configuration /// ensure the proper add or remove is being called when using this function /// @param _chainConfig array of chainids to addresses to add function setTargetAddresses( WormholeTrustedSender.TrustedSender[] memory _chainConfig ) external onlyOwner { for (uint256 i = 0; i < _chainConfig.length; i++) { targetAddress[_chainConfig[i].chainId] = _chainConfig[i].addr; emit TargetAddressUpdated( _chainConfig[i].chainId, _chainConfig[i].addr ); } } /// -------------------------------------------------------- /// -------------------------------------------------------- /// ---------------- View Only Functions ------------------- /// -------------------------------------------------------- /// -------------------------------------------------------- /// @notice Estimate bridge cost to bridge out to a destination chain /// @param dstChainId Destination chain id function bridgeCost( uint16 dstChainId ) public view returns (uint256 gasCost) { (gasCost, ) = wormholeRelayer.quoteEVMDeliveryPrice( dstChainId, 0, gasLimit ); } /// -------------------------------------------------------- /// -------------------------------------------------------- /// -------------------- Bridge In/Out --------------------- /// -------------------------------------------------------- /// -------------------------------------------------------- /// @notice Bridge Out Funds to an external chain. /// Callable by the users to bridge out their funds to an external chain. /// If a user sends tokens to the token contract on the external chain, /// that call will revert, and the tokens will be lost permanently. /// @param user to send funds from, should be msg.sender in all cases /// @param targetChain Destination chain id /// @param amount Amount of xERC20 to bridge out /// @param to Address to receive funds on destination chain function _bridgeOut( address user, uint256 targetChain, uint256 amount, address to ) internal override { uint16 targetChainId = targetChain.toUint16(); uint256 cost = bridgeCost(targetChainId); require(msg.value == cost, "WormholeBridge: cost not equal to quote"); require( targetAddress[targetChainId] != address(0), "WormholeBridge: invalid target chain" ); /// user must burn xERC20 tokens first _burnTokens(user, amount); wormholeRelayer.sendPayloadToEvm{value: cost}( targetChainId, targetAddress[targetChainId], abi.encode(to, amount), // payload 0, /// no receiver value allowed, only message passing gasLimit ); emit TokensSent(targetChainId, to, amount); } /// @notice callable only by the wormhole relayer /// @param payload the payload of the message, contains the to and amount /// additional vaas, unused parameter /// @param senderAddress the address of the sender on the source chain, bytes32 encoded /// @param sourceChain the chain id of the source chain /// @param nonce the unique message ID function receiveWormholeMessages( bytes memory payload, bytes[] memory, // additionalVaas bytes32 senderAddress, uint16 sourceChain, bytes32 nonce ) external payable override { require(msg.value == 0, "WormholeBridge: no value allowed"); require( msg.sender == address(wormholeRelayer), "WormholeBridge: only relayer allowed" ); require( isTrustedSender(sourceChain, senderAddress), "WormholeBridge: sender not trusted" ); require( !processedNonces[nonce], "WormholeBridge: message already processed" ); processedNonces[nonce] = true; // Parse the payload and do the corresponding actions! (address to, uint256 amount) = abi.decode(payload, (address, uint256)); /// mint tokens and emit events _bridgeIn(sourceChain, to, amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to * 0 before setting it to a non-zero value. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
pragma solidity 0.8.19; interface IXERC20 { /** * @notice Emits when a limit is set * * @param bridge The address of the bridge we are setting the limit too * @param bufferCap The updated buffer cap for the bridge */ event BridgeLimitsSet(address indexed bridge, uint256 bufferCap); /** * @notice Returns the max limit of a minter * * @param _minter The minter we are viewing the limits of * @return _limit The limit the minter has */ function mintingMaxLimitOf( address _minter ) external view returns (uint256 _limit); /** * @notice Returns the max limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningMaxLimitOf( address _bridge ) external view returns (uint256 _limit); /** * @notice Returns the current limit of a minter * * @param _minter The minter we are viewing the limits of * @return _limit The limit the minter has */ function mintingCurrentLimitOf( address _minter ) external view returns (uint256 _limit); /** * @notice Returns the current limit of a bridge * * @param _bridge the bridge we are viewing the limits of * @return _limit The limit the bridge has */ function burningCurrentLimitOf( address _bridge ) external view returns (uint256 _limit); /** * @notice Mints tokens for a user * @dev Can only be called by a minter * @param _user The address of the user who needs tokens minted * @param _amount The amount of tokens being minted */ function mint(address _user, uint256 _amount) external; /** * @notice Burns tokens for a user * @dev Can only be called by a minter * @param _user The address of the user who needs tokens burned * @param _amount The amount of tokens being burned */ function burn(address _user, uint256 _amount) external; }
pragma solidity 0.8.19; interface IXERC20Lockbox { /** * @notice Emitted when tokens are deposited into the lockbox */ event Deposit(address _sender, uint256 _amount); /** * @notice Emitted when tokens are withdrawn from the lockbox */ event Withdraw(address _sender, uint256 _amount); /** * @notice Deposit ERC20 tokens into the lockbox * * @param _amount The amount of tokens to deposit */ function deposit(uint256 _amount) external; /** * @notice Deposit ERC20 tokens into the lockbox, and send the XERC20 to a user * * @param _user The user to send the XERC20 to * @param _amount The amount of tokens to deposit */ function depositTo(address _user, uint256 _amount) external; /** * @notice Withdraw ERC20 tokens from the lockbox * * @param _amount The amount of tokens to withdraw */ function withdraw(uint256 _amount) external; /** * @notice Withdraw ERC20 tokens from the lockbox * * @param _user The user to withdraw to * @param _amount The amount of tokens to withdraw */ function withdrawTo(address _user, uint256 _amount) external; }
pragma solidity 0.8.19; import {Ownable2StepUpgradeable} from "@openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol"; import {SafeERC20} from "@openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20} from "@openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IXERC20} from "@protocol/xWELL/interfaces/IXERC20.sol"; /// @notice Abstract Upgradeable xERC20 Adapter Contract abstract contract xERC20BridgeAdapter is Ownable2StepUpgradeable { using SafeERC20 for IERC20; /// @notice address of the xERC20 token IXERC20 public xERC20; /// -------------------------------------------------------- /// -------------------------------------------------------- /// ------------------------ Events ------------------------ /// -------------------------------------------------------- /// -------------------------------------------------------- /// @notice emitted when tokens are bridged out /// @param dstChainId destination chain id to send tokens to /// @param bridgeUser user who bridged out tokens /// @param tokenReceiver address to receive tokens on destination chain /// @param amount of tokens bridged out event BridgedOut( uint256 indexed dstChainId, address indexed bridgeUser, address indexed tokenReceiver, uint256 amount ); /// @notice emitted when tokens are bridged in /// @param srcChainId source chain id tokens were bridged from /// @param tokenReceiver address to receive tokens on destination chain /// @param amount of tokens bridged in event BridgedIn( uint256 indexed srcChainId, address indexed tokenReceiver, uint256 amount ); /// @notice ensure logic contract is unusable constructor() { _disableInitializers(); } /// @notice Bridge Out Funds to an external chain /// @param dstChainId Destination chain id /// @param amount Amount of xERC20 to bridge out /// @param to Address to receive funds on destination chain function bridge( uint256 dstChainId, uint256 amount, address to ) external payable virtual { _bridgeOut(msg.sender, dstChainId, amount, to); emit BridgedOut(dstChainId, msg.sender, to, amount); } /// @notice set the xERC20 token /// @param newxerc20 address of the xERC20 token function _setxERC20(address newxerc20) internal { xERC20 = IXERC20(newxerc20); } /// @notice Bridge out funds from the chain from the given user /// by burning their tokens. The bridge out function must call /// this function in the overridden bridge out function. /// @param user to bridge out funds from /// @param amount of xERC20 tokens to bridge out function _burnTokens(address user, uint256 amount) internal { xERC20.burn(user, amount); } /// @notice Bridge in funds from the chain from the given user /// by minting tokens to the user /// @param chainId chain id funds are bridged from /// @param user to bridge in funds to /// @param amount of xERC20 tokens to bridge in function _bridgeIn( uint256 chainId, address user, uint256 amount ) internal virtual { xERC20.mint(user, amount); emit BridgedIn(chainId, user, amount); } /// @notice bridge tokens from this chain to the dstChain /// @param user address burning tokens and funding the cross chain call /// @param dstChainId destination chain id /// @param amount amount of tokens to bridge /// @param to address to receive tokens on the destination chain function _bridgeOut( address user, uint256 dstChainId, uint256 amount, address to ) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: Apache 2 pragma solidity 0.8.19; interface IWormhole { struct GuardianSet { address[] keys; uint32 expirationTime; } struct Signature { bytes32 r; bytes32 s; uint8 v; uint8 guardianIndex; } struct VM { uint8 version; uint32 timestamp; uint32 nonce; uint16 emitterChainId; bytes32 emitterAddress; uint64 sequence; uint8 consistencyLevel; bytes payload; uint32 guardianSetIndex; Signature[] signatures; bytes32 hash; } struct ContractUpgrade { bytes32 module; uint8 action; uint16 chain; address newContract; } struct GuardianSetUpgrade { bytes32 module; uint8 action; uint16 chain; GuardianSet newGuardianSet; uint32 newGuardianSetIndex; } struct SetMessageFee { bytes32 module; uint8 action; uint16 chain; uint256 messageFee; } struct TransferFees { bytes32 module; uint8 action; uint16 chain; uint256 amount; bytes32 recipient; } struct RecoverChainId { bytes32 module; uint8 action; uint256 evmChainId; uint16 newChainId; } event LogMessagePublished( address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel ); event ContractUpgraded( address indexed oldContract, address indexed newContract ); event GuardianSetAdded(uint32 indexed index); function publishMessage( uint32 nonce, bytes memory payload, uint8 consistencyLevel ) external payable returns (uint64 sequence); function initialize() external; function parseAndVerifyVM( bytes calldata encodedVM ) external view returns (VM memory vm, bool valid, string memory reason); function verifyVM( VM memory vm ) external view returns (bool valid, string memory reason); function verifySignatures( bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet ) external pure returns (bool valid, string memory reason); function parseVM( bytes memory encodedVM ) external pure returns (VM memory vm); function quorum( uint numGuardians ) external pure returns (uint numSignaturesRequiredForQuorum); function getGuardianSet( uint32 index ) external view returns (GuardianSet memory); function getCurrentGuardianSetIndex() external view returns (uint32); function getGuardianSetExpiry() external view returns (uint32); function governanceActionIsConsumed( bytes32 hash ) external view returns (bool); function isInitialized(address impl) external view returns (bool); function chainId() external view returns (uint16); function isFork() external view returns (bool); function governanceChainId() external view returns (uint16); function governanceContract() external view returns (bytes32); function messageFee() external view returns (uint256); function evmChainId() external view returns (uint256); function nextSequence(address emitter) external view returns (uint64); function parseContractUpgrade( bytes memory encodedUpgrade ) external pure returns (ContractUpgrade memory cu); function parseGuardianSetUpgrade( bytes memory encodedUpgrade ) external pure returns (GuardianSetUpgrade memory gsu); function parseSetMessageFee( bytes memory encodedSetMessageFee ) external pure returns (SetMessageFee memory smf); function parseTransferFees( bytes memory encodedTransferFees ) external pure returns (TransferFees memory tf); function parseRecoverChainId( bytes memory encodedRecoverChainId ) external pure returns (RecoverChainId memory rci); function submitContractUpgrade(bytes memory _vm) external; function submitSetMessageFee(bytes memory _vm) external; function submitNewGuardianSet(bytes memory _vm) external; function submitTransferFees(bytes memory _vm) external; function submitRecoverChainId(bytes memory _vm) external; }
// SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; /** * @title WormholeRelayer * @author * @notice This project allows developers to build cross-chain applications powered by Wormhole without needing to * write and run their own relaying infrastructure * * We implement the IWormholeRelayer interface that allows users to request a delivery provider to relay a payload (and/or additional messages) * to a chain and address of their choice. */ /** * @notice VaaKey identifies a wormhole message * * @custom:member chainId Wormhole chain ID of the chain where this VAA was emitted from * @custom:member emitterAddress Address of the emitter of the VAA, in Wormhole bytes32 format * @custom:member sequence Sequence number of the VAA */ struct VaaKey { uint16 chainId; bytes32 emitterAddress; uint64 sequence; } // 0-127 are reserved for standardized KeyTypes, 128-255 are for custom use uint8 constant VAA_KEY_TYPE = 1; struct MessageKey { uint8 keyType; // 0-127 are reserved for standardized KeyTypes, 128-255 are for custom use bytes encodedKey; } interface IWormholeRelayerBase { event SendEvent( uint64 indexed sequence, uint256 deliveryQuote, uint256 paymentForExtraReceiverValue ); function getRegisteredWormholeRelayerContract( uint16 chainId ) external view returns (bytes32); /** * @notice Returns true if a delivery has been attempted for the given deliveryHash * Note: invalid deliveries where the tx reverts are not considered attempted */ function deliveryAttempted( bytes32 deliveryHash ) external view returns (bool attempted); /** * @notice block number at which a delivery was successfully executed */ function deliverySuccessBlock( bytes32 deliveryHash ) external view returns (uint256 blockNumber); /** * @notice block number of the latest attempt to execute a delivery that failed */ function deliveryFailureBlock( bytes32 deliveryHash ) external view returns (uint256 blockNumber); } /** * @title IWormholeRelayerSend * @notice The interface to request deliveries */ interface IWormholeRelayerSend is IWormholeRelayerBase { /** * @notice Publishes an instruction for the default delivery provider * to relay a payload to the address `targetAddress` on chain `targetChain` * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` * * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` * * Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendPayloadToEvm` function * with `refundChain` and `refundAddress` as parameters * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param gasLimit gas limit with which to call `targetAddress`. * @return sequence sequence number of published VAA containing delivery instructions */ function sendPayloadToEvm( uint16 targetChain, address targetAddress, bytes memory payload, uint256 receiverValue, uint256 gasLimit ) external payable returns (uint64 sequence); /** * @notice Publishes an instruction for the default delivery provider * to relay a payload to the address `targetAddress` on chain `targetChain` * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` * * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the * `targetChainRefundPerGasUnused` rate quoted by the delivery provider * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format * @param refundAddress The address on `refundChain` to deliver any refund to * @return sequence sequence number of published VAA containing delivery instructions */ function sendPayloadToEvm( uint16 targetChain, address targetAddress, bytes memory payload, uint256 receiverValue, uint256 gasLimit, uint16 refundChain, address refundAddress ) external payable returns (uint64 sequence); /** * @notice Publishes an instruction for the default delivery provider * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` * * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` * * Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendVaasToEvm` function * with `refundChain` and `refundAddress` as parameters * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param gasLimit gas limit with which to call `targetAddress`. * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` * @return sequence sequence number of published VAA containing delivery instructions */ function sendVaasToEvm( uint16 targetChain, address targetAddress, bytes memory payload, uint256 receiverValue, uint256 gasLimit, VaaKey[] memory vaaKeys ) external payable returns (uint64 sequence); /** * @notice Publishes an instruction for the default delivery provider * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` * * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the * `targetChainRefundPerGasUnused` rate quoted by the delivery provider * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format * @param refundAddress The address on `refundChain` to deliver any refund to * @return sequence sequence number of published VAA containing delivery instructions */ function sendVaasToEvm( uint16 targetChain, address targetAddress, bytes memory payload, uint256 receiverValue, uint256 gasLimit, VaaKey[] memory vaaKeys, uint16 refundChain, address refundAddress ) external payable returns (uint64 sequence); /** * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress` * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` * with gas limit `gasLimit` and `msg.value` equal to * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. * * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to * quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit, deliveryProviderAddress) + paymentForExtraReceiverValue * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue * (in addition to the `receiverValue` specified) * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the * `targetChainRefundPerGasUnused` rate quoted by the delivery provider * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format * @param refundAddress The address on `refundChain` to deliver any refund to * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` * @param consistencyLevel Consistency level with which to publish the delivery instructions - see * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels * @return sequence sequence number of published VAA containing delivery instructions */ function sendToEvm( uint16 targetChain, address targetAddress, bytes memory payload, uint256 receiverValue, uint256 paymentForExtraReceiverValue, uint256 gasLimit, uint16 refundChain, address refundAddress, address deliveryProviderAddress, VaaKey[] memory vaaKeys, uint8 consistencyLevel ) external payable returns (uint64 sequence); /** * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress` * to relay a payload and external messages specified by `messageKeys` to the address `targetAddress` on chain `targetChain` * with gas limit `gasLimit` and `msg.value` equal to * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. * * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to * quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit, deliveryProviderAddress) + paymentForExtraReceiverValue * * Note: MessageKeys can specify wormhole messages (VaaKeys) or other types of messages (ex. USDC CCTP attestations). Ensure the selected * DeliveryProvider supports all the MessageKey.keyType values specified or it will not be delivered! * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue * (in addition to the `receiverValue` specified) * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the * `targetChainRefundPerGasUnused` rate quoted by the delivery provider * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format * @param refundAddress The address on `refundChain` to deliver any refund to * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @param messageKeys Additional messagess to pass in as parameter in call to `targetAddress` * @param consistencyLevel Consistency level with which to publish the delivery instructions - see * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels * @return sequence sequence number of published VAA containing delivery instructions */ function sendToEvm( uint16 targetChain, address targetAddress, bytes memory payload, uint256 receiverValue, uint256 paymentForExtraReceiverValue, uint256 gasLimit, uint16 refundChain, address refundAddress, address deliveryProviderAddress, MessageKey[] memory messageKeys, uint8 consistencyLevel ) external payable returns (uint64 sequence); /** * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress` * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` * with `msg.value` equal to * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. * * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to * quoteDeliveryPrice(targetChain, receiverValue, encodedExecutionParameters, deliveryProviderAddress) + paymentForExtraReceiverValue * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue * (in addition to the `receiverValue` specified) * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format * @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` * @param consistencyLevel Consistency level with which to publish the delivery instructions - see * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels * @return sequence sequence number of published VAA containing delivery instructions */ function send( uint16 targetChain, bytes32 targetAddress, bytes memory payload, uint256 receiverValue, uint256 paymentForExtraReceiverValue, bytes memory encodedExecutionParameters, uint16 refundChain, bytes32 refundAddress, address deliveryProviderAddress, VaaKey[] memory vaaKeys, uint8 consistencyLevel ) external payable returns (uint64 sequence); /** * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress` * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` * with `msg.value` equal to * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. * * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` * `targetAddress` must implement the IWormholeReceiver interface * * This function must be called with `msg.value` equal to * quoteDeliveryPrice(targetChain, receiverValue, encodedExecutionParameters, deliveryProviderAddress) + paymentForExtraReceiverValue * * Note: MessageKeys can specify wormhole messages (VaaKeys) or other types of messages (ex. USDC CCTP attestations). Ensure the selected * DeliveryProvider supports all the MessageKey.keyType values specified or it will not be delivered! * * @param targetChain in Wormhole Chain ID format * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue * (in addition to the `receiverValue` specified) * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format * @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @param messageKeys Additional messagess to pass in as parameter in call to `targetAddress` * @param consistencyLevel Consistency level with which to publish the delivery instructions - see * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels * @return sequence sequence number of published VAA containing delivery instructions */ function send( uint16 targetChain, bytes32 targetAddress, bytes memory payload, uint256 receiverValue, uint256 paymentForExtraReceiverValue, bytes memory encodedExecutionParameters, uint16 refundChain, bytes32 refundAddress, address deliveryProviderAddress, MessageKey[] memory messageKeys, uint8 consistencyLevel ) external payable returns (uint64 sequence); /** * @notice Requests a previously published delivery instruction to be redelivered * (e.g. with a different delivery provider) * * This function must be called with `msg.value` equal to * quoteEVMDeliveryPrice(targetChain, newReceiverValue, newGasLimit, newDeliveryProviderAddress) * * @notice *** This will only be able to succeed if the following is true ** * - newGasLimit >= gas limit of the old instruction * - newReceiverValue >= receiver value of the old instruction * - newDeliveryProvider's `targetChainRefundPerGasUnused` >= old relay provider's `targetChainRefundPerGasUnused` * * @param deliveryVaaKey VaaKey identifying the wormhole message containing the * previously published delivery instructions * @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions * @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param newGasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the * `targetChainRefundPerGasUnused` rate quoted by the delivery provider, to the refund chain and address specified in the original request * @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @return sequence sequence number of published VAA containing redelivery instructions * * @notice *** This will only be able to succeed if the following is true ** * - newGasLimit >= gas limit of the old instruction * - newReceiverValue >= receiver value of the old instruction */ function resendToEvm( VaaKey memory deliveryVaaKey, uint16 targetChain, uint256 newReceiverValue, uint256 newGasLimit, address newDeliveryProviderAddress ) external payable returns (uint64 sequence); /** * @notice Requests a previously published delivery instruction to be redelivered * * * This function must be called with `msg.value` equal to * quoteDeliveryPrice(targetChain, newReceiverValue, newEncodedExecutionParameters, newDeliveryProviderAddress) * * @param deliveryVaaKey VaaKey identifying the wormhole message containing the * previously published delivery instructions * @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions * @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param newEncodedExecutionParameters new encoded information on how to execute delivery that may impact pricing * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` * @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @return sequence sequence number of published VAA containing redelivery instructions * * @notice *** This will only be able to succeed if the following is true ** * - (For EVM_V1) newGasLimit >= gas limit of the old instruction * - newReceiverValue >= receiver value of the old instruction * - (For EVM_V1) newDeliveryProvider's `targetChainRefundPerGasUnused` >= old relay provider's `targetChainRefundPerGasUnused` */ function resend( VaaKey memory deliveryVaaKey, uint16 targetChain, uint256 newReceiverValue, bytes memory newEncodedExecutionParameters, address newDeliveryProviderAddress ) external payable returns (uint64 sequence); /** * @notice Returns the price to request a relay to chain `targetChain`, using the default delivery provider * * @param targetChain in Wormhole Chain ID format * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param gasLimit gas limit with which to call `targetAddress`. * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay * @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused, * if a refundAddress is specified. * Note: This value can be overridden by the delivery provider on the target chain. The returned value here should be considered to be a * promise by the delivery provider of the amount of refund per gas unused that will be returned to the refundAddress at the target chain. * If a delivery provider decides to override, this will be visible as part of the emitted Delivery event on the target chain. */ function quoteEVMDeliveryPrice( uint16 targetChain, uint256 receiverValue, uint256 gasLimit ) external view returns ( uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused ); /** * @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress` * * @param targetChain in Wormhole Chain ID format * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param gasLimit gas limit with which to call `targetAddress`. * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay * @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused, * if a refundAddress is specified * Note: This value can be overridden by the delivery provider on the target chain. The returned value here should be considered to be a * promise by the delivery provider of the amount of refund per gas unused that will be returned to the refundAddress at the target chain. * If a delivery provider decides to override, this will be visible as part of the emitted Delivery event on the target chain. */ function quoteEVMDeliveryPrice( uint16 targetChain, uint256 receiverValue, uint256 gasLimit, address deliveryProviderAddress ) external view returns ( uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused ); /** * @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress` * * @param targetChain in Wormhole Chain ID format * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay * @return encodedExecutionInfo encoded information on how the delivery will be executed * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` and `targetChainRefundPerGasUnused` * (which is the amount of target chain currency that will be refunded per unit of gas unused, * if a refundAddress is specified) */ function quoteDeliveryPrice( uint16 targetChain, uint256 receiverValue, bytes memory encodedExecutionParameters, address deliveryProviderAddress ) external view returns (uint256 nativePriceQuote, bytes memory encodedExecutionInfo); /** * @notice Returns the (extra) amount of target chain currency that `targetAddress` * will be called with, if the `paymentForExtraReceiverValue` field is set to `currentChainAmount` * * @param targetChain in Wormhole Chain ID format * @param currentChainAmount The value that `paymentForExtraReceiverValue` will be set to * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider * @return targetChainAmount The amount such that if `targetAddress` will be called with `msg.value` equal to * receiverValue + targetChainAmount */ function quoteNativeForChain( uint16 targetChain, uint256 currentChainAmount, address deliveryProviderAddress ) external view returns (uint256 targetChainAmount); /** * @notice Returns the address of the current default delivery provider * @return deliveryProvider The address of (the default delivery provider)'s contract on this source * chain. This must be a contract that implements IDeliveryProvider. */ function getDefaultDeliveryProvider() external view returns (address deliveryProvider); } /** * @title IWormholeRelayerDelivery * @notice The interface to execute deliveries. Only relevant for Delivery Providers */ interface IWormholeRelayerDelivery is IWormholeRelayerBase { enum DeliveryStatus { SUCCESS, RECEIVER_FAILURE } enum RefundStatus { REFUND_SENT, REFUND_FAIL, CROSS_CHAIN_REFUND_SENT, CROSS_CHAIN_REFUND_FAIL_PROVIDER_NOT_SUPPORTED, CROSS_CHAIN_REFUND_FAIL_NOT_ENOUGH, NO_REFUND_REQUESTED } /** * @custom:member recipientContract - The target contract address * @custom:member sourceChain - The chain which this delivery was requested from (in wormhole * ChainID format) * @custom:member sequence - The wormhole sequence number of the delivery VAA on the source chain * corresponding to this delivery request * @custom:member deliveryVaaHash - The hash of the delivery VAA corresponding to this delivery * request * @custom:member gasUsed - The amount of gas that was used to call your target contract * @custom:member status: * - RECEIVER_FAILURE, if the target contract reverts * - SUCCESS, if the target contract doesn't revert * @custom:member additionalStatusInfo: * - If status is SUCCESS, then this is empty. * - If status is RECEIVER_FAILURE, this is `RETURNDATA_TRUNCATION_THRESHOLD` bytes of the * return data (i.e. potentially truncated revert reason information). * @custom:member refundStatus - Result of the refund. REFUND_SUCCESS or REFUND_FAIL are for * refunds where targetChain=refundChain; the others are for targetChain!=refundChain, * where a cross chain refund is necessary, or if the default code path is used where no refund is requested (NO_REFUND_REQUESTED) * @custom:member overridesInfo: * - If not an override: empty bytes array * - Otherwise: An encoded `DeliveryOverride` */ event Delivery( address indexed recipientContract, uint16 indexed sourceChain, uint64 indexed sequence, bytes32 deliveryVaaHash, DeliveryStatus status, uint256 gasUsed, RefundStatus refundStatus, bytes additionalStatusInfo, bytes overridesInfo ); /** * @notice The delivery provider calls `deliver` to relay messages as described by one delivery instruction * * The delivery provider must pass in the specified (by VaaKeys[]) signed wormhole messages (VAAs) from the source chain * as well as the signed wormhole message with the delivery instructions (the delivery VAA) * * The messages will be relayed to the target address (with the specified gas limit and receiver value) iff the following checks are met: * - the delivery VAA has a valid signature * - the delivery VAA's emitter is one of these WormholeRelayer contracts * - the delivery provider passed in at least enough of this chain's currency as msg.value (enough meaning the maximum possible refund) * - the instruction's target chain is this chain * - the relayed signed VAAs match the descriptions in container.messages (the VAA hashes match, or the emitter address, sequence number pair matches, depending on the description given) * * @param encodedVMs - An array of signed wormhole messages (all from the same source chain * transaction) * @param encodedDeliveryVAA - Signed wormhole message from the source chain's WormholeRelayer * contract with payload being the encoded delivery instruction container * @param relayerRefundAddress - The address to which any refunds to the delivery provider * should be sent * @param deliveryOverrides - Optional overrides field which must be either an empty bytes array or * an encoded DeliveryOverride struct */ function deliver( bytes[] memory encodedVMs, bytes memory encodedDeliveryVAA, address payable relayerRefundAddress, bytes memory deliveryOverrides ) external payable; } interface IWormholeRelayer is IWormholeRelayerDelivery, IWormholeRelayerSend {}
// SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; /** * @notice Interface for a contract which can receive Wormhole messages. */ interface IWormholeReceiver { /** * @notice When a `send` is performed with this contract as the target, this function will be * invoked by the WormholeRelayer contract * * NOTE: This function should be restricted such that only the Wormhole Relayer contract can call it. * * We also recommend that this function checks that `sourceChain` and `sourceAddress` are indeed who * you expect to have requested the calling of `send` on the source chain * * The invocation of this function corresponding to the `send` request will have msg.value equal * to the receiverValue specified in the send request. * * If the invocation of this function reverts or exceeds the gas limit * specified by the send requester, this delivery will result in a `ReceiverFailure`. * * @param payload - an arbitrary message which was included in the delivery by the * requester. This message's signature will already have been verified (as long as msg.sender is the Wormhole Relayer contract) * @param additionalMessages - Additional messages which were requested to be included in this delivery. * Note: There are no contract-level guarantees that the messages in this array are what was requested * so **you should verify any sensitive information given here!** * * For example, if a 'VaaKey' was specified on the source chain, then MAKE SURE the corresponding message here * has valid signatures (by calling `parseAndVerifyVM(message)` on the Wormhole core contract) * * This field can be used to perform and relay TokenBridge or CCTP transfers, and there are example * usages of this at * https://github.com/wormhole-foundation/hello-token * https://github.com/wormhole-foundation/hello-cctp * * @param sourceAddress - the (wormhole format) address on the sending chain which requested * this delivery. * @param sourceChain - the wormhole chain ID where this delivery was requested. * @param deliveryHash - the VAA hash of the deliveryVAA. * */ function receiveWormholeMessages( bytes memory payload, bytes[] memory additionalMessages, bytes32 sourceAddress, uint16 sourceChain, bytes32 deliveryHash ) external payable; }
// SPDX-License-Identifier: BSD-3-Clause pragma solidity 0.8.19; import {EnumerableSet} from "@openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol"; import {IWormholeTrustedSender} from "@protocol/Governance/IWormholeTrustedSender.sol"; /// @notice A contract that manages Wormhole trusted senders /// Used to allow only certain trusted senders on external chains /// to pass messages to this contract. contract WormholeTrustedSender is IWormholeTrustedSender { using EnumerableSet for EnumerableSet.Bytes32Set; /// ------------- EVENT ------------- /// @notice Emitted when a trusted sender is updated event TrustedSenderUpdated(uint16 chainId, address addr, bool added); /// ------------- MAPPING ----------- /// @notice Map of chain id => trusted sender mapping(uint16 => EnumerableSet.Bytes32Set) private trustedSenders; /// ------------- STRUCTS ------------- /// @notice A trusted sender is a contract that is allowed to emit VAAs struct TrustedSender { uint16 chainId; address addr; } /// ------------- INTERNAL HELPERS ------------- /// @dev Updates the list of trusted senders /// @param _trustedSenders The list of trusted senders, allowing one /// trusted sender per chain id function _addTrustedSenders( TrustedSender[] memory _trustedSenders ) internal { unchecked { for (uint256 i = 0; i < _trustedSenders.length; i++) { _addTrustedSender( _trustedSenders[i].addr, _trustedSenders[i].chainId ); } } } /// @notice Adds a trusted sender to the list /// @param trustedSender The trusted sender to add /// @param chainId The chain id of the trusted sender to add function _addTrustedSender(address trustedSender, uint16 chainId) internal { require( trustedSenders[chainId].add(addressToBytes(trustedSender)), "WormholeTrustedSender: already in list" ); emit TrustedSenderUpdated( chainId, trustedSender, true /// added to list ); } /// @notice remove a trusted sender /// @param trustedSender The trusted sender to remove /// @param chainId The chain id of the trusted sender to remove function _removeTrustedSender( address trustedSender, uint16 chainId ) internal { require( trustedSenders[chainId].remove(addressToBytes(trustedSender)), "WormholeTrustedSender: not in list" ); emit TrustedSenderUpdated( chainId, trustedSender, false /// removed from list ); } /// @dev Removes trusted senders from the list /// @param _trustedSenders The list of trusted senders to remove function _removeTrustedSenders( TrustedSender[] memory _trustedSenders ) internal { unchecked { for (uint256 i = 0; i < _trustedSenders.length; i++) { _removeTrustedSender( _trustedSenders[i].addr, _trustedSenders[i].chainId ); } } } /// ------------- VIEW ONLY API ------------- /// @notice returns whether or not the address is in the trusted senders list for a given chain /// @param chainId The wormhole chain id to check /// @param addr The address to check function isTrustedSender( uint16 chainId, bytes32 addr ) public view override returns (bool) { return trustedSenders[chainId].contains(addr); } /// @notice returns whether or not the address is in the trusted senders list for a given chain /// @param chainId The wormhole chain id to check /// @param addr The address to check function isTrustedSender( uint16 chainId, address addr ) public view override returns (bool) { return isTrustedSender(chainId, addressToBytes(addr)); } /// @notice returns the list of trusted senders for a given chain /// @param chainId The wormhole chain id to check /// @return The list of trusted senders function allTrustedSenders( uint16 chainId ) external view override returns (bytes32[] memory) { bytes32[] memory trustedSendersList = new bytes32[]( trustedSenders[chainId].length() ); unchecked { for (uint256 i = 0; i < trustedSendersList.length; i++) { trustedSendersList[i] = trustedSenders[chainId].at(i); } } return trustedSendersList; } /// @notice Wormhole addresses are denominated in 32 byte chunks. Converting the address to a bytes20 /// then to a bytes32 *left* aligns it, so we right shift to get the proper data /// @param addr The address to convert /// @return The address as a bytes32 function addressToBytes( address addr ) public pure override returns (bytes32) { return bytes32(bytes20(addr)) >> 96; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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. * * ```solidity * 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: BSD-3-Clause pragma solidity 0.8.19; interface IWormholeTrustedSender { /// ------------- VIEW ONLY API ------------- /// @notice returns whether or not the address is in the trusted senders list for a given chain /// @param chainId The wormhole chain id to check /// @param addr The address to check function isTrustedSender( uint16 chainId, bytes32 addr ) external view returns (bool); /// @notice returns whether or not the address is in the trusted senders list for a given chain /// @param chainId The wormhole chain id to check /// @param addr The address to check function isTrustedSender( uint16 chainId, address addr ) external view returns (bool); /// @notice returns the list of trusted senders for a given chain /// @param chainId The wormhole chain id to check /// @return The list of trusted senders function allTrustedSenders( uint16 chainId ) external view returns (bytes32[] memory); /// @notice Wormhole addresses are denominated in 32 byte chunks. Converting the address to a bytes20 /// then to a bytes32 *left* aligns it, so we right shift to get the proper data /// @param addr The address to convert /// @return The address as a bytes32 function addressToBytes(address addr) external pure returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
{ "remappings": [ "@forge-std/=lib/forge-std/src/", "@openzeppelin-contracts/=lib/openzeppelin-contracts/", "@openzeppelin/=lib/openzeppelin-contracts/", "@openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "@protocol/=src/", "@test/=test/", "@proposals/=src/proposals/", "@utils/=utils/", "@zelt/=lib/zelt/", "@zelt-src/=lib/zelt/src/", "@zelt-test/=lib/zelt/test/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/", "solmate/=lib/solmate/src/", "zelt/=lib/zelt/src/" ], "optimizer": { "enabled": true, "runs": 1 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"srcChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgedIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"dstChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"bridgeUser","type":"address"},{"indexed":true,"internalType":"address","name":"tokenReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgedOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"oldGasLimit","type":"uint96"},{"indexed":false,"internalType":"uint96","name":"newGasLimit","type":"uint96"}],"name":"GasLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lockbox","type":"address"}],"name":"LockboxSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"dstChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"target","type":"address"}],"name":"TargetAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"dstChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"tokenReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"chainId","type":"uint16"},{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bool","name":"added","type":"bool"}],"name":"TrustedSenderUpdated","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"addr","type":"address"}],"internalType":"struct WormholeTrustedSender.TrustedSender[]","name":"_trustedSenders","type":"tuple[]"}],"name":"addTrustedSenders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addressToBytes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"}],"name":"allTrustedSenders","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dstChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"bridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dstChainId","type":"uint16"}],"name":"bridgeCost","outputs":[{"internalType":"uint256","name":"gasCost","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasLimit","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newxerc20","type":"address"},{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"address","name":"wormholeRelayerAddress","type":"address"},{"internalType":"uint16","name":"targetChain","type":"uint16"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"addr","type":"address"}],"name":"isTrustedSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"addr","type":"bytes32"}],"name":"isTrustedSender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processedNonces","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bytes[]","name":"","type":"bytes[]"},{"internalType":"bytes32","name":"senderAddress","type":"bytes32"},{"internalType":"uint16","name":"sourceChain","type":"uint16"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"receiveWormholeMessages","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"addr","type":"address"}],"internalType":"struct WormholeTrustedSender.TrustedSender[]","name":"_trustedSenders","type":"tuple[]"}],"name":"removeTrustedSenders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"newGasLimit","type":"uint96"}],"name":"setGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lockbox","type":"address"}],"name":"setLockbox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"addr","type":"address"}],"internalType":"struct WormholeTrustedSender.TrustedSender[]","name":"_chainConfig","type":"tuple[]"}],"name":"setTargetAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"targetAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wormholeRelayer","outputs":[{"internalType":"contract IWormholeRelayer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xERC20","outputs":[{"internalType":"contract IXERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052609980546001600160601b031916620493e017905534801561002557600080fd5b5061002e610033565b6100f2565b600054610100900460ff161561009f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100f0576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611db9806101016000396000f3fe60806040526004361061011b5760003560e01c80631cf1b97c146101205780632e1127571461013557806335a2017d14610155578063366a596e1461018a57806337d6d162146101b7578063404a4edb146101e5578063435350b714610215578063529dca321461023557806366cc5702146102485780636cf0e20814610268578063715018a61461028857806379ba50971461029d5780638ab9b2e1146102b25780638da5cb5b146102df5780638db0eb24146102f45780639ffe56f714610314578063ae8e397f14610334578063d4f3826b1461036a578063d68d945b1461038a578063da25b725146103aa578063ded8454a146103d1578063e30c3978146103f1578063f2fde38b14610406578063f68016b714610426575b600080fd5b61013361012e3660046116a3565b61045e565b005b34801561014157600080fd5b506101336101503660046116f3565b6104bd565b34801561016157600080fd5b5061017561017036600461174d565b610661565b60405190151581526020015b60405180910390f35b34801561019657600080fd5b506097546101aa906001600160a01b031681565b6040516101819190611784565b3480156101c357600080fd5b506101d76101d2366004611798565b610679565b604051908152602001610181565b3480156101f157600080fd5b506101756102003660046117b3565b609a6020526000908152604090205460ff1681565b34801561022157600080fd5b506101336102303660046117cc565b61070d565b6101336102433660046118f0565b6107da565b34801561025457600080fd5b50609c546101aa906001600160a01b031681565b34801561027457600080fd5b506101336102833660046119ea565b6109b2565b34801561029457600080fd5b506101336109c6565b3480156102a957600080fd5b506101336109da565b3480156102be57600080fd5b506102d26102cd366004611798565b610a55565b6040516101819190611ab0565b3480156102eb57600080fd5b506101aa610b06565b34801561030057600080fd5b5061013361030f3660046119ea565b610b15565b34801561032057600080fd5b5061013361032f366004611af4565b610c2e565b34801561034057600080fd5b506101aa61034f366004611798565b609b602052600090815260409020546001600160a01b031681565b34801561037657600080fd5b50610175610385366004611b1d565b610c98565b34801561039657600080fd5b506101336103a53660046119ea565b610cb5565b3480156103b657600080fd5b506099546101aa90600160601b90046001600160a01b031681565b3480156103dd57600080fd5b506101d76103ec3660046117cc565b610cc6565b3480156103fd57600080fd5b506101aa610cd2565b34801561041257600080fd5b506101336104213660046117cc565b610ce1565b34801561043257600080fd5b50609954610446906001600160601b031681565b6040516001600160601b039091168152602001610181565b61046a33848484610d47565b806001600160a01b0316336001600160a01b0316847f1b95be00c2bd701a308dffe849aceb8671ea2f19125a1c83660dbc4f59cb7277856040516104b091815260200190565b60405180910390a4505050565b600054610100900460ff16158080156104dd5750600054600160ff909116105b806104f75750303b1580156104f7575060005460ff166001145b61055f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610582576000805461ff0019166101001790555b61058a610f60565b61059384610f8f565b609780546001600160a01b0319166001600160a01b038716179055609980546001600160601b0316600160601b6001600160a01b0386160217905561ffff82166000908152609b602052604090208054306001600160a01b031990911681179091556105ff9083610fa8565b609980546001600160601b031916620493e0179055801561065a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60006106708361038584610cc6565b90505b92915050565b60995460405163c23ee3c360e01b815261ffff831660048201526000602482018190526001600160601b038316604483015291600160601b90046001600160a01b03169063c23ee3c3906064016040805180830381865afa1580156106e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107069190611b47565b5092915050565b61071561104a565b609c546001600160a01b0316156107845760405162461bcd60e51b815260206004820152602d60248201527f576f726d686f6c65556e77726170706572416461707465723a206c6f636b626f60448201526c1e08185b1c9958591e481cd95d609a1b6064820152608401610556565b609c80546001600160a01b0319166001600160a01b0383161790556040517ffa2e15ea41196e438f0593ecdd6036acd83bdfcd39d627b77c17eab43f376a39906107cf908390611784565b60405180910390a150565b34156108285760405162461bcd60e51b815260206004820181905260248201527f576f726d686f6c654272696467653a206e6f2076616c756520616c6c6f7765646044820152606401610556565b609954600160601b90046001600160a01b031633146108955760405162461bcd60e51b8152602060048201526024808201527f576f726d686f6c654272696467653a206f6e6c792072656c6179657220616c6c6044820152631bddd95960e21b6064820152608401610556565b61089f8284610c98565b6108f65760405162461bcd60e51b815260206004820152602260248201527f576f726d686f6c654272696467653a2073656e646572206e6f74207472757374604482015261195960f21b6064820152608401610556565b6000818152609a602052604090205460ff16156109675760405162461bcd60e51b815260206004820152602960248201527f576f726d686f6c654272696467653a206d65737361676520616c7265616479206044820152681c1c9bd8d95cdcd95960ba1b6064820152608401610556565b6000818152609a602090815260408220805460ff19166001179055865182916109969189018101908901611b6b565b915091506109a98461ffff1683836110a9565b50505050505050565b6109ba61104a565b6109c38161118e565b50565b6109ce61104a565b6109d86000610f8f565b565b33806109e4610cd2565b6001600160a01b031614610a4c5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610556565b6109c381610f8f565b61ffff8116600090815260986020526040812060609190610a75906111e6565b6001600160401b03811115610a8c57610a8c6117f0565b604051908082528060200260200182016040528015610ab5578160200160208202803683370190505b50905060005b81518110156107065761ffff84166000908152609860205260409020610ae190826111f0565b828281518110610af357610af3611b99565b6020908102919091010152600101610abb565b6033546001600160a01b031690565b610b1d61104a565b60005b8151811015610c2a57818181518110610b3b57610b3b611b99565b602002602001015160200151609b6000848481518110610b5d57610b5d611b99565b60200260200101516000015161ffff1661ffff16815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550818181518110610bb557610bb5611b99565b6020026020010151602001516001600160a01b0316828281518110610bdc57610bdc611b99565b60200260200101516000015161ffff167f40408703d30ddad046e1af438394d2996712767ef13391ae7d9d21fa9eb63df560405160405180910390a380610c2281611bc5565b915050610b20565b5050565b610c3661104a565b609980546001600160601b038381166001600160601b031983168117909355604080519190921680825260208201939093527f5ccd21ad0b9c241d63daee4d43a957379ac1bef51da6554ef0d581c5ad09f5bb91015b60405180910390a15050565b61ffff8216600090815260986020526040812061067090836111fc565b610cbd61104a565b6109c381611208565b6001600160a01b031690565b6065546001600160a01b031690565b610ce961104a565b606580546001600160a01b0319166001600160a01b038316908117909155610d0f610b06565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610d5284611260565b90506000610d5f82610679565b9050803414610dc05760405162461bcd60e51b815260206004820152602760248201527f576f726d686f6c654272696467653a20636f7374206e6f7420657175616c20746044820152666f2071756f746560c81b6064820152608401610556565b61ffff82166000908152609b60205260409020546001600160a01b0316610e355760405162461bcd60e51b8152602060048201526024808201527f576f726d686f6c654272696467653a20696e76616c69642074617267657420636044820152633430b4b760e11b6064820152608401610556565b610e3f86856112c7565b60995461ffff83166000908152609b60209081526040918290205491516001600160a01b03600160601b909404841693638fecdd0293869388939190921691610e8c918a918c9101611bde565b60408051601f19818403018152908290526099546001600160e01b031960e088901b168352610ecc9493926000916001600160601b031690600401611bf7565b60206040518083038185885af1158015610eea573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f0f9190611c7d565b50826001600160a01b03168261ffff167fb8186e5c1968dbdec75b316d5fc157768894c909d6342dbddced70bb4e28513886604051610f5091815260200190565b60405180910390a3505050505050565b600054610100900460ff16610f875760405162461bcd60e51b815260040161055690611ca6565b6109d861132f565b606580546001600160a01b03191690556109c38161135f565b610fcd610fb483610cc6565b61ffff83166000908152609860205260409020906113b1565b6110285760405162461bcd60e51b815260206004820152602660248201527f576f726d686f6c655472757374656453656e6465723a20616c726561647920696044820152651b881b1a5cdd60d21b6064820152608401610556565b600080516020611d6483398151915281836001604051610c8c93929190611cf1565b33611053610b06565b6001600160a01b0316146109d85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610556565b6110b48330836113bd565b609754609c5460405163095ea7b360e01b81526001600160a01b039283169263095ea7b3926110ea929116908590600401611bde565b6020604051808303816000875af1158015611109573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112d9190611d18565b50609c5460405163040b850f60e31b81526001600160a01b039091169063205c2878906111609085908590600401611bde565b600060405180830381600087803b15801561117a57600080fd5b505af11580156109a9573d6000803e3d6000fd5b60005b8151811015610c2a576111de8282815181106111af576111af611b99565b6020026020010151602001518383815181106111cd576111cd611b99565b60200260200101516000015161146a565b600101611191565b6000610673825490565b60006106708383611508565b60006106708383611532565b60005b8151811015610c2a5761125882828151811061122957611229611b99565b60200260200101516020015183838151811061124757611247611b99565b602002602001015160000151610fa8565b60010161120b565b600061ffff8211156112c35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b6064820152608401610556565b5090565b609754604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906112f99085908590600401611bde565b600060405180830381600087803b15801561131357600080fd5b505af1158015611327573d6000803e3d6000fd5b505050505050565b600054610100900460ff166113565760405162461bcd60e51b815260040161055690611ca6565b6109d833610f8f565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610670838361154a565b6097546040516340c10f1960e01b81526001600160a01b03909116906340c10f19906113ef9085908590600401611bde565b600060405180830381600087803b15801561140957600080fd5b505af115801561141d573d6000803e3d6000fd5b50505050816001600160a01b0316837fee8d2d3b6400c99942181eba0fe478db850dbcd0fe427164578909a39bc9a1138360405161145d91815260200190565b60405180910390a3505050565b61148f61147683610cc6565b61ffff8316600090815260986020526040902090611594565b6114e65760405162461bcd60e51b815260206004820152602260248201527f576f726d686f6c655472757374656453656e6465723a206e6f7420696e206c696044820152611cdd60f21b6064820152608401610556565b600080516020611d6483398151915281836000604051610c8c93929190611cf1565b600082600001828154811061151f5761151f611b99565b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b60006115568383611532565b61158c57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610673565b506000610673565b60006106708383600081815260018301602052604081205480156116845760006115bf600183611d3a565b85549091506000906115d390600190611d3a565b90508181146116385760008660000182815481106115f3576115f3611b99565b906000526020600020015490508087600001848154811061161657611616611b99565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061164957611649611d4d565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610673565b6000915050610673565b6001600160a01b03811681146109c357600080fd5b6000806000606084860312156116b857600080fd5b833592506020840135915060408401356116d18161168e565b809150509250925092565b803561ffff811681146116ee57600080fd5b919050565b6000806000806080858703121561170957600080fd5b84356117148161168e565b935060208501356117248161168e565b925060408501356117348161168e565b9150611742606086016116dc565b905092959194509250565b6000806040838503121561176057600080fd5b611769836116dc565b915060208301356117798161168e565b809150509250929050565b6001600160a01b0391909116815260200190565b6000602082840312156117aa57600080fd5b610670826116dc565b6000602082840312156117c557600080fd5b5035919050565b6000602082840312156117de57600080fd5b81356117e98161168e565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611828576118286117f0565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611856576118566117f0565b604052919050565b600082601f83011261186f57600080fd5b81356001600160401b03811115611888576118886117f0565b61189b601f8201601f191660200161182e565b8181528460208386010111156118b057600080fd5b816020850160208301376000918101602001919091529392505050565b60006001600160401b038211156118e6576118e66117f0565b5060051b60200190565b600080600080600060a0868803121561190857600080fd5b85356001600160401b038082111561191f57600080fd5b61192b89838a0161185e565b965060209150818801358181111561194257600080fd5b8801601f81018a1361195357600080fd5b8035611966611961826118cd565b61182e565b81815260059190911b8201840190848101908c83111561198557600080fd5b8584015b838110156119bd578035868111156119a15760008081fd5b6119af8f898389010161185e565b845250918601918601611989565b509850505050604088013594506119d9915050606087016116dc565b949793965091946080013592915050565b600060208083850312156119fd57600080fd5b82356001600160401b03811115611a1357600080fd5b8301601f81018513611a2457600080fd5b8035611a32611961826118cd565b81815260069190911b82018301908381019087831115611a5157600080fd5b928401925b82841015611aa55760408489031215611a6f5760008081fd5b611a77611806565b611a80856116dc565b815285850135611a8f8161168e565b8187015282526040939093019290840190611a56565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611ae857835183529284019291840191600101611acc565b50909695505050505050565b600060208284031215611b0657600080fd5b81356001600160601b03811681146117e957600080fd5b60008060408385031215611b3057600080fd5b611b39836116dc565b946020939093013593505050565b60008060408385031215611b5a57600080fd5b505080516020909101519092909150565b60008060408385031215611b7e57600080fd5b8251611b898161168e565b6020939093015192949293505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611bd757611bd7611baf565b5060010190565b6001600160a01b03929092168252602082015260400190565b61ffff861681526000602060018060a01b0387168184015260a0604084015285518060a085015260005b81811015611c3d5787810183015185820160c001528201611c21565b50600060c0828601015260c0601f19601f83011685010192505050836060830152611c7360808301846001600160601b03169052565b9695505050505050565b600060208284031215611c8f57600080fd5b81516001600160401b03811681146117e957600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b61ffff9390931683526001600160a01b039190911660208301521515604082015260600190565b600060208284031215611d2a57600080fd5b815180151581146117e957600080fd5b8181038181111561067357610673611baf565b634e487b7160e01b600052603160045260246000fdfead5ad009fb0380817906297d4db849c9a30b93e0d3761c005ef8c487d9239224a264697066735822122010835d8fa515d44cd4486f80a6b1a84b467ca392b6578b9835bb166f1be2dae664736f6c63430008130033
Deployed Bytecode
0x60806040526004361061011b5760003560e01c80631cf1b97c146101205780632e1127571461013557806335a2017d14610155578063366a596e1461018a57806337d6d162146101b7578063404a4edb146101e5578063435350b714610215578063529dca321461023557806366cc5702146102485780636cf0e20814610268578063715018a61461028857806379ba50971461029d5780638ab9b2e1146102b25780638da5cb5b146102df5780638db0eb24146102f45780639ffe56f714610314578063ae8e397f14610334578063d4f3826b1461036a578063d68d945b1461038a578063da25b725146103aa578063ded8454a146103d1578063e30c3978146103f1578063f2fde38b14610406578063f68016b714610426575b600080fd5b61013361012e3660046116a3565b61045e565b005b34801561014157600080fd5b506101336101503660046116f3565b6104bd565b34801561016157600080fd5b5061017561017036600461174d565b610661565b60405190151581526020015b60405180910390f35b34801561019657600080fd5b506097546101aa906001600160a01b031681565b6040516101819190611784565b3480156101c357600080fd5b506101d76101d2366004611798565b610679565b604051908152602001610181565b3480156101f157600080fd5b506101756102003660046117b3565b609a6020526000908152604090205460ff1681565b34801561022157600080fd5b506101336102303660046117cc565b61070d565b6101336102433660046118f0565b6107da565b34801561025457600080fd5b50609c546101aa906001600160a01b031681565b34801561027457600080fd5b506101336102833660046119ea565b6109b2565b34801561029457600080fd5b506101336109c6565b3480156102a957600080fd5b506101336109da565b3480156102be57600080fd5b506102d26102cd366004611798565b610a55565b6040516101819190611ab0565b3480156102eb57600080fd5b506101aa610b06565b34801561030057600080fd5b5061013361030f3660046119ea565b610b15565b34801561032057600080fd5b5061013361032f366004611af4565b610c2e565b34801561034057600080fd5b506101aa61034f366004611798565b609b602052600090815260409020546001600160a01b031681565b34801561037657600080fd5b50610175610385366004611b1d565b610c98565b34801561039657600080fd5b506101336103a53660046119ea565b610cb5565b3480156103b657600080fd5b506099546101aa90600160601b90046001600160a01b031681565b3480156103dd57600080fd5b506101d76103ec3660046117cc565b610cc6565b3480156103fd57600080fd5b506101aa610cd2565b34801561041257600080fd5b506101336104213660046117cc565b610ce1565b34801561043257600080fd5b50609954610446906001600160601b031681565b6040516001600160601b039091168152602001610181565b61046a33848484610d47565b806001600160a01b0316336001600160a01b0316847f1b95be00c2bd701a308dffe849aceb8671ea2f19125a1c83660dbc4f59cb7277856040516104b091815260200190565b60405180910390a4505050565b600054610100900460ff16158080156104dd5750600054600160ff909116105b806104f75750303b1580156104f7575060005460ff166001145b61055f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610582576000805461ff0019166101001790555b61058a610f60565b61059384610f8f565b609780546001600160a01b0319166001600160a01b038716179055609980546001600160601b0316600160601b6001600160a01b0386160217905561ffff82166000908152609b602052604090208054306001600160a01b031990911681179091556105ff9083610fa8565b609980546001600160601b031916620493e0179055801561065a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b60006106708361038584610cc6565b90505b92915050565b60995460405163c23ee3c360e01b815261ffff831660048201526000602482018190526001600160601b038316604483015291600160601b90046001600160a01b03169063c23ee3c3906064016040805180830381865afa1580156106e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107069190611b47565b5092915050565b61071561104a565b609c546001600160a01b0316156107845760405162461bcd60e51b815260206004820152602d60248201527f576f726d686f6c65556e77726170706572416461707465723a206c6f636b626f60448201526c1e08185b1c9958591e481cd95d609a1b6064820152608401610556565b609c80546001600160a01b0319166001600160a01b0383161790556040517ffa2e15ea41196e438f0593ecdd6036acd83bdfcd39d627b77c17eab43f376a39906107cf908390611784565b60405180910390a150565b34156108285760405162461bcd60e51b815260206004820181905260248201527f576f726d686f6c654272696467653a206e6f2076616c756520616c6c6f7765646044820152606401610556565b609954600160601b90046001600160a01b031633146108955760405162461bcd60e51b8152602060048201526024808201527f576f726d686f6c654272696467653a206f6e6c792072656c6179657220616c6c6044820152631bddd95960e21b6064820152608401610556565b61089f8284610c98565b6108f65760405162461bcd60e51b815260206004820152602260248201527f576f726d686f6c654272696467653a2073656e646572206e6f74207472757374604482015261195960f21b6064820152608401610556565b6000818152609a602052604090205460ff16156109675760405162461bcd60e51b815260206004820152602960248201527f576f726d686f6c654272696467653a206d65737361676520616c7265616479206044820152681c1c9bd8d95cdcd95960ba1b6064820152608401610556565b6000818152609a602090815260408220805460ff19166001179055865182916109969189018101908901611b6b565b915091506109a98461ffff1683836110a9565b50505050505050565b6109ba61104a565b6109c38161118e565b50565b6109ce61104a565b6109d86000610f8f565b565b33806109e4610cd2565b6001600160a01b031614610a4c5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610556565b6109c381610f8f565b61ffff8116600090815260986020526040812060609190610a75906111e6565b6001600160401b03811115610a8c57610a8c6117f0565b604051908082528060200260200182016040528015610ab5578160200160208202803683370190505b50905060005b81518110156107065761ffff84166000908152609860205260409020610ae190826111f0565b828281518110610af357610af3611b99565b6020908102919091010152600101610abb565b6033546001600160a01b031690565b610b1d61104a565b60005b8151811015610c2a57818181518110610b3b57610b3b611b99565b602002602001015160200151609b6000848481518110610b5d57610b5d611b99565b60200260200101516000015161ffff1661ffff16815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550818181518110610bb557610bb5611b99565b6020026020010151602001516001600160a01b0316828281518110610bdc57610bdc611b99565b60200260200101516000015161ffff167f40408703d30ddad046e1af438394d2996712767ef13391ae7d9d21fa9eb63df560405160405180910390a380610c2281611bc5565b915050610b20565b5050565b610c3661104a565b609980546001600160601b038381166001600160601b031983168117909355604080519190921680825260208201939093527f5ccd21ad0b9c241d63daee4d43a957379ac1bef51da6554ef0d581c5ad09f5bb91015b60405180910390a15050565b61ffff8216600090815260986020526040812061067090836111fc565b610cbd61104a565b6109c381611208565b6001600160a01b031690565b6065546001600160a01b031690565b610ce961104a565b606580546001600160a01b0319166001600160a01b038316908117909155610d0f610b06565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000610d5284611260565b90506000610d5f82610679565b9050803414610dc05760405162461bcd60e51b815260206004820152602760248201527f576f726d686f6c654272696467653a20636f7374206e6f7420657175616c20746044820152666f2071756f746560c81b6064820152608401610556565b61ffff82166000908152609b60205260409020546001600160a01b0316610e355760405162461bcd60e51b8152602060048201526024808201527f576f726d686f6c654272696467653a20696e76616c69642074617267657420636044820152633430b4b760e11b6064820152608401610556565b610e3f86856112c7565b60995461ffff83166000908152609b60209081526040918290205491516001600160a01b03600160601b909404841693638fecdd0293869388939190921691610e8c918a918c9101611bde565b60408051601f19818403018152908290526099546001600160e01b031960e088901b168352610ecc9493926000916001600160601b031690600401611bf7565b60206040518083038185885af1158015610eea573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f0f9190611c7d565b50826001600160a01b03168261ffff167fb8186e5c1968dbdec75b316d5fc157768894c909d6342dbddced70bb4e28513886604051610f5091815260200190565b60405180910390a3505050505050565b600054610100900460ff16610f875760405162461bcd60e51b815260040161055690611ca6565b6109d861132f565b606580546001600160a01b03191690556109c38161135f565b610fcd610fb483610cc6565b61ffff83166000908152609860205260409020906113b1565b6110285760405162461bcd60e51b815260206004820152602660248201527f576f726d686f6c655472757374656453656e6465723a20616c726561647920696044820152651b881b1a5cdd60d21b6064820152608401610556565b600080516020611d6483398151915281836001604051610c8c93929190611cf1565b33611053610b06565b6001600160a01b0316146109d85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610556565b6110b48330836113bd565b609754609c5460405163095ea7b360e01b81526001600160a01b039283169263095ea7b3926110ea929116908590600401611bde565b6020604051808303816000875af1158015611109573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112d9190611d18565b50609c5460405163040b850f60e31b81526001600160a01b039091169063205c2878906111609085908590600401611bde565b600060405180830381600087803b15801561117a57600080fd5b505af11580156109a9573d6000803e3d6000fd5b60005b8151811015610c2a576111de8282815181106111af576111af611b99565b6020026020010151602001518383815181106111cd576111cd611b99565b60200260200101516000015161146a565b600101611191565b6000610673825490565b60006106708383611508565b60006106708383611532565b60005b8151811015610c2a5761125882828151811061122957611229611b99565b60200260200101516020015183838151811061124757611247611b99565b602002602001015160000151610fa8565b60010161120b565b600061ffff8211156112c35760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201526536206269747360d01b6064820152608401610556565b5090565b609754604051632770a7eb60e21b81526001600160a01b0390911690639dc29fac906112f99085908590600401611bde565b600060405180830381600087803b15801561131357600080fd5b505af1158015611327573d6000803e3d6000fd5b505050505050565b600054610100900460ff166113565760405162461bcd60e51b815260040161055690611ca6565b6109d833610f8f565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000610670838361154a565b6097546040516340c10f1960e01b81526001600160a01b03909116906340c10f19906113ef9085908590600401611bde565b600060405180830381600087803b15801561140957600080fd5b505af115801561141d573d6000803e3d6000fd5b50505050816001600160a01b0316837fee8d2d3b6400c99942181eba0fe478db850dbcd0fe427164578909a39bc9a1138360405161145d91815260200190565b60405180910390a3505050565b61148f61147683610cc6565b61ffff8316600090815260986020526040902090611594565b6114e65760405162461bcd60e51b815260206004820152602260248201527f576f726d686f6c655472757374656453656e6465723a206e6f7420696e206c696044820152611cdd60f21b6064820152608401610556565b600080516020611d6483398151915281836000604051610c8c93929190611cf1565b600082600001828154811061151f5761151f611b99565b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b60006115568383611532565b61158c57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610673565b506000610673565b60006106708383600081815260018301602052604081205480156116845760006115bf600183611d3a565b85549091506000906115d390600190611d3a565b90508181146116385760008660000182815481106115f3576115f3611b99565b906000526020600020015490508087600001848154811061161657611616611b99565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061164957611649611d4d565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610673565b6000915050610673565b6001600160a01b03811681146109c357600080fd5b6000806000606084860312156116b857600080fd5b833592506020840135915060408401356116d18161168e565b809150509250925092565b803561ffff811681146116ee57600080fd5b919050565b6000806000806080858703121561170957600080fd5b84356117148161168e565b935060208501356117248161168e565b925060408501356117348161168e565b9150611742606086016116dc565b905092959194509250565b6000806040838503121561176057600080fd5b611769836116dc565b915060208301356117798161168e565b809150509250929050565b6001600160a01b0391909116815260200190565b6000602082840312156117aa57600080fd5b610670826116dc565b6000602082840312156117c557600080fd5b5035919050565b6000602082840312156117de57600080fd5b81356117e98161168e565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611828576118286117f0565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611856576118566117f0565b604052919050565b600082601f83011261186f57600080fd5b81356001600160401b03811115611888576118886117f0565b61189b601f8201601f191660200161182e565b8181528460208386010111156118b057600080fd5b816020850160208301376000918101602001919091529392505050565b60006001600160401b038211156118e6576118e66117f0565b5060051b60200190565b600080600080600060a0868803121561190857600080fd5b85356001600160401b038082111561191f57600080fd5b61192b89838a0161185e565b965060209150818801358181111561194257600080fd5b8801601f81018a1361195357600080fd5b8035611966611961826118cd565b61182e565b81815260059190911b8201840190848101908c83111561198557600080fd5b8584015b838110156119bd578035868111156119a15760008081fd5b6119af8f898389010161185e565b845250918601918601611989565b509850505050604088013594506119d9915050606087016116dc565b949793965091946080013592915050565b600060208083850312156119fd57600080fd5b82356001600160401b03811115611a1357600080fd5b8301601f81018513611a2457600080fd5b8035611a32611961826118cd565b81815260069190911b82018301908381019087831115611a5157600080fd5b928401925b82841015611aa55760408489031215611a6f5760008081fd5b611a77611806565b611a80856116dc565b815285850135611a8f8161168e565b8187015282526040939093019290840190611a56565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611ae857835183529284019291840191600101611acc565b50909695505050505050565b600060208284031215611b0657600080fd5b81356001600160601b03811681146117e957600080fd5b60008060408385031215611b3057600080fd5b611b39836116dc565b946020939093013593505050565b60008060408385031215611b5a57600080fd5b505080516020909101519092909150565b60008060408385031215611b7e57600080fd5b8251611b898161168e565b6020939093015192949293505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611bd757611bd7611baf565b5060010190565b6001600160a01b03929092168252602082015260400190565b61ffff861681526000602060018060a01b0387168184015260a0604084015285518060a085015260005b81811015611c3d5787810183015185820160c001528201611c21565b50600060c0828601015260c0601f19601f83011685010192505050836060830152611c7360808301846001600160601b03169052565b9695505050505050565b600060208284031215611c8f57600080fd5b81516001600160401b03811681146117e957600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b61ffff9390931683526001600160a01b039190911660208301521515604082015260600190565b600060208284031215611d2a57600080fd5b815180151581146117e957600080fd5b8181038181111561067357610673611baf565b634e487b7160e01b600052603160045260246000fdfead5ad009fb0380817906297d4db849c9a30b93e0d3761c005ef8c487d9239224a264697066735822122010835d8fa515d44cd4486f80a6b1a84b467ca392b6578b9835bb166f1be2dae664736f6c63430008130033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.