Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
2989287 | 97 days ago | Contract Creation | 0 APE |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
WrappedNative
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./Constants.sol"; import "./utils/EIP712.sol"; import "./utils/Math.sol"; /** * @title WrappedNative * @author Limit Break, Inc. * @notice A contract that wraps native tokens (e.g. Ether) into an ERC-20 token. Designed as a * canonical replacement for WETH9 that can be deployed to a consistent, deterministic address on all chains. * * @notice WrappedNative features the following improvements over WETH9: * * @notice - **Deterministically Deployable By Anyone To A Consistent Address On Any Chain!** * @notice - **More Gas Efficient Operations Than WETH9!** * @notice - **`approve` and `transfer` functions are payable** - will auto-deposit when `msg.value > 0`. This feature * will allow a user to wrap and approve a protocol in a single action instead of two, improving UX and saving gas. * @notice - **`depositTo`** - allows a depositor to specify the address to give WNATIVE to. * Much more gas efficient for operations such as native refunds from protocols compared to `deposit + transfer`. * @notice - **`withdrawToAccount`** - allows a withdrawer to withdraw to a different address. * @notice - **`withdrawSplit`** - allows a withdrawer to withdraw and send native tokens to several addresses at once. * @notice - **Permit Functions** - allows for transfers and withdrawals to be approved to spenders/operators gaslessly using EIP-712 signatures. * Permitted withdrawals allow gas sponsorship to unwrap wrapped native tokens on the user's behalf, for a small convenience fee specified by the app. * This is useful when user has no native tokens on a new chain but they have received wrapped native tokens. */ contract WrappedNative is EIP712 { /// @dev Storage of user master nonces for permit processing. mapping (address => uint256) private _masterNonces; /// @dev Storage of permit nonces for permit processing. Uses bitmaps for gas-efficient storage. mapping (address => mapping (uint256 => uint256)) private _permitNonces; /// @notice Stores the wrapped native token balance of each user. mapping (address => uint256) public balanceOf; /// @notice Stores the wrapped native token allowance for each user/spender pair. mapping (address => mapping (address => uint)) public allowance; /// @notice Address that will receive infrastructure fee taxes on permit transfers. address immutable ADDRESS_INFRASTRUCTURE_TAX; constructor(address infrastructureTaxRecipient) EIP712(NAME, VERSION) { ADDRESS_INFRASTRUCTURE_TAX = infrastructureTaxRecipient; } //================================================= //== Deposit / Fallback Function Implementations == //================================================= /** * @notice Fallback function to deposit funds into the contract, or to call various view functions. * If the `msg.value` is greater than zero, the function will deposit the funds into the * `msg.sender` account. If the `msg.value` is zero, the function will check the `msg.sig` * to determine which view function is being called. If a matching function selector is found * the function will execute and return the appropriate value. If no matching function selector is found, * the function will revert. * * @notice The reason seldom-used view functions have been implemented via fallback is to save gas costs * elsewhere in the contract in common operations that have a runtime gas cost. * * @notice The following function selectors are implemented via fallback: * * @notice - **function isNonceUsed(address account, uint256 nonce) external view returns (bool)** * @notice - **function masterNonces(address account) external view returns (uint256)** * @notice - **function totalSupply() external view returns (uint256)** * @notice - **function domainSeparatorV4() external view returns (bytes32)** * @notice - **function name() external view returns (string)** * @notice - **function symbol() external view returns (string)** * @notice - **function decimals() external view returns (uint8)** * * @dev Throws when `msg.value` == 0 and the `msg.sig` does not match any of the implemented view functions. */ fallback() external payable { if (msg.value > 0) { deposit(); } else { if (msg.sig == SELECTOR_IS_NONCE_USED) { // isNonceUsed(address account, uint256 nonce) (address account, uint256 nonce) = abi.decode(msg.data[4:], (address,uint256)); bool isUsed = ((_permitNonces[account][uint248(nonce >> 8)] >> uint8(nonce)) & ONE) == ONE; assembly { mstore(0x00, isUsed) return(0x00, 0x20) } } else if (msg.sig == SELECTOR_MASTER_NONCES) { // masterNonces(address account) assembly { if lt(calldatasize(), 0x24) { revert(0,0) } mstore(0x00, shr(0x60, shl(0x60, calldataload(0x04)))) mstore(0x20, _masterNonces.slot) mstore(0x00, sload(keccak256(0x00, 0x40))) return(0x00, 0x20) } } else if (msg.sig == SELECTOR_TOTAL_SUPPLY) { // totalSupply() assembly { mstore(0x00, selfbalance()) return(0x00, 0x20) } } else if (msg.sig == SELECTOR_DOMAIN_SEPARATOR_V4) { // domainSeparatorV4() bytes32 domainSeparator = _domainSeparatorV4(); assembly { mstore(0x00, domainSeparator) return(0x00, 0x20) } } else if (msg.sig == SELECTOR_NAME) { // name() bytes memory nameReturnValue = abi.encode(NAME); assembly { return(add(nameReturnValue, 0x20), mload(nameReturnValue)) } } else if (msg.sig == SELECTOR_SYMBOL) { // symbol() bytes memory symbolReturnValue = abi.encode(SYMBOL); assembly { return(add(symbolReturnValue, 0x20), mload(symbolReturnValue)) } } else if (msg.sig == SELECTOR_DECIMALS) { // decimals() assembly { mstore(0x00, 0x12) // 18 return(0x00, 0x20) } } else { revert(); } } } /** * @notice Deposits `msg.value` funds into the `msg.sender` account, increasing their wrapped native token balance. * @notice This function is triggered when native funds are sent to this contract with no calldata. */ receive() external payable { deposit(); } //================================================= //========== Basic Deposits / Withdrawals ========= //================================================= /** * @notice Deposits `msg.value` funds into the `msg.sender` account, increasing their wrapped native token balance. * * @dev <h4>Postconditions:</h4> * @dev 1. This contract's native token balance has increased by `msg.value`. * @dev 2. The `msg.sender`'s native token balance has decreased by `msg.value`. * @dev 3. The `msg.sender`'s wrapped native token balance has increased by `msg.value`. * @dev 4. A `Deposit` event has been emitted. The `msg.sender` address is logged in the event. */ function deposit() public payable { depositTo(msg.sender); } /** * @notice Deposits `msg.value` funds into specified user's account, increasing their wrapped native token balance. * * @dev <h4>Postconditions:</h4> * @dev 1. This contract's native token balance has increased by `msg.value`. * @dev 2. The `msg.sender`'s native token balance has decreased by `msg.value`. * @dev 3. The `to` account's wrapped native token balance has increased by `msg.value`. * @dev 4. A `Deposit` event has been emitted. Caveat: The `to` address is logged in the event, not `msg.sender`. * * @param to The address that receives wrapped native tokens. */ function depositTo(address to) public payable { assembly { mstore(0x00, to) mstore(0x20, balanceOf.slot) let balanceSlot := keccak256(0x00, 0x40) sstore(balanceSlot, add(sload(balanceSlot), callvalue())) mstore(0x00, callvalue()) log2(0x00, 0x20, DEPOSIT_EVENT_TOPIC_0, to) } } /** * @notice Withdraws `amount` funds from the `msg.sender` account, decreasing their wrapped native token balance. * * @dev Throws when the `msg.sender`'s wrapped native token balance is less than `amount` to withdraw. * @dev Throws when the unwrapped native funds cannot be transferred to the `msg.sender` account. * * @dev <h4>Postconditions:</h4> * @dev 1. This contract's native token balance has decreased by `amount`. * @dev 2. The `msg.sender`'s wrapped native token balance has decreased by `amount`. * @dev 3. The `msg.sender`'s native token balance has increased by `amount`. * @dev 4. A `Withdrawal` event has been emitted. The `msg.sender` address is logged in the event. * * @param amount The amount of wrapped native tokens to withdraw. */ function withdraw(uint256 amount) public { withdrawToAccount(msg.sender, amount); } /** * @notice Withdraws `amount` funds from the `msg.sender` account, decreasing their wrapped native token balance. * * @dev Throws when the `msg.sender`'s wrapped native token balance is less than `amount` to withdraw. * @dev Throws when the unwrapped native funds cannot be transferred to the `to` account. * * @dev <h4>Postconditions:</h4> * @dev 1. This contract's native token balance has decreased by `amount`. * @dev 2. The `msg.sender`'s wrapped native token balance has decreased by `amount`. * @dev 3. The `to` account's native token balance has increased by `amount`. * @dev 4. A `Withdrawal` event has been emitted. Caveat: The `msg.sender` address is logged in the event, not `to`. * * @param to The address that receives the unwrapped native tokens. * @param amount The amount of wrapped native tokens to withdraw. */ function withdrawToAccount(address to, uint256 amount) public { _withdrawFromAccount(msg.sender, to, amount); } /** * @notice Withdraws funds from the `msg.sender` and splits the funds between multiple receiver addresses. * * @dev Throws when the `msg.sender`'s wrapped native token balance is less than the sum of `amounts` to withdraw. * @dev Throws when the unwrapped native funds cannot be transferred to one or more of the receiver addresses. * @dev Throws when the `toAddresses` and `amounts` arrays are not the same length. * * @dev <h4>Postconditions:</h4> * @dev 1. This contract's native token balance has decreased by the sum of `amounts`. * @dev 2. The `msg.sender`'s wrapped native token balance has decreased by the sum of `amounts`. * @dev 3. The receiver addresses' native token balances have increased by the corresponding amounts in `amounts`. * @dev 4. A `Withdrawal` event has been emitted for each receiver address. Caveat: The `msg.sender` address is * logged in the events, not the receiver address. * * @param toAddresses The addresses that receive the unwrapped native tokens. * @param amounts The amounts of wrapped native tokens to withdraw for each receiver address. */ function withdrawSplit(address[] calldata toAddresses, uint256[] calldata amounts) external { if (toAddresses.length != amounts.length) { revert(); } for (uint256 i = 0; i < toAddresses.length;) { withdrawToAccount(toAddresses[i], amounts[i]); unchecked { ++i; } } } //================================================= //========== ERC-20 Approvals & Transfers ========= //================================================= /** * @notice Approves `spender` to spend/transfer `amount` of the `msg.sender`'s wrapped native tokens. * When `amount` is set to `type(uint256).max`, the approval is unlimited. * * @notice Unlike a typical ERC-20 token, this function is payable, allowing for a `deposit` and approval to be * executed simultaneously. If `msg.value` is greater than zero, the function will deposit the funds * into the `msg.sender` account before approving the `spender` to spend/transfer the funds. * If `msg.value` is zero, the function will only approve the `spender` to spend/transfer the funds. * This feature is intended to improve the UX of users using wrapped native tokens so that users don't have * to perform two transactions to first deposit, then approve the spending of their tokens, saving gas in * the process. * * @dev <h4>Postconditions:</h4> * @dev 1. The `spender` is approved to spend/transfer `amount` of the `msg.sender`'s wrapped native tokens. * @dev 2. A `Approval` event has been emitted. The `msg.sender` address, `spender` address, and `amount` of the * updated approval are logged in the event. * @dev 3. If `msg.value` is greater than zero, the `msg.sender`'s wrapped native token balance has increased by * `msg.value`. * @dev 4. If `msg.value` is greater than zero, a `Deposit` event has been emitted. The `msg.sender` address is * logged in the event. * * @param spender The address that is approved to spend/transfer the `msg.sender`'s wrapped native tokens. * @param amount The amount of wrapped native tokens that the `spender` is approved to spend/transfer. Approved * spending is unlimited when this values is set to `type(uint256).max`. * * @return Always returns `true`. */ function approve(address spender, uint256 amount) public payable returns (bool) { if (msg.value > 0) { deposit(); } assembly { mstore(0x00, caller()) mstore(0x20, allowance.slot) mstore(0x20, keccak256(0x00, 0x40)) mstore(0x00, spender) let allowanceSlot := keccak256(0x00, 0x40) sstore(allowanceSlot, amount) mstore(0x00, amount) log3(0x00, 0x20, APPROVAL_EVENT_TOPIC_0, caller(), spender) mstore(0x00, 0x01) return(0x00, 0x20) } } /** * @notice Transfers an `amount` of wrapped native tokens from the `msg.sender` to the `to` address. * * @notice If the `msg.value` is greater than zero, the function will deposit the funds into the `msg.sender` account * before transferring the wrapped funds. Otherwise, the function will only transfer the funds. * * @dev Throws when the `msg.sender` has an insufficient balance to transfer `amount` of wrapped native tokens. * * @dev <h4>Postconditions:</h4> * @dev 1. When `msg.value` is greater than zero, this contract's native token balance has increased by `msg.value`. * @dev 2. When `msg.value` is greater than zero, the `msg.sender`'s native token balance has decreased by `msg.value`. * @dev 3. When `msg.value` is greater than zero, the `msg.sender`'s wrapped native token balance has increased by `msg.value`. * @dev 4. When `msg.value` is greater than zero, a `Deposit` event has been emitted. The `msg.sender` address is logged in the event. * @dev 5. The `amount` of wrapped native tokens has been transferred from the `msg.sender` account to the `to` account. * @dev 6. A `Transfer` event has been emitted. The `msg.sender` address, `to` address, and `amount` are logged in the event. * * @param to The address that receives the wrapped native tokens. * @param amount The amount of wrapped native tokens to transfer. * * @return Always returns `true`. */ function transfer(address to, uint256 amount) public payable returns (bool) { return transferFrom(msg.sender, to, amount); } /** * @notice Transfers an `amount` of wrapped native tokens from the `from` to the `to` address. * * @notice If the `msg.value` is greater than zero, the function will deposit the funds into the `from` account * before transferring the wrapped funds. Otherwise, the function will only transfer the funds. * @notice **As a reminder, the `msg.sender`'s native tokens will be deposited and the `from` (not the `msg.sender`) * address will be credited before the transfer. Integrating spender/operator protocols MUST be aware that * deposits made during transfers will not credit their own account.** * * @dev Throws when the `from` account has an insufficient balance to transfer `amount` of wrapped native tokens. * @dev Throws when the `msg.sender` is not the `from` address, and the `msg.sender` has not been approved * by `from` for an allowance greater than or equal to `amount`. * * @dev <h4>Postconditions:</h4> * @dev 1. When `msg.value` is greater than zero, this contract's native token balance has increased by `msg.value`. * @dev 2. When `msg.value` is greater than zero, the `msg.sender`'s native token balance has decreased by `msg.value`. * @dev 3. When `msg.value` is greater than zero, the `from` account's wrapped native token balance has increased by `msg.value`. * @dev 4. When `msg.value` is greater than zero, a `Deposit` event has been emitted. The `from` address is logged in the event. * @dev 5. The `amount` of wrapped native tokens has been transferred from the `from` account to the `to` account. * @dev 6. A `Transfer` event has been emitted. The `from` address, `to` address, and `amount` are logged in the event. * * @param from The address that transfers the wrapped native tokens. * @param to The address that receives the wrapped native tokens. * @param amount The amount of wrapped native tokens to transfer. * * @return Always returns `true`. */ function transferFrom(address from, address to, uint256 amount) public payable returns (bool) { if (msg.value > 0) { depositTo(from); } assembly { mstore(0x00, from) mstore(0x20, balanceOf.slot) let balanceSlotFrom := keccak256(0x00, 0x40) let balanceValFrom := sload(balanceSlotFrom) if lt(balanceValFrom, amount) { revert(0,0) } sstore(balanceSlotFrom, sub(balanceValFrom, amount)) mstore(0x00, to) let balanceSlotTo := keccak256(0x00, 0x40) sstore(balanceSlotTo, add(sload(balanceSlotTo), amount)) if iszero(eq(from, caller())) { mstore(0x00, from) mstore(0x20, allowance.slot) mstore(0x20, keccak256(0x00, 0x40)) mstore(0x00, caller()) let allowanceSlot := keccak256(0x00, 0x40) let allowanceVal := sload(allowanceSlot) if iszero(eq(allowanceVal, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) { if lt(allowanceVal, amount) { revert(0,0) } sstore(allowanceSlot, sub(allowanceVal, amount)) } } mstore(0x00, amount) log3(0x00, 0x20, TRANSFER_EVENT_TOPIC_0, from, to) mstore(0x00, 0x01) return(0x00, 0x20) } } //================================================= //======= Permitted Transfers / Withdrawals ======= //================================================= /** * @notice Allows the `msg.sender` to revoke/cancel all prior permitted transfer and withdrawal signatures. * * @dev <h4>Postconditions:</h4> * @dev 1. The `msg.sender`'s master nonce has been incremented by `1` in contract storage, rendering all signed * permits using the prior master nonce unusable. * @dev 2. A `MasterNonceInvalidated` event has been emitted. */ function revokeMyOutstandingPermits() external { assembly { mstore(0x00, caller()) mstore(0x20, _masterNonces.slot) let masterNonceSlot := keccak256(0x00, 0x40) let invalidatedNonce := sload(masterNonceSlot) sstore(masterNonceSlot, add(0x01, invalidatedNonce)) log3(0x00, 0x00, MASTER_NONCE_INVALIDATED_EVENT_TOPIC_0, caller(), invalidatedNonce) } } /** * @notice Allows the `msg.sender` to revoke/cancel a single, previously signed permitted transfer or withdrawal * signature by specifying the nonce of the individual permit. * * @dev Throws when the `msg.sender` has already revoked the permit nonce. * @dev Throws when the permit nonce was already used successfully. * * @dev <h4>Postconditions:</h4> * @dev 1. The specified `nonce` for the `msg.sender` has been revoked and can * no longer be used to execute a permitted transfer or withdrawal. * @dev 2. A `PermitNonceInvalidated` event has been emitted. * * @param nonce The nonce that was signed in the permitted transfer or withdrawal. */ function revokeMyNonce(uint256 nonce) external { _checkAndInvalidateNonce(msg.sender, nonce); } /** * @notice Allows a spender/operator to transfer wrapped native tokens from the `from` account to the `to` account * using a gasless signature from the `from` account so that the `from` account does not need to pay gas * to set an on-chain allowance. * * @notice If the `msg.value` is greater than zero, the function will deposit the funds into the `from` account * before transferring the wrapped funds. Otherwise, the function will only transfer the funds. * @notice **As a reminder, the `msg.sender`'s native tokens will be deposited and the `from` (not the `msg.sender`) * address will be credited before the transfer. Integrating spender/operator protocols MUST be aware that * deposits made during transfers will not credit their own account.** * * @dev Throws when the `from` account is the zero address. * @dev Throws when the `msg.sender` does not match the operator/spender from the signed transfer permit. * @dev Throws when the permitAmount does not match the signed transfer permit. * @dev Throws when the nonce does not match the signed transfer permit. * @dev Throws when the expiration does not match the signed transfer permit. * @dev Throws when the permit has expired. * @dev Throws when the requested transfer amount exceeds the maximum permitted transfer amount. * @dev Throws when the permit nonce has already been used or revoked/cancelled. * @dev Throws when the master nonce has been revoked/cancelled since the permit was signed. * @dev Throws when the permit signature is invalid, or was not signed by the `from` account. * @dev Throws when the `from` account has an insufficient balance to transfer `transferAmount` of wrapped native tokens. * * @dev <h4>Postconditions:</h4> * @dev 1. When `msg.value` is greater than zero, this contract's native token balance has increased by `msg.value`. * @dev 2. When `msg.value` is greater than zero, the `msg.sender`'s native token balance has decreased by `msg.value`. * @dev 3. When `msg.value` is greater than zero, the `from` account's wrapped native token balance has increased by `msg.value`. * @dev 4. When `msg.value` is greater than zero, a `Deposit` event has been emitted. The `from` address is logged in the event. * @dev 5. `nonce` for `from` account is invalidated. * @dev 6. A `PermitNonceInvalidated` event has been emitted. * @dev 7. The `transferAmount` of wrapped native tokens has been transferred from the `from` account to the `to` account. * @dev 8. A `Transfer` event has been emitted. The `from` address, `to` address, and `transferAmount` are logged in the event. * * @param from The address that transfers the wrapped native tokens. * @param to The address that receives the wrapped native tokens. * @param transferAmount The amount of wrapped native tokens to transfer. * @param permitAmount The maximum amount of wrapped native tokens that can be transferred, signed in permit. * @param nonce The nonce, signed in permit. * @param expiration The expiration timestamp, signed in permit. * @param signedPermit The signature of the permit. */ function permitTransfer( address from, address to, uint256 transferAmount, uint256 permitAmount, uint256 nonce, uint256 expiration, bytes calldata signedPermit ) external payable { if (msg.value > 0) { depositTo(from); } if (block.timestamp > expiration || transferAmount > permitAmount || from == address(0)) { revert(); } _checkAndInvalidateNonce(from, nonce); _verifyPermitSignature( from, _hashTypedDataV4( keccak256( abi.encode( PERMIT_TRANSFER_TYPEHASH, msg.sender, permitAmount, nonce, expiration, _masterNonces[from] ) ) ), signedPermit ); _balanceTransfer(from, to, transferAmount); } /** * @notice Allows a spender/operator to withdraw wrapped native tokens from the `from` account to the `to` account * using a gasless signature signed by the `from` account to prove authorization of the withdrawal. * * @dev Throws when the `from` account is the zero address. * @dev Throws when the `msg.sender` does not match the operator/spender from the signed withdrawal permit. * @dev Throws when the permit has expired. * @dev Throws when the amount does not match the signed withdrawal permit. * @dev Throws when the nonce does not match the signed withdrawal permit. * @dev Throws when the expiration does not match the signed withdrawal permit. * @dev Throws when the convenience fee reciever and fee does not match the signed withdrawal permit. * @dev Throws when the `to` address does not match the signed withdrawal permit. * @dev Throws when the permit nonce has already been used or revoked/cancelled. * @dev Throws when the master nonce has been revoked/cancelled since the permit was signed. * @dev Throws when the permit signature is invalid, or was not signed by the `from` account. * @dev Throws when the `from` account has an insufficient balance to transfer `transferAmount` of wrapped native tokens. * * @dev <h4>Postconditions:</h4> * @dev 1. This contract's native token balance has decreased by `amount`, less convenience and infrastructure * fees that remain wrapped. * @dev 2. The `from` account's wrapped native token balance has decreased by `amount`. * @dev 3. The `to` account's native token balance has increased by `amount`, less convenience and/or infrastructure fees. * @dev 4. The `convenienceFeeReceiver` account's wrapped native token balance has increased by the convenience fee. * @dev 5. The infrastructure tax account's wrapped native token balance has increased by the infrastructure fee. * @dev 6. `nonce` for `from` account is invalidated. * @dev 7. A `PermitNonceInvalidated` event has been emitted. * @dev 8. A `Withdrawal` event has been emitted. Caveat: The `from` address is logged in the event, not `to` or `msg.sender`. * * @param from The address that from which funds are withdrawn. * @param to The address that receives the withdrawn funds. * @param amount The amount of wrapped native tokens to withdraw. * @param nonce The nonce, signed in permit. * @param expiration The expiration timestamp, signed in permit. * @param convenienceFeeReceiver The address that receives the convenience fee. * @param convenienceFeeBps The basis points of the convenience fee. * @param signedPermit The signature of the permit. */ function doPermittedWithdraw( address from, address to, uint256 amount, uint256 nonce, uint256 expiration, address convenienceFeeReceiver, uint256 convenienceFeeBps, bytes calldata signedPermit ) external { if (block.timestamp > expiration || from == address(0)) { revert(); } _checkAndInvalidateNonce(from, nonce); _verifyPermitSignature( from, _hashTypedDataV4( keccak256( abi.encode( PERMIT_WITHDRAWAL_TYPEHASH, msg.sender, amount, nonce, expiration, _masterNonces[from], to, convenienceFeeReceiver, convenienceFeeBps ) ) ), signedPermit ); ( uint256 userAmount, uint256 convenienceFee, uint256 infrastructureFee ) = _computeWithdrawalSplits(amount, convenienceFeeReceiver, convenienceFeeBps); if (convenienceFee > 0) { _balanceTransfer(from, convenienceFeeReceiver, convenienceFee); } if (infrastructureFee > 0) { _balanceTransfer(from, ADDRESS_INFRASTRUCTURE_TAX, infrastructureFee); } _withdrawFromAccount(from, to, userAmount); } //================================================= //========= Miscellaneous Helper Functions ======== //================================================= /** * @dev Helper function that transfers wrapped native token balance between accounts. * * @dev Throws when the `from` account has an insufficient balance to transfer `amount` of wrapped native tokens. * * @param from The address from which the wrapped native tokens is transferred. * @param to The address to which the wrapped native tokens are transferred. * @param amount The amount of wrapped native tokens to transfer. */ function _balanceTransfer(address from, address to, uint256 amount) private { assembly { mstore(0x00, from) mstore(0x20, balanceOf.slot) let balanceSlotFrom := keccak256(0x00, 0x40) let balanceValFrom := sload(balanceSlotFrom) if lt(balanceValFrom, amount) { revert(0,0) } sstore(balanceSlotFrom, sub(balanceValFrom, amount)) mstore(0x00, to) let balanceSlotTo := keccak256(0x00, 0x40) sstore(balanceSlotTo, add(sload(balanceSlotTo), amount)) mstore(0x00, amount) log3(0x00, 0x20, TRANSFER_EVENT_TOPIC_0, from, to) } } /** * @dev Helper function that withdraws wrapped native tokens from an account to another account. * * @dev Throws when the `from` account has an insufficient balance to transfer `amount` of wrapped native tokens. * @dev Throws when the unwrapped native funds cannot be transferred to the `to` account. * * @param from The address from which the wrapped native tokens are withdrawn. * @param to The address to which the native tokens are transferred. * @param amount The amount of wrapped native tokens to withdraw. */ function _withdrawFromAccount(address from, address to, uint256 amount) private { assembly { mstore(0x00, from) mstore(0x20, balanceOf.slot) let balanceSlot := keccak256(0x00, 0x40) let balanceVal := sload(balanceSlot) let updatedBalance := sub(balanceVal, amount) sstore(balanceSlot, updatedBalance) mstore(0x00, amount) log2(0x00, 0x20, WITHDRAWAL_EVENT_TOPIC_0, from) if or(gt(updatedBalance, balanceVal), iszero(call(gas(), to, amount, 0, 0, 0, 0))) { revert(0,0) } } } /** * @dev Helper function that checks and invalidates a permit nonce. * * @dev Throws when the permit nonce has already been used or revoked/cancelled. * * @param account The account that signed the permit. * @param nonce The nonce that was signed in the permit. */ function _checkAndInvalidateNonce(address account, uint256 nonce) private { unchecked { if (uint256(_permitNonces[account][uint248(nonce >> 8)] ^= (ONE << uint8(nonce))) & (ONE << uint8(nonce)) == ZERO) { revert(); } } assembly { log3(0x00, 0x00, PERMIT_NONCE_INVALIDATED_EVENT_TOPIC_0, account, nonce) } } //================================================= //============= Fee Split Calculations ============ //================================================= /** * @dev Helper function that computes the withdrawal fee split amounts. * * @param amount The amount of wrapped native tokens to split. * @param convenienceFeeReceiver The address that receives the convenience fee. * @param convenienceFeeBps The basis points of the convenience fee. */ function _computeWithdrawalSplits( uint256 amount, address convenienceFeeReceiver, uint256 convenienceFeeBps ) private pure returns (uint256 userAmount, uint256 convenienceFee, uint256 convenienceFeeInfrastructure) { if (convenienceFeeBps > FEE_DENOMINATOR) { revert(); } if (amount > type(uint240).max) { revert(); } if (convenienceFeeReceiver == address(0)) { convenienceFeeBps = 0; } unchecked { if (convenienceFeeBps > INFRASTRUCTURE_TAX_THRESHOLD) { convenienceFee = amount * convenienceFeeBps / FEE_DENOMINATOR; convenienceFeeInfrastructure = convenienceFee * INFRASTRUCTURE_TAX_BPS / FEE_DENOMINATOR; convenienceFee -= convenienceFeeInfrastructure; userAmount = amount - convenienceFee - convenienceFeeInfrastructure; } else if (convenienceFeeBps > 0) { convenienceFeeInfrastructure = amount / FEE_DENOMINATOR; convenienceFee = amount * (convenienceFeeBps - ONE) / FEE_DENOMINATOR; userAmount = amount - convenienceFee - convenienceFeeInfrastructure; } else { convenienceFeeInfrastructure = amount / FEE_DENOMINATOR; userAmount = amount - convenienceFeeInfrastructure; } } } //================================================= //============ Signature Verification ============= //================================================= /** * @notice Verifies a permit signature based on the bytes length of the signature provided. * * @dev Throws when - * @dev The bytes signature length is 64 or 65 bytes AND * @dev The ECDSA recovered signer is not the expectedSigner AND * @dev The expectedSigner's code length is zero OR the expectedSigner does not return a valid EIP-1271 response * @dev * @dev OR * @dev * @dev The bytes signature length is not 64 or 65 bytes AND * @dev The expectedSigner's code length is zero OR the expectedSigner does not return a valid EIP-1271 response */ function _verifyPermitSignature( address expectedSigner, bytes32 digest, bytes calldata signature ) private view { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // Divide the signature in r, s and v variables /// @solidity memory-safe-assembly assembly { r := calldataload(signature.offset) s := calldataload(add(signature.offset, 32)) v := byte(0, calldataload(add(signature.offset, 64))) } (bool isError, address signer) = _ecdsaRecover(digest, v, r, s); if (expectedSigner != signer || isError) { _verifyEIP1271Signature(expectedSigner, digest, signature); } } else if (signature.length == 64) { bytes32 r; bytes32 vs; // Divide the signature in r and vs variables /// @solidity memory-safe-assembly assembly { r := calldataload(signature.offset) vs := calldataload(add(signature.offset, 32)) } (bool isError, address signer) = _ecdsaRecover(digest, r, vs); if (expectedSigner != signer || isError) { _verifyEIP1271Signature(expectedSigner, digest, signature); } } else { _verifyEIP1271Signature(expectedSigner, digest, signature); } } /** * @notice Verifies an EIP-1271 signature. * * @dev Throws when `signer` code length is zero OR the EIP-1271 call does not * @dev return the correct magic value. * * @param signer The signer address to verify a signature with * @param hash The hash digest to verify with the signer * @param signature The signature to verify */ function _verifyEIP1271Signature(address signer, bytes32 hash, bytes calldata signature) private view { if(signer.code.length == 0) { revert(); } if (!_safeIsValidSignature(signer, hash, signature)) { revert(); } } /** * @notice Overload of the `_ecdsaRecover` function to unpack the `v` and `s` values * * @param digest The hash digest that was signed * @param r The `r` value of the signature * @param vs The packed `v` and `s` values of the signature * * @return isError True if the ECDSA function is provided invalid inputs * @return signer The recovered address from ECDSA */ function _ecdsaRecover(bytes32 digest, bytes32 r, bytes32 vs) private pure returns (bool isError, address signer) { unchecked { bytes32 s = vs & UPPER_BIT_MASK; uint8 v = uint8(uint256(vs >> 255)) + 27; (isError, signer) = _ecdsaRecover(digest, v, r, s); } } /** * @notice Recovers the signer address using ECDSA * * @dev Does **NOT** revert if invalid input values are provided or `signer` is recovered as address(0) * @dev Returns an `isError` value in those conditions that is handled upstream * * @param digest The hash digest that was signed * @param v The `v` value of the signature * @param r The `r` value of the signature * @param s The `s` value of the signature * * @return isError True if the ECDSA function is provided invalid inputs * @return signer The recovered address from ECDSA */ function _ecdsaRecover(bytes32 digest, uint8 v, bytes32 r, bytes32 s) private pure returns (bool isError, address signer) { if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { // Invalid signature `s` value - return isError = true and signer = address(0) to check EIP-1271 return (true, address(0)); } signer = ecrecover(digest, v, r, s); isError = (signer == address(0)); } /** * @notice A gas efficient, and fallback-safe way to call the isValidSignature function for EIP-1271. * * @param signer The EIP-1271 signer to call to check for a valid signature. * @param hash The hash digest to verify with the EIP-1271 signer. * @param signature The supplied signature to verify. * * @return isValid True if the EIP-1271 signer returns the EIP-1271 magic value. */ function _safeIsValidSignature( address signer, bytes32 hash, bytes calldata signature ) private view returns(bool isValid) { assembly { function _callIsValidSignature(_signer, _hash, _signatureOffset, _signatureLength) -> _isValid { let ptr := mload(0x40) // store isValidSignature(bytes32,bytes) selector mstore(ptr, hex"1626ba7e") // store bytes32 hash value in abi encoded location mstore(add(ptr, 0x04), _hash) // store abi encoded location of the bytes signature data mstore(add(ptr, 0x24), 0x40) // store bytes signature length mstore(add(ptr, 0x44), _signatureLength) // copy calldata bytes signature to memory calldatacopy(add(ptr, 0x64), _signatureOffset, _signatureLength) // calculate data length based on abi encoded data with rounded up signature length let dataLength := add(0x64, and(add(_signatureLength, 0x1F), not(0x1F))) // update free memory pointer mstore(0x40, add(ptr, dataLength)) // static call _signer with abi encoded data // skip return data check if call failed or return data size is not at least 32 bytes if and(iszero(lt(returndatasize(), 0x20)), staticcall(gas(), _signer, ptr, dataLength, 0x00, 0x20)) { // check if return data is equal to isValidSignature magic value _isValid := eq(mload(0x00), hex"1626ba7e") leave } } isValid := _callIsValidSignature(signer, hash, signature.offset, signature.length) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./interfaces/IWrappedNative.sol"; import "./interfaces/IWrappedNativeExtended.sol"; string constant VERSION = "1"; string constant NAME = "Wrapped Native"; string constant SYMBOL = "WNATIVE"; uint8 constant DECIMALS = 18; bytes32 constant UPPER_BIT_MASK = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; uint256 constant ZERO = 0; uint256 constant ONE = 1; uint256 constant INFRASTRUCTURE_TAX_THRESHOLD = 9; // When convenienceFeeBps is greater than 9, we apply infrastructure tax to convenience fee. uint256 constant INFRASTRUCTURE_TAX_BPS = 10_00; uint256 constant FEE_DENOMINATOR = 100_00; uint256 constant WITHDRAWAL_EVENT_TOPIC_0 = 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65; uint256 constant DEPOSIT_EVENT_TOPIC_0 = 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c; uint256 constant APPROVAL_EVENT_TOPIC_0 = 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925; uint256 constant TRANSFER_EVENT_TOPIC_0 = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; uint256 constant PERMIT_NONCE_INVALIDATED_EVENT_TOPIC_0 = 0x8dc5a0b2e80f26187d38744e9559150e3bd6e06fccefbe737fd33411cfb15151; uint256 constant MASTER_NONCE_INVALIDATED_EVENT_TOPIC_0 = 0x9614574d6542397172c19ba2bf4588434feeb977576e92b7b59b38242ab59609; bytes32 constant PERMIT_TRANSFER_TYPEHASH = keccak256("PermitTransfer(address operator,uint256 amount,uint256 nonce,uint256 expiration,uint256 masterNonce)"); bytes32 constant PERMIT_WITHDRAWAL_TYPEHASH = keccak256("PermitWithdrawal(address operator,uint256 amount,uint256 nonce,uint256 expiration,uint256 masterNonce,address to,address convenienceFeeReceiver,uint256 convenienceFeeBps)"); bytes4 constant SELECTOR_IS_NONCE_USED = IWrappedNativeExtended.isNonceUsed.selector; bytes4 constant SELECTOR_MASTER_NONCES = IWrappedNativeExtended.masterNonces.selector; bytes4 constant SELECTOR_TOTAL_SUPPLY = IWrappedNative.totalSupply.selector; bytes4 constant SELECTOR_DOMAIN_SEPARATOR_V4 = IWrappedNativeExtended.domainSeparatorV4.selector; bytes4 constant SELECTOR_NAME = IWrappedNative.name.selector; bytes4 constant SELECTOR_SYMBOL = IWrappedNative.symbol.selector; bytes4 constant SELECTOR_DECIMALS = IWrappedNative.decimals.selector;
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface IWrappedNative { // ERC20 Specific event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 value) external payable returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external payable returns (bool); function transferFrom(address from, address to, uint256 value) external payable returns (bool); // ERC20 Metadata Specific function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); // Wrapped Native Specific event Deposit(address indexed to, uint256 amount); event Withdrawal(address indexed from, uint256 amount); function deposit() external payable; function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./IWrappedNative.sol"; interface IWrappedNativeExtended is IWrappedNative { // Wrapped Native Permit Specific event PermitNonceInvalidated(address indexed account,uint256 indexed nonce); event MasterNonceInvalidated(address indexed account, uint256 indexed nonce); // Enhancements for Deposits and Withdrawals function depositTo(address to) external payable; function withdrawToAccount(address to, uint256 amount) external; function withdrawSplit(address[] calldata toAddresses, uint256[] calldata amounts) external; // Permit Processing function domainSeparatorV4() external view returns (bytes32); function isNonceUsed(address account, uint256 nonce) external view returns (bool); function masterNonces(address account) external view returns (uint256); function revokeMyOutstandingPermits() external; function revokeMyNonce(uint256 nonce) external; function permitTransfer( address from, address to, uint256 transferAmount, uint256 permitAmount, uint256 nonce, uint256 expiration, bytes calldata signedPermit ) external payable; function doPermittedWithdraw( address from, address to, uint256 amount, uint256 nonce, uint256 expiration, address convenienceFeeReceiver, uint256 convenienceFeeBps, bytes calldata signedPermit ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; import "./MessageHashUtils.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment */ abstract contract EIP712 { bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _cachedDomainSeparator; uint256 private immutable _cachedChainId; bytes32 private immutable _hashedName; bytes32 private immutable _hashedVersion; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { _hashedName = keccak256(bytes(name)); _hashedVersion = keccak256(bytes(version)); _cachedChainId = block.chainid; _cachedDomainSeparator = _buildDomainSeparator(); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (block.chainid == _cachedChainId) { return _cachedDomainSeparator; } else { return _buildDomainSeparator(); } } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "./Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./Math.sol"; import {SignedMath} from "./SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@limitbreak/creator-token-transfer-validator/=lib/creator-token-transfer-validator/", "@limitbreak/tm-cloner/=lib/tm-cloner/", "@limitbreak/tm-core-lib/=lib/tm-core-lib/", "@limitbreak/tm-extension-registry/=lib/tm-extension-registry/", "@limitbreak/tm-role-server/=lib/tm-role-server/", "@limitbreak/tm-template-factory/=lib/tm-template-factory/", "@limitbreak/tm-web2-gateway/=lib/tm-web2-gateway/", "@limitbreak/wrapped-native/=lib/wrapped-native/", "@limitbreak/permit-c/=lib/payment-processor-v2/lib/PermitC/src/", "@limitbreak/trusted-forwarder/=lib/payment-processor-v2/lib/TrustedForwarder/src/", "@opensea/tstorish/=lib/creator-token-standards/lib/tstorish/src/", "@openzeppelin/=lib/payment-processor-v2/lib/openzeppelin-contracts/", "@rari-capital/solmate/=lib/payment-processor-v2/lib/solmate/", "ERC721A/=lib/creator-token-standards/lib/ERC721A/contracts/", "PermitC/=lib/payment-processor-v2/lib/PermitC/", "TrustedForwarder/=lib/TrustedForwarder/", "creator-token-standards/=lib/creator-token-standards/", "creator-token-transfer-validator/=lib/creator-token-transfer-validator/src/", "erc4626-tests/=lib/payment-processor-v2/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a/=lib/creator-token-standards/lib/ERC721A/", "fake-contracts/=lib/fake-contracts/src/", "forge-gas-metering/=lib/payment-processor-v2/lib/PermitC/lib/forge-gas-metering/", "multisig/=lib/multisig/", "murky/=lib/payment-processor-v2/lib/murky/", "openzeppelin-contracts/=lib/payment-processor-v2/lib/openzeppelin-contracts/", "openzeppelin/=lib/payment-processor-v2/lib/openzeppelin-contracts/contracts/", "payment-processor-v2/=lib/payment-processor-v2/", "solady/=lib/payment-processor-v2/lib/PermitC/lib/forge-gas-metering/lib/solady/", "solmate/=lib/payment-processor-v2/lib/solmate/src/", "tm-cloner/=lib/tm-cloner/src/", "tm-core-lib/=lib/tm-core-lib/src/", "tm-extension-registry/=lib/tm-extension-registry/src/", "tm-role-server/=lib/tm-role-server/src/", "tm-template-factory/=lib/tm-template-factory/src/", "tm-web2-gateway/=lib/tm-web2-gateway/src/", "tstorish/=lib/creator-token-standards/lib/tstorish/src/", "wrapped-native/=lib/wrapped-native/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"infrastructureTaxRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"address","name":"convenienceFeeReceiver","type":"address"},{"internalType":"uint256","name":"convenienceFeeBps","type":"uint256"},{"internalType":"bytes","name":"signedPermit","type":"bytes"}],"name":"doPermittedWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"transferAmount","type":"uint256"},{"internalType":"uint256","name":"permitAmount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiration","type":"uint256"},{"internalType":"bytes","name":"signedPermit","type":"bytes"}],"name":"permitTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"revokeMyNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeMyOutstandingPermits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"toAddresses","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"withdrawSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawToAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101203461015e57601f61160238819003918201601f19168301926001600160401b039290918385118386101761014a57816020928492604097885283398101031261015e5751916001600160a01b038316830361015e5780519061006382610162565b600e825260208201916d57726170706564204e617469766560901b835281519261008c84610162565b600184526020840191603160f81b8352519020928360c052519020908160e0524660a05280519160208301937f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f85528284015260608301524660808301523060a083015260a0825260c08201938285109085111761014a57839052519020608052610100918252611484918261017e833960805182611218015260a051826111f2015260c05182611267015260e0518261128d015251816108bd0152f35b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b604081019081106001600160401b0382111761014a5760405256fe60806040526004361015610026575b361561001e5761001c610cd9565b005b61001c610ad9565b5f3560e01c8063095ea7b31461010557806323b872dd146101005780632e1a7d4d146100fb57806370a08231146100f6578063a9059cbb146100f1578063b760faf9146100ec578063c2b1a472146100e7578063d0e30db0146100e2578063d4229c24146100dd578063dd62ed3e146100d8578063e06cbc62146100d3578063e5fe69fe146100ce578063f38e809d146100c95763facb18e30361000e576109ec565b610952565b610917565b610730565b6106af565b610503565b6104a3565b61045b565b61041d565b610378565b610311565b6102d5565b6101c2565b61012c565b73ffffffffffffffffffffffffffffffffffffffff81160361012857565b5f80fd5b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356101628161010a565b602435346101b4575b335f52600360205260405f20602052815f528060405f20555f52337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa360015f5260205ff35b6101bd33610a9d565b61016b565b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356101f88161010a565b602435906102058261010a565b604435346102c7575b815f52600260205260405f208054828110610128578290039055825f5260405f2081815401905533820361026d575b5f527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205fa360015f5260205ff35b815f52600360205260405f20602052335f5260405f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81036102b4575b505061023d565b8281106101285782900390555f806102ad565b6102d082610a9d565b61020e565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c6004353333610f30565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285773ffffffffffffffffffffffffffffffffffffffff6004356103618161010a565b165f526002602052602060405f2054604051908152f35b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356103ae8161010a565b6024353461040f575b335f52600260205260405f208054828110610128578290039055815f5260405f208181540190555f52337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205fa360015f5260205ff35b61041833610a9d565b6103b7565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c6004356104568161010a565b610a9d565b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c6004356104998161010a565b6024359033610f30565b5f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c33610a9d565b9181601f840112156101285782359167ffffffffffffffff8311610128576020838186019501011161012857565b60e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356105398161010a565b6024356105458161010a565b604435906064359260843560a4359060c43567ffffffffffffffff8111610128576105749036906004016104d5565b91346106a1575b8342118015610698575b801561067a575b6101285761001c9761067594610667836105a961066f958a610f81565b73ffffffffffffffffffffffffffffffffffffffff89165f525f60205261063b60405f205460405194859360208501973389919260a093969594919673ffffffffffffffffffffffffffffffffffffffff60c08501987f3c038916d033a3e04838da5aca7b9a42656eeae3b520daf7ed52ec02fd37fb9486521660208501526040840152606083015260808201520152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610b2d565b519020611011565b84611052565b6110df565b5073ffffffffffffffffffffffffffffffffffffffff85161561058c565b50878711610585565b6106aa85610a9d565b61057b565b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356106ea8161010a565b602435906106f78261010a565b73ffffffffffffffffffffffffffffffffffffffff8091165f52600360205260405f2091165f52602052602060405f2054604051908152f35b34610128576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285760043561076c8161010a565b602435906107798261010a565b6044359160a435916064356084356107908561010a565b60c4359060e43567ffffffffffffffff8111610128576107b49036906004016104d5565b97909382421180156108f9575b6101285761001c986108a095610895848b966106678661063b8b8f8f9073ffffffffffffffffffffffffffffffffffffffff828f9361089b9e61080391610f81565b165f525f60205260405f2054604051978896602088019a338c9461010096919294999897939961012087019a7fe55aaa79350b0eb9ee70c987c9b0603c46531ab71d2b7c5404835db2f60e220c885273ffffffffffffffffffffffffffffffffffffffff968780961660208a015260408901526060880152608087015260a08601521660c08401521660e08201520152565b88611052565b611131565b919490806108e8575b5050806108b7575b50610f30565b6108e2907f0000000000000000000000000000000000000000000000000000000000000000836110df565b5f6108b1565b6108f291846110df565b5f806108a9565b5073ffffffffffffffffffffffffffffffffffffffff8616156107c1565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c60043533610f81565b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012857335f525f60205260405f20805490816001019055337f9614574d6542397172c19ba2bf4588434feeb977576e92b7b59b38242ab596095f80a3005b9181601f840112156101285782359167ffffffffffffffff8311610128576020808501948460051b01011161012857565b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285767ffffffffffffffff60043581811161012857610a3c9036906004016109bb565b909160243590811161012857610a569036906004016109bb565b90818303610128575f5b838110610a6957005b80610a97610a7a6001938789610b6e565b35610a848161010a565b610a8f838787610b6e565b359033610f30565b01610a60565b805f52600260205260405f20348154019055345f527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60205fa2565b610ae233610a9d565b565b6040810190811067ffffffffffffffff821117610b0057604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610b0057604052565b9190811015610b7e5760051b0190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60405190610bb882610ae4565b600782527f574e4154495645000000000000000000000000000000000000000000000000006020830152565b6020808252825181830181905293925f5b858110610c34575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b818101830151848201604001528201610bf5565b60405190610c5582610ae4565b600e82527f57726170706564204e61746976650000000000000000000000000000000000006020830152565b91909182600411610128578211610128577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6004920190565b91908260409103126101285760208235610cd38161010a565b92013590565b3415610ce757610ae2610ad9565b5f357fffffffff00000000000000000000000000000000000000000000000000000000167fcab7e8eb000000000000000000000000000000000000000000000000000000008103610dcb5760018073ffffffffffffffffffffffffffffffffffffffff60ff610dbe610d8d610d67610d5f3636610c81565b810190610cba565b941673ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b8360081c7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b5491161c16145f5260205ff35b7f45253c53000000000000000000000000000000000000000000000000000000008103610e2557602436106101285773ffffffffffffffffffffffffffffffffffffffff600435165f525f60205260405f20545f5260205ff35b7f18160ddd000000000000000000000000000000000000000000000000000000008103610e5457475f5260205ff35b7f78e890ba000000000000000000000000000000000000000000000000000000008103610e8a57610e836111ef565b5f5260205ff35b7f06fdde03000000000000000000000000000000000000000000000000000000008103610ed257610eb9610c48565b604051610ece8161063b602082019485610be4565b5190f35b7f95d89b41000000000000000000000000000000000000000000000000000000008103610f0157610eb9610bab565b7f313ce56700000000000000000000000000000000000000000000000000000000036101285760125f5260205ff35b90915f80808093858252600260205260408220968754968288038099558284527f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65602085a25af11591111761012857565b600160ff83161b73ffffffffffffffffffffffffffffffffffffffff82165f526001602052610fde60405f208460081c7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b818154188091551615610128577f8dc5a0b2e80f26187d38744e9559150e3bd6e06fccefbe737fd33411cfb151515f80a3565b60429061101c6111ef565b90604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b929190604183036110be576110746020830135833560408501355f1a84611337565b73ffffffffffffffffffffffffffffffffffffffff868116911614801591906110b6575b506110a4575b50505050565b6110ad936112e1565b5f80808061109e565b90505f611098565b604083036110d65761107460208301358335836112fb565b610ae2936112e1565b9091815f52600260205260405f208054828110610128578290039055825f5260405f208181540190555f527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205fa3565b915f61271092838311610128577dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85116101285773ffffffffffffffffffffffffffffffffffffffff16156111e7575b60098211156111a057508190830204906103e8820204808092038093030392565b929181156111dd57829350807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9304928392018402048093030392565b9050810480910392565b5f915061117f565b467f00000000000000000000000000000000000000000000000000000000000000000361123a577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff821117610b005760405251902090565b929190833b15610128576112f4936113bc565b1561012857565b90611333929160ff601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851694821c011690611337565b9091565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116113b1576020935f9360ff60809460405194855216868401526040830152606082015282805260015afa156113a6575f5173ffffffffffffffffffffffffffffffffffffffff81161591565b6040513d5f823e3d90fd5b505050506001905f90565b5f90602092937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f5f989780604051947f1626ba7e00000000000000000000000000000000000000000000000000000000998a875260048701526040602487015281604487015260648601370116606481830101604052606401915afa60203d1015166114475750565b5f5114915056fea26469706673582212202bc2e977d4326194251bed68a13b88aa97f9f60de0fe047b4a249863c5cc5c6664736f6c634300081800330000000000000000000000004e3c052b97f27156f785c578b99346947e1bb4b3
Deployed Bytecode
0x60806040526004361015610026575b361561001e5761001c610cd9565b005b61001c610ad9565b5f3560e01c8063095ea7b31461010557806323b872dd146101005780632e1a7d4d146100fb57806370a08231146100f6578063a9059cbb146100f1578063b760faf9146100ec578063c2b1a472146100e7578063d0e30db0146100e2578063d4229c24146100dd578063dd62ed3e146100d8578063e06cbc62146100d3578063e5fe69fe146100ce578063f38e809d146100c95763facb18e30361000e576109ec565b610952565b610917565b610730565b6106af565b610503565b6104a3565b61045b565b61041d565b610378565b610311565b6102d5565b6101c2565b61012c565b73ffffffffffffffffffffffffffffffffffffffff81160361012857565b5f80fd5b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356101628161010a565b602435346101b4575b335f52600360205260405f20602052815f528060405f20555f52337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa360015f5260205ff35b6101bd33610a9d565b61016b565b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356101f88161010a565b602435906102058261010a565b604435346102c7575b815f52600260205260405f208054828110610128578290039055825f5260405f2081815401905533820361026d575b5f527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205fa360015f5260205ff35b815f52600360205260405f20602052335f5260405f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81036102b4575b505061023d565b8281106101285782900390555f806102ad565b6102d082610a9d565b61020e565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c6004353333610f30565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285773ffffffffffffffffffffffffffffffffffffffff6004356103618161010a565b165f526002602052602060405f2054604051908152f35b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356103ae8161010a565b6024353461040f575b335f52600260205260405f208054828110610128578290039055815f5260405f208181540190555f52337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205fa360015f5260205ff35b61041833610a9d565b6103b7565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c6004356104568161010a565b610a9d565b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c6004356104998161010a565b6024359033610f30565b5f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c33610a9d565b9181601f840112156101285782359167ffffffffffffffff8311610128576020838186019501011161012857565b60e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356105398161010a565b6024356105458161010a565b604435906064359260843560a4359060c43567ffffffffffffffff8111610128576105749036906004016104d5565b91346106a1575b8342118015610698575b801561067a575b6101285761001c9761067594610667836105a961066f958a610f81565b73ffffffffffffffffffffffffffffffffffffffff89165f525f60205261063b60405f205460405194859360208501973389919260a093969594919673ffffffffffffffffffffffffffffffffffffffff60c08501987f3c038916d033a3e04838da5aca7b9a42656eeae3b520daf7ed52ec02fd37fb9486521660208501526040840152606083015260808201520152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610b2d565b519020611011565b84611052565b6110df565b5073ffffffffffffffffffffffffffffffffffffffff85161561058c565b50878711610585565b6106aa85610a9d565b61057b565b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610128576004356106ea8161010a565b602435906106f78261010a565b73ffffffffffffffffffffffffffffffffffffffff8091165f52600360205260405f2091165f52602052602060405f2054604051908152f35b34610128576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285760043561076c8161010a565b602435906107798261010a565b6044359160a435916064356084356107908561010a565b60c4359060e43567ffffffffffffffff8111610128576107b49036906004016104d5565b97909382421180156108f9575b6101285761001c986108a095610895848b966106678661063b8b8f8f9073ffffffffffffffffffffffffffffffffffffffff828f9361089b9e61080391610f81565b165f525f60205260405f2054604051978896602088019a338c9461010096919294999897939961012087019a7fe55aaa79350b0eb9ee70c987c9b0603c46531ab71d2b7c5404835db2f60e220c885273ffffffffffffffffffffffffffffffffffffffff968780961660208a015260408901526060880152608087015260a08601521660c08401521660e08201520152565b88611052565b611131565b919490806108e8575b5050806108b7575b50610f30565b6108e2907f0000000000000000000000004e3c052b97f27156f785c578b99346947e1bb4b3836110df565b5f6108b1565b6108f291846110df565b5f806108a9565b5073ffffffffffffffffffffffffffffffffffffffff8616156107c1565b346101285760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285761001c60043533610f81565b34610128575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012857335f525f60205260405f20805490816001019055337f9614574d6542397172c19ba2bf4588434feeb977576e92b7b59b38242ab596095f80a3005b9181601f840112156101285782359167ffffffffffffffff8311610128576020808501948460051b01011161012857565b346101285760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101285767ffffffffffffffff60043581811161012857610a3c9036906004016109bb565b909160243590811161012857610a569036906004016109bb565b90818303610128575f5b838110610a6957005b80610a97610a7a6001938789610b6e565b35610a848161010a565b610a8f838787610b6e565b359033610f30565b01610a60565b805f52600260205260405f20348154019055345f527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60205fa2565b610ae233610a9d565b565b6040810190811067ffffffffffffffff821117610b0057604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610b0057604052565b9190811015610b7e5760051b0190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60405190610bb882610ae4565b600782527f574e4154495645000000000000000000000000000000000000000000000000006020830152565b6020808252825181830181905293925f5b858110610c34575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6040809697860101520116010190565b818101830151848201604001528201610bf5565b60405190610c5582610ae4565b600e82527f57726170706564204e61746976650000000000000000000000000000000000006020830152565b91909182600411610128578211610128577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6004920190565b91908260409103126101285760208235610cd38161010a565b92013590565b3415610ce757610ae2610ad9565b5f357fffffffff00000000000000000000000000000000000000000000000000000000167fcab7e8eb000000000000000000000000000000000000000000000000000000008103610dcb5760018073ffffffffffffffffffffffffffffffffffffffff60ff610dbe610d8d610d67610d5f3636610c81565b810190610cba565b941673ffffffffffffffffffffffffffffffffffffffff165f52600160205260405f2090565b8360081c7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b5491161c16145f5260205ff35b7f45253c53000000000000000000000000000000000000000000000000000000008103610e2557602436106101285773ffffffffffffffffffffffffffffffffffffffff600435165f525f60205260405f20545f5260205ff35b7f18160ddd000000000000000000000000000000000000000000000000000000008103610e5457475f5260205ff35b7f78e890ba000000000000000000000000000000000000000000000000000000008103610e8a57610e836111ef565b5f5260205ff35b7f06fdde03000000000000000000000000000000000000000000000000000000008103610ed257610eb9610c48565b604051610ece8161063b602082019485610be4565b5190f35b7f95d89b41000000000000000000000000000000000000000000000000000000008103610f0157610eb9610bab565b7f313ce56700000000000000000000000000000000000000000000000000000000036101285760125f5260205ff35b90915f80808093858252600260205260408220968754968288038099558284527f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65602085a25af11591111761012857565b600160ff83161b73ffffffffffffffffffffffffffffffffffffffff82165f526001602052610fde60405f208460081c7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff165f5260205260405f2090565b818154188091551615610128577f8dc5a0b2e80f26187d38744e9559150e3bd6e06fccefbe737fd33411cfb151515f80a3565b60429061101c6111ef565b90604051917f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201522090565b929190604183036110be576110746020830135833560408501355f1a84611337565b73ffffffffffffffffffffffffffffffffffffffff868116911614801591906110b6575b506110a4575b50505050565b6110ad936112e1565b5f80808061109e565b90505f611098565b604083036110d65761107460208301358335836112fb565b610ae2936112e1565b9091815f52600260205260405f208054828110610128578290039055825f5260405f208181540190555f527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60205fa3565b915f61271092838311610128577dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85116101285773ffffffffffffffffffffffffffffffffffffffff16156111e7575b60098211156111a057508190830204906103e8820204808092038093030392565b929181156111dd57829350807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9304928392018402048093030392565b9050810480910392565b5f915061117f565b467f00000000000000000000000000000000000000000000000000000000000081730361123a577f203501403e693081e811072f909cd2bf162eb3828ff7c30c608384818f01a72190565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f10e20441b5a92700455eb9fe1bd4e33f98bd0733d6a532f2eec1ab8c30caf5d260408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff821117610b005760405251902090565b929190833b15610128576112f4936113bc565b1561012857565b90611333929160ff601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851694821c011690611337565b9091565b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116113b1576020935f9360ff60809460405194855216868401526040830152606082015282805260015afa156113a6575f5173ffffffffffffffffffffffffffffffffffffffff81161591565b6040513d5f823e3d90fd5b505050506001905f90565b5f90602092937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f5f989780604051947f1626ba7e00000000000000000000000000000000000000000000000000000000998a875260048701526040602487015281604487015260648601370116606481830101604052606401915afa60203d1015166114475750565b5f5114915056fea26469706673582212202bc2e977d4326194251bed68a13b88aa97f9f60de0fe047b4a249863c5cc5c6664736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004e3c052b97f27156f785c578b99346947e1bb4b3
-----Decoded View---------------
Arg [0] : infrastructureTaxRecipient (address): 0x4E3c052b97F27156f785c578B99346947e1bb4b3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004e3c052b97f27156f785c578b99346947e1bb4b3
Deployed Bytecode Sourcemap
1757:41700:1:-:0;;;;;;;;;-1:-1:-1;1757:41700:1;;;;;;:::i;:::-;;;6951:53;;:::i;1757:41700::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;14654:9;14650:53;;1757:41700;14713:445;-1:-1:-1;14713:445:1;;1757:41700;14713:445;1757:41700;-1:-1:-1;14713:445:1;1757:41700;14713:445;;-1:-1:-1;14713:445:1;;1757:41700;-1:-1:-1;14713:445:1;;-1:-1:-1;14713:445:1;;;1757:41700;-1:-1:-1;14713:445:1;;-1:-1:-1;14713:445:1;1757:41700;-1:-1:-1;14713:445:1;14650:53;7789:10;;;:::i;:::-;14650:53;;1757:41700;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;19021:9;19017:59;;1757:41700;19086:1327;-1:-1:-1;19086:1327:1;;1757:41700;19086:1327;1757:41700;-1:-1:-1;19086:1327:1;;;;;;;;;;;;;;-1:-1:-1;19086:1327:1;1757:41700;-1:-1:-1;19086:1327:1;;;;;;;;;;;;1757:41700;-1:-1:-1;19086:1327:1;;1757:41700;-1:-1:-1;19086:1327:1;;-1:-1:-1;19086:1327:1;1757:41700;-1:-1:-1;19086:1327:1;;;-1:-1:-1;19086:1327:1;;1757:41700;19086:1327;1757:41700;-1:-1:-1;19086:1327:1;1757:41700;19086:1327;;-1:-1:-1;19086:1327:1;1757:41700;-1:-1:-1;19086:1327:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;19017:59;19060:4;;;:::i;:::-;19017:59;;1757:41700;;;;;;;;;;;10827:6;1757:41700;;9755:10;;10827:6;:::i;1757:41700::-;;;;;;;;;;;;;;;;;:::i;:::-;;-1:-1:-1;1757:41700:1;2170:45;1757:41700;;;;-1:-1:-1;1757:41700:1;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;19021:9;19017:59;;1757:41700;16793:10;-1:-1:-1;19086:1327:1;;1757:41700;19086:1327;1757:41700;-1:-1:-1;19086:1327:1;;;;;;;;;;;;;;-1:-1:-1;19086:1327:1;1757:41700;-1:-1:-1;19086:1327:1;;;;;;;-1:-1:-1;19086:1327:1;16793:10;19086:1327;1757:41700;-1:-1:-1;19086:1327:1;;-1:-1:-1;19086:1327:1;1757:41700;-1:-1:-1;19086:1327:1;19017:59;19060:4;16793:10;19060:4;:::i;:::-;19017:59;;1757:41700;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;10827:6;1757:41700;;;;;:::i;:::-;;;10811:10;;10827:6;:::i;1757:41700::-;;;;;;;;7789:10;;;:::i;1757:41700::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;25952:9;;25948:59;;1757:41700;26021:15;;:28;:73;;;;1757:41700;26021:107;;;;1757:41700;26017:146;;26723:14;26204:5;26663:12;26204:5;26348:268;26204:5;;26283:365;26204:5;;;:::i;:::-;1757:41700;;;-1:-1:-1;1757:41700:1;-1:-1:-1;1757:41700:1;;26348:268;1757:41700;-1:-1:-1;1757:41700:1;1423:113:0;1757:41700:1;;26348:268;;;1757:41700;26348:268;;26434:10;;26348:268;1423:113:0;;;;;;;;;1757:41700:1;1423:113:0;;;1757:41700:1;1423:113:0;1757:41700:1;;;1423:113:0;;;;;;;1757:41700:1;1423:113:0;;;1757:41700:1;1423:113:0;;;1757:41700:1;1423:113:0;1757:41700:1;1423:113:0;26348:268:1;;;;;;;;;:::i;:::-;1423:113:0;26317:317:1;;26283:365;:::i;:::-;26663:12;;:::i;:::-;26723:14;:::i;26021:107::-;1757:41700;;;;26110:18;26021:107;;:73;26065:29;;;;26021:73;;25948:59;25991:4;;;:::i;:::-;25948:59;;1757:41700;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;-1:-1:-1;1757:41700:1;2308:63;1757:41700;;;-1:-1:-1;1757:41700:1;;;-1:-1:-1;1757:41700:1;;;;;-1:-1:-1;1757:41700:1;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;29886:15;;;;;:28;:62;;;;1757:41700;29882:101;;31114:10;30024:5;30745:75;30024:5;30095:480;30024:5;;;30160:383;30024:5;30160:383;30024:5;;;;1757:41700;30024:5;;;30590:12;30024:5;;;;:::i;:::-;1757:41700;30383:13;1757:41700;30383:13;1757:41700;;;30383:13;1757:41700;1423:113:0;1757:41700:1;;30160:383;;;1757:41700;30160:383;;30248:10;;30160:383;1589:183:0;;;;;;;;;;;;;;1757:41700:1;1589:183:0;1757:41700:1;;;;;;;;1589:183:0;;;1423:113;1589:183;;;1757:41700:1;1589:183:0;;;1757:41700:1;1589:183:0;;;1757:41700:1;1589:183:0;;;1757:41700:1;;1589:183:0;;;1423:113;1757:41700:1;1589:183:0;;;1423:113;1589:183;1757:41700:1;1589:183:0;30095:480:1;30590:12;;:::i;:::-;30745:75;:::i;:::-;30835:18;;;;30831:111;;1757:41700;30956:21;;;30952:121;;1757:41700;31114:10;;:::i;30952:121::-;31044:17;31016:26;;31044:17;;:::i;:::-;30952:121;;;30831:111;30916:14;;;;:::i;:::-;30831:111;;;;29886:62;1757:41700;;;;29930:18;29886:62;;1757:41700;;;;;;;;;;;22317:5;1757:41700;;22305:10;22317:5;:::i;1757:41700::-;;;;;;;;;;;21080:378;1757:41700;21080:378;1757:41700;21080:378;;;1757:41700;21080:378;;;;;;;;;;;1757:41700;21080:378;;1757:41700;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;12162:36;;;;12158:75;;-1:-1:-1;12263:22:1;;;;;;1757:41700;12248:13;12320:14;10827:6;12320:14;1757:41700;12320:14;;;;:::i;:::-;1757:41700;;;;:::i;:::-;12336:10;;;;;:::i;:::-;1757:41700;10811:10;;10827:6;:::i;:::-;1757:41700;12248:13;;8461:371;8517:309;;;;;;;;;;;;;;;;;;;;;;8461:371::o;7735:72::-;7789:10;;;:::i;:::-;7735:72::o;1423:113:0:-;2287:32;1423:113;;;;;;;;;;;2287:32;1423:113;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1757:41700:1:-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;2287:32:0;;1757:41700:1;2287:32:0;;;;:::i;:::-;;;;;;;;;:::o;247:9::-;;;;;1423:113;;247:9;;;;;;1423:113;247:9;-1:-1:-1;247:9:0;;;;;;;;;1423:113;;247:9;;;;;;;;;;1423:113;;247:9;;;:::o;:::-;;;;;;;;;;;;;;;;;;2287:32;1757:41700:1;2287:32:0;;;;:::i;:::-;247:9;2287:32;;247:9;;;;;:::o;204:16::-;;;;;4690:1:1;204:16:0;;;;;;;;4690:1:1;204:16:0;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;1757:41700:1;204:16:0;:::o;4420:2285:1:-;4462:9;:13;:9;;4458:2241;;:::i;:::-;4474:1;4535:7;;;1816:43:0;4535:33:1;;1816:43:0;;4747:13:1;4681:8;1757:41700;204:16:0;4747:43:1;:22;4670:43;4681:12;:8;;:12;:::i;:::-;4670:43;;;;:::i;:::-;1757:41700;;;;;;4747:13;1757:41700;;;;;;;4747:22;1757:41700;204:16:0;1757:41700:1;204:16:0;;;;;;;;;;;4747:43:1;1423:113:0;204:16;;1757:41700:1;4746:67;4745:76;4474:1;4839:108;;4474:1;4839:108;4531:2158;1902:44:0;4971:33:1;;1902:44:0;;5057:366:1;;;;;;;;;4474:1;5057:366;4474:1;5057:366;;;4474:1;5057:366;;4474:1;5057:366;;4474:1;5057:366;4967:1722;1988:35:0;5447:32:1;;1988:35:0;;5516:115:1;4474:1;5516:115;;4474:1;5516:115;5443:1246;2072:49:0;5655:39:1;;2072:49:0;;5763:20:1;;:::i;:::-;4474:1;5801:117;;4474:1;5801:117;5651:1038;2155:28:0;5942:24:1;;2155:28:0;;247:9;;:::i;:::-;1757:41700:1;;6027:16;;;;;;;;;:::i;:::-;6061:107;;;5938:751;2219:30:0;6192:26:1;;2219:30:0;;2287:32;;:::i;6188:501:1:-;2287:32:0;6454:28:1;2287:32:0;;6516:112:1;4474:1;6516:112;;4474:1;6516:112;33061:632;;;33151:536;33061:632;;;;33151:536;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33061:632::o;34009:412::-;441:1:0;204:16;;;1757:41700:1;;;;-1:-1:-1;1757:41700:1;441:1:0;1757:41700:1;;34129:43;1757:41700;-1:-1:-1;1757:41700:1;;34169:1;1757:41700;204:16:0;;;;;;;;;;;34129:43:1;1423:113:0;;;34129:68:1;1757:41700;;;34121:118;:126;34117:173;;34310:105;-1:-1:-1;34310:105:1;;34009:412::o;4263:176:4:-;3514:233:6;4263:176:4;4399:20;;:::i;:::-;3514:233:6;;;;;;;;;;;;;;;;4263:176:4;:::o;37173:1471:1:-;;;;37350:2;37330:22;;37350:2;;37795:30;37542:207;;;;;;;;;;-1:-1:-1;37542:207:1;37795:30;;:::i;:::-;1757:41700;;;;;;37843:24;;;;;:35;;37326:1312;37839:132;;;37326:1312;;;;;37173:1471::o;37839:132::-;37946:9;;;:::i;:::-;37839:132;;;;;;37843:35;;;;;;37326:1312;38011:2;37991:22;;38011:2;;38365:28;38181:138;;;;;;38365:28;;:::i;37987:651::-;38617:9;;;:::i;31783:700::-;;;31869:608;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31783:700::o;34922:1408::-;;1757:41700;672:6:0;35179:35:1;;;;35175:74;;672:6:0;35263:26:1;;35259:65;;1757:41700;;35338:36;35334:88;;34922:1408;492:1:0;35460:48:1;;492:1:0;;;;;;;;;;630:5;492:1;;;;;;;;;;;35456:858:1;34922:1408::o;35456:858::-;35869:21;;;;;;492:1:0;;;;;;;;;;;;;;;;;;35865:449:1;34922:1408::o;35865:449::-;492:1:0;;;;;;;35865:449:1;7735:72::o;35334:88::-;1757:41700;;-1:-1:-1;35334:88:1;;3222:230:4;3298:13;3315:14;3298:31;3315:14;;3352:22;3345:29;:::o;3294:152::-;1757:41700:1;;3549:81:4;;;1757:41700:1;1828:95:4;1757:41700:1;;3572:11:4;1757:41700:1;1828:95:4;;1757:41700:1;3585:14:4;1828:95;;;1757:41700:1;3298:13:4;1828:95;;;1757:41700:1;3624:4:4;1828:95;;;1423:113:0;1828:95:4;3549:81;;1828:95;1423:113:0;;;;;;;;;;;1757:41700:1;1423:113:0;;3539:92:4;;3405:30;:::o;39049:275:1:-;;;;39164:18;;:23;39161:61;;41825:1624;;;:::i;:::-;39236:47;39232:86;;39049:275::o;39769:315::-;;40037:30;39769:315;;204:16:0;40000:2:1;323:66:0;39929:19:1;;1757:41700;;;323:66:0;204:16;40037:30:1;;:::i;:::-;40017:50;39769:315;:::o;40742:470::-;40891:66;40878:79;;40874:244;;1757:41700;;-1:-1:-1;1757:41700:1;204:16:0;1757:41700:1;;;;;;;204:16:0;1757:41700:1;;;;;;;;;;;;41137:26;;;;;;;;;-1:-1:-1;41137:26:1;1757:41700;;;41184:20;40742:470;:::o;41137:26::-;1757:41700;;;-1:-1:-1;1757:41700:1;;;;;40874:244;41082:25;;;;41090:4;41082:25;41104:1;41082:25;:::o;41825:1624::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;-1:-1:-1;41825:1624:1:o
Swarm Source
ipfs://2bc2e977d4326194251bed68a13b88aa97f9f60de0fe047b4a249863c5cc5c66
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2,707.06 | 0.01 | $27.07 |
[ 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.