Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Fusion
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 800 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "./common/Singleton.sol";
import "./common/StorageAccessible.sol";
import "./common/NativeCurrencyPaymentFallback.sol";
import "./base/ModuleManager.sol";
import "./base/ProofManager.sol";
import "./handler/TokenCallbackHandler.sol";
import "./external/FusionContext.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
import "./common/NativeCurrencyPaymentFallback.sol";
import {Enum} from "./libraries/Enum.sol";
import {Transaction} from "./libraries/Transaction.sol";
import {Quote} from "./libraries/Quote.sol";
/**
* @title Fusion - A User Friendly Smart Contract Wallet powered by ZK-SNARKs
* @dev Most important concepts :
* - TxVerifier: Address of the Noir based ZK-SNARK verifier contract that will be used to verify proofs and execute transactions on the Fusion Wallet
* - TxHash: The hash used as a public inputs for the transaction verifier
* - nonce: The nonce of the Fusion Wallet
* @author Anoy Roy Chowdhury - <[email protected]>
*/
contract Fusion is
Singleton,
StorageAccessible,
ModuleManager,
ProofManager,
TokenCallbackHandler,
NativeCurrencyPaymentFallback,
FusionContext
{
string public constant VERSION = "1.0.0";
// The address of the Noir based ZK-SNARK verifier contract
address public TxVerifier;
// The hash used as a public inputs for verifiers
bytes32 public TxHash;
// The nonce of the Fusion Wallet
uint256 private nonce;
event SetupFusion(address txVerifier, bytes32 txHash);
// This constructor ensures that this contract can only be used as a singleton for Proxy contracts
constructor() {
/**
* By setting the TxHash to bytes32(uint256(1)), it is not possible to call setupFusion anymore,
* This is an unusable Fusion Wallet, and it is only used to deploy the proxy contract
*/
TxHash = bytes32(uint256(1));
}
/**
* @notice Initializes the Fusion Wallet
* @dev The function is called only once during deployment
* If the proxy was created without setting up, anyone can call setup and claim the proxy
* @param _txVerifier The address of the Noir based ZK-SNARK verifier contract
* @param _txHash The hash used as a public inputs for verifiers
* @param to The destination address of the call to execute
* @param data The data of the call to
*/
function setupFusion(
address _txVerifier,
bytes32 _txHash,
address to,
bytes calldata data
) external {
require(TxVerifier == address(0), "Fusion: already initialized");
require(TxHash == bytes32(uint256(0)), "Fusion: already initialized");
TxVerifier = _txVerifier;
TxHash = _txHash;
setupModules(to, data);
emit SetupFusion(_txVerifier, _txHash);
}
/**
* @notice Executes a transaction
* @param _proof The zk-SNARK proof
* @param txData call to perform
*/
function executeTx(
bytes calldata _proof,
Transaction.TransactionData calldata txData
) public payable returns (bool success) {
// Verifying the proof
require(
verify(
_proof,
Transaction.getTxHash(
txData,
_useNonce(),
getChainId(),
address(0),
0,
0,
0
),
TxHash,
TxVerifier
),
"Fusion: invalid proof"
);
// Execute the call
success = execute(
txData.to,
txData.value,
txData.data,
txData.operation,
txData.gasLimit
);
}
/**
* @notice Executes a batch of transactions.
* @dev This method will revert if any of the transactions fail.
* @param _proof The zk-SNARK proof
* @param transactions Array of Transaction objects.
*/
function executeBatchTx(
bytes calldata _proof,
Transaction.TransactionData[] calldata transactions
) public payable {
// Verifying the proof
require(
verify(
_proof,
Transaction.getTxBatchHash(
transactions,
_useNonce(),
getChainId(),
address(0),
0,
0,
0
),
TxHash,
TxVerifier
),
"Fusion: invalid proof"
);
// Execute the batch call
batchExecute(transactions);
}
/**
* @notice Executes a transaction with a gas quote from a provider
* @param _proof The zk-SNARK proof
* @param txData call to perform
* @param quote The gas quote
*/
function executeTxWithProvider(
bytes calldata _proof,
Transaction.TransactionData calldata txData,
Quote.GasQuote calldata quote
) public payable {
// Verifying the proof
require(
verify(
_proof,
Transaction.getTxHash(
txData,
_useNonce(),
getChainId(),
quote.token,
quote.gasPrice,
quote.baseGas,
quote.deadline
),
TxHash,
TxVerifier
),
"Fusion: invalid proof"
);
// Check if the balance is sufficient
require(
checkBalance(quote.token, quote.estimatedFees),
"Fusion: insufficient balance"
);
// Check Deadline
require(block.timestamp <= quote.deadline, "Fusion: deadline exceeded");
uint256 startGas = gasleft();
require(
execute(
txData.to,
txData.value,
txData.data,
txData.operation,
txData.gasLimit
),
"Fusion: execution failed"
);
chargeFees(
startGas,
quote.gasPrice,
quote.baseGas,
quote.gasRecipient,
quote.token
);
}
/**
* @notice Executes a batch of transactions with a gas quote from a provider
* @param _proof The zk-SNARK proof
* @param transactions Array of Transaction objects.
* @param quote The gas quote
*/
function executeBatchTxWithProvider(
bytes calldata _proof,
Transaction.TransactionData[] calldata transactions,
Quote.GasQuote calldata quote
) public payable {
// Verifying the proof
require(
verify(
_proof,
Transaction.getTxBatchHash(
transactions,
_useNonce(),
getChainId(),
quote.token,
quote.gasPrice,
quote.baseGas,
quote.deadline
),
TxHash,
TxVerifier
),
"Fusion: invalid proof"
);
// Check if the balance is sufficient
require(
checkBalance(quote.token, quote.estimatedFees),
"Fusion: insufficient balance"
);
// Check Deadline
require(block.timestamp <= quote.deadline, "Fusion: deadline exceeded");
uint256 startGas = gasleft();
batchExecute(transactions);
chargeFees(
startGas,
quote.gasPrice,
quote.baseGas,
quote.gasRecipient,
quote.token
);
}
/**
* @notice Checks if the balance is sufficient
* @param token The address of the token to be used for fees
* @param estimatedFees The estimated fees for the transaction
*/
function checkBalance(
address token,
uint256 estimatedFees
) internal view returns (bool) {
if (token != address(0)) {
uint8 decimals = IERC20Metadata(token).decimals();
if (
IERC20(token).balanceOf(address(this)) <
estimatedFees / 10 ** (18 - decimals)
) {
return false;
}
} else {
if (address(this).balance < estimatedFees) {
return false;
}
}
return true;
}
/**
* @notice Verifies if the proof is valid or not
* @dev The parameters are named to maintain the same implementation as EIP-1271
* Should return whether the proof provided is valid for the provided data
* @param _hash the message which is used to verify zero-knowledge proof
* @param _signature Noir based zero-knowledge proof
*/
function isValidSignature(
bytes32 _hash,
bytes calldata _signature
) public view returns (bytes4 magicValue) {
if (verify(_signature, _hash, TxHash, TxVerifier)) {
return 0x1626ba7e;
} else {
return 0xffffffff;
}
}
/**
* @notice Returns the nonce of the Fusion Wallet
*/
function getNonce() public view returns (uint256) {
return nonce;
}
/**
* @notice Returns the nonce of the Fusion Wallet and increments it
*/
function _useNonce() internal returns (uint256) {
unchecked {
return nonce++;
}
}
/**
* @notice Gets the chain ID of the current network
*/
function getChainId() internal view returns (uint256 chainId) {
assembly {
chainId := chainid()
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(
address owner,
address spender
) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import {Enum} from "../libraries/Enum.sol";
import {Transaction} from "../libraries/Transaction.sol";
/**
* @title Executor - A contract that can execute transactions
* @author Anoy Roy Chowdhury - <[email protected]>
*/
abstract contract Executor {
/**
* @notice Executes a call with provided parameters.
* @dev This method doesn't perform any sanity check of the transaction, such as:
* - if the contract at `to` address has code or not
* It is the responsibility of the caller to perform such checks.
* @param to Destination address.
* @param value Ether value.
* @param data Data payload.
* @return success boolean flag indicating if the call succeeded.
*/
function execute(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 txGas
) internal returns (bool success) {
uint256 gasLeft;
if (operation == Enum.Operation.DelegateCall) {
/* solhint-disable no-inline-assembly */
assembly ("memory-safe") {
success := delegatecall(
txGas,
to,
add(data, 0x20),
mload(data),
0,
0
)
gasLeft := gas()
}
/* solhint-enable no-inline-assembly */
} else {
/* solhint-disable no-inline-assembly */
assembly ("memory-safe") {
success := call(
txGas,
to,
value,
add(data, 0x20),
mload(data),
0,
0
)
gasLeft := gas()
}
/* solhint-enable no-inline-assembly */
}
// Check if the gas left is less than 1/63 of the initial gas
// To avoid insufficient gas griefing attacks, as referenced in https://ronan.eth.limo/blog/ethereum-gas-dangers/
if (gasLeft < txGas / 63) {
assembly ("memory-safe") {
invalid()
}
}
}
/**
* @notice Executes a batch of transactions.
* @dev This method doesn't perform any sanity check of the transactions, such as:
* - if the contract at `to` address has code or not
* It is the responsibility of the caller to perform such checks.
* @param transactions Array of Transaction objects.
*/
function batchExecute(
Transaction.TransactionData[] memory transactions
) internal {
for (uint256 i = 0; i < transactions.length; i++) {
bool success = execute(
transactions[i].to,
transactions[i].value,
transactions[i].data,
transactions[i].operation,
transactions[i].gasLimit
);
require(success, "Fusion: batch execution failed");
}
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "../common/SelfAuthorized.sol";
import {Enum} from "../libraries/Enum.sol";
import "./Executor.sol";
/**
* @title ModuleManager - Manages the modules of the Fusion Wallet.
* @author Anoy Roy Chowdhury - <[email protected]>
*/
abstract contract ModuleManager is SelfAuthorized, Executor {
event EnabledModule(address module);
event DisabledModule(address module);
// The sentinel value used to indicate the start of the list.
address internal constant SENTINEL_MODULES = address(0x1);
// A mapping from modules to the previous module in the list.
mapping(address => address) internal modules;
/**
* @notice Setup function sets the initial storage of the contract.
* Optionally executes a delegate call to another contract to setup the modules.
* @param to Optional destination address of call to execute.
* @param data Optional data of call to execute.
*/
function setupModules(address to, bytes memory data) internal {
require(
modules[SENTINEL_MODULES] == address(0),
"Modules already initialized"
);
modules[SENTINEL_MODULES] = SENTINEL_MODULES;
if (to != address(0)) {
require(isContract(to), "Invalid Module");
// Setup has to complete successfully or transaction fails.
require(
execute(
to,
0,
data,
Enum.Operation.DelegateCall,
type(uint256).max
),
"Module setup failed"
);
}
}
/**
* @notice Enables a module for the Fusion Wallet.
* @param module The module to be enabled.
*/
function enableModule(address module) external authorized {
// Module address cannot be null or sentinel.
if (module == address(0) || module == SENTINEL_MODULES)
revert("Fusion: INVALID_MODULE_ADDRESS");
// Module cannot be added twice.
if (modules[module] != address(0)) revert("Fusion: MODULE_EXISTS");
modules[module] = modules[SENTINEL_MODULES];
modules[SENTINEL_MODULES] = module;
emit EnabledModule(module);
}
/**
* @notice Disables a module for the Fusion Wallet.
* @param prevModule The previous module in the list.
* @param module The module to be disabled.
*/
function disableModule(
address prevModule,
address module
) external authorized {
// Validate module address and check that it corresponds to module index.
if (module == address(0) || module == SENTINEL_MODULES)
revert("Fusion: INVALID_MODULE_ADDRESS");
if (modules[prevModule] != module) revert("Fusion: INVALID_MODULE");
modules[prevModule] = modules[module];
modules[module] = address(0);
emit DisabledModule(module);
}
function execTransactionFromModule(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation
) external returns (bool success) {
require(
modules[msg.sender] != address(0),
"Fusion: UNAUTHORIZED_MODULE"
);
success = execute(to, value, data, operation, gasleft());
}
/**
* @notice Returns the modules of the linked list.
* @param start The start of the linked list or the sentinel address.
* @param pageSize The size of the page.
*/
function getModulesPaginated(
address start,
uint256 pageSize
) external view returns (address[] memory array, address next) {
if (start != SENTINEL_MODULES && !isModuleEnabled(start))
revert("Fusion: INVALID_START_MODULE");
if (pageSize == 0) revert("Fusion: INVALID_PAGE_SIZE");
// Init array with max page size
array = new address[](pageSize);
// Populate return array
uint256 moduleCount = 0;
next = modules[start];
while (
next != address(0) &&
next != SENTINEL_MODULES &&
moduleCount < pageSize
) {
array[moduleCount] = next;
next = modules[next];
moduleCount++;
}
/**
Because of the argument validation, we can assume that the loop will always iterate over the valid module list values
and the `next` variable will either be an enabled module or a sentinel address (signalling the end).
If we haven't reached the end inside the loop, we need to set the next pointer to the last element of the modules array
because the `next` variable (which is a module by itself) acting as a pointer to the start of the next page is neither
included to the current page, nor will it be included in the next one if you pass it as a start.
*/
if (next != SENTINEL_MODULES) {
next = array[moduleCount - 1];
}
// Set correct size of returned array
/* solhint-disable no-inline-assembly */
/// @solidity memory-safe-assembly
assembly {
mstore(array, moduleCount)
}
/* solhint-enable no-inline-assembly */
}
/**
* @notice Checks if the module is a part of the linked list.
* @param module The module to be checked.
*/
function isModuleEnabled(address module) public view returns (bool) {
return SENTINEL_MODULES != module && modules[module] != address(0);
}
/**
* @notice Returns true if `account` is a contract.
* @dev This function will return false if invoked during the constructor of a contract,
* as the code is not actually created until after the constructor finishes.
* @param account The address being queried
*/
function isContract(address account) internal view returns (bool) {
uint256 size;
/* solhint-disable no-inline-assembly */
/// @solidity memory-safe-assembly
assembly {
size := extcodesize(account)
}
/* solhint-enable no-inline-assembly */
return size > 0;
}
}// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import "./Verifier.sol"; import "../libraries/Conversion.sol"; /** * @title Proof Manager - Converts given hash to public inputs and verifies the proof * @notice This contract is a base contract for coverting given hash to public inputs and verifying the proof * @author Anoy Roy Chowdhury - <[email protected]> */ abstract contract ProofManager is Verifier { /** * @notice Verifies the proof and returns the result of verification. * @param _proof The proof inputs * @param _message The message hash * @param _hash The hash of the user that verifies the proof * @param _verifier The address of the verifier contract * @dev _verifyingAddress should be address(0) if the message was signed directly by the EOA */ function verify( bytes calldata _proof, bytes32 _message, bytes32 _hash, address _verifier ) internal view returns (bool) { bytes32[] memory publicInputs = Conversion.convertToInputs( _message, _hash ); return verifyProof(_proof, publicInputs, _verifier); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title UltraVerifierInterface - Interface for verification of proofs * @author Anoy Roy Chowdhury - <[email protected]> * @notice This Interface is used to verify proofs using UltraVerifier */ interface UltraVerifierInterface { function verify( bytes calldata _proof, bytes32[] calldata _publicInputs ) external view returns (bool); } /** * @title Verifier - Base contract for verification of proofs * @dev This contract is used to verify proofs using UltraVerifier */ abstract contract Verifier { /** * @notice Verifies the proof and returns the result of verification. * @param _proof The proof inputs * @param _publicInputs The public inputs * @param _verifier The address of the verifier contract */ function verifyProof( bytes calldata _proof, bytes32[] memory _publicInputs, address _verifier ) internal view returns (bool) { return UltraVerifierInterface(_verifier).verify(_proof, _publicInputs); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title NativeCurrencyPaymentFallback - A contract that has a fallback to accept native currency payments. * @author Anoy Roy Chowdhury <[email protected]> */ abstract contract NativeCurrencyPaymentFallback { event FusionReceived(address indexed sender, uint256 value); /** * @notice Receive function accepts native currency transactions. * @dev Emits an event with sender and received value. */ receive() external payable { emit FusionReceived(msg.sender, msg.value); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title SelfAuthorized - Authorizes current contract to perform actions to itself. * @author Anoy Roy Chowdhury - <[email protected]> */ abstract contract SelfAuthorized { function requireSelfCall() private view { if (msg.sender != address(this)) { revert("ONLY_CALLABLE_BY_SELF"); } } modifier authorized() { // Modifiers are copied around during compilation. This is a function call as it minimized the bytecode size requireSelfCall(); _; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title Singleton - Base for singleton contracts (should always be the first super contract) * @author Anoy Roy Chowdhury - <[email protected]> */ abstract contract Singleton { // singleton always has to be the first declared variable to ensure the same location as in the Proxy contract. // It should also always be ensured the address is stored alone (uses a full word) address private singleton; }
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/**
* @title StorageAccessible - A generic base contract that allows callers to access all internal storage.
* @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
* It removes a method from the original contract not needed for the Safe contracts.
* @author Gnosis Developers
*/
abstract contract StorageAccessible {
/**
* @notice Reads `length` bytes of storage in the currents contract
* @param offset - the offset in the current contract's storage in words to start reading from
* @param length - the number of words (32 bytes) of data to read
* @return the bytes that were read.
*/
function getStorageAt(
uint256 offset,
uint256 length
) public view returns (bytes memory) {
bytes memory result = new bytes(length * 32);
for (uint256 index = 0; index < length; index++) {
// solhint-disable-next-line no-inline-assembly
assembly {
let word := sload(add(offset, index))
mstore(add(add(result, 0x20), mul(index, 0x20)), word)
}
}
return result;
}
/**
* @dev Performs a delegatecall on a targetContract in the context of self.
* Internally reverts execution to avoid side effects (making it static).
*
* This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.
* Specifically, the `returndata` after a call to this method will be:
* `success:bool || response.length:uint256 || response:bytes`.
*
* @param targetContract Address of the contract containing the code to execute.
* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
*/
function simulateAndRevert(
address targetContract,
bytes memory calldataPayload
) external {
// solhint-disable-next-line no-inline-assembly
assembly {
let success := delegatecall(
gas(),
targetContract,
add(calldataPayload, 0x20),
mload(calldataPayload),
0,
0
)
mstore(0x00, success)
mstore(0x20, returndatasize())
returndatacopy(0x40, 0, returndatasize())
revert(0, add(returndatasize(), 0x40))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev FusionContext - A contract that charges fees for the transaction.
* @author Anoy Roy Chowdhury - <[email protected]>
*/
abstract contract FusionContext {
/**
* @notice Charges the fees for the transaction.
* @param startGas Gas used before calling the function
* @param gasPrice gas price of the transaction
* @param baseGas base gas deducted by the relayer
* @param GasTank address of the GasTank
* @param token address of the token
*/
function chargeFees(
uint256 startGas,
uint256 gasPrice,
uint256 baseGas,
address GasTank,
address token
) internal {
uint256 gasUsed = startGas - gasleft();
uint256 gasFee = (gasUsed + baseGas) * gasPrice;
if (token != address(0)) {
uint8 decimals = IERC20Metadata(token).decimals();
uint256 transferAmount = gasFee / 10 ** (18 - decimals);
// Low-level call with additional check for tokens without return value
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(
IERC20.transfer.selector,
GasTank,
transferAmount
)
);
bool transferSucceeded = success &&
(data.length == 0 || abi.decode(data, (bool)));
if (!transferSucceeded) {
revert("Fusion: fee transfer failed");
}
} else {
(bool success, ) = GasTank.call{value: gasFee}("");
if (!success) {
revert("Fusion: fee transfer failed");
}
}
}
}// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; import "../interfaces/ERC1155TokenReceiver.sol"; import "../interfaces/ERC721TokenReceiver.sol"; import "../interfaces/ERC777TokensRecipient.sol"; import "../interfaces/IERC165.sol"; /** * @title Default Callback Handler - Handles supported tokens' callbacks, allowing Safes receiving these tokens. * @author Anoy Roy Chowdhury - <[email protected]> */ contract TokenCallbackHandler is ERC1155TokenReceiver, ERC777TokensRecipient, ERC721TokenReceiver, IERC165 { /** * @notice Handles ERC1155 Token callback. * return Standardized onERC1155Received return value. */ function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external pure override returns (bytes4) { return 0xf23a6e61; } /** * @notice Handles ERC1155 Token batch callback. * return Standardized onERC1155BatchReceived return value. */ function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external pure override returns (bytes4) { return 0xbc197c81; } /** * @notice Handles ERC721 Token callback. * return Standardized onERC721Received return value. */ function onERC721Received( address, address, uint256, bytes calldata ) external pure override returns (bytes4) { return 0x150b7a02; } /** * @notice Handles ERC777 Token callback. * return nothing (not standardized) */ function tokensReceived( address, address, address, uint256, bytes calldata, bytes calldata ) external pure override { // We implement this for completeness, doesn't really have any value } /** * @notice Implements ERC165 interface support for ERC1155TokenReceiver, ERC721TokenReceiver and IERC165. * @param interfaceId Id of the interface. * @return if the interface is supported. */ function supportsInterface( bytes4 interfaceId ) external view virtual override returns (bool) { return interfaceId == type(ERC1155TokenReceiver).interfaceId || interfaceId == type(ERC721TokenReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
// Note: The ERC-165 identifier for this interface is 0x4e2312e0.
interface ERC1155TokenReceiver {
/**
* @notice Handle the receipt of a single ERC1155 token type.
* @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.
* This function MUST return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.
* This function MUST revert if it rejects the transfer.
* Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
* @param _operator The address which initiated the transfer (i.e. msg.sender).
* @param _from The address which previously owned the token.
* @param _id The ID of the token being transferred.
* @param _value The amount of tokens being transferred.
* @param _data Additional data with no specified format.
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`.
*/
function onERC1155Received(
address _operator,
address _from,
uint256 _id,
uint256 _value,
bytes calldata _data
) external returns (bytes4);
/**
* @notice Handle the receipt of multiple ERC1155 token types.
* @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.
* This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).
* This function MUST revert if it rejects the transfer(s).
* Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
* @param _operator The address which initiated the batch transfer (i.e. msg.sender).
* @param _from The address which previously owned the token.
* @param _ids An array containing ids of each token being transferred (order and length must match _values array).
* @param _values An array containing amounts of each token being transferred (order and length must match _ids array).
* @param _data Additional data with no specified format.
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`.
*/
function onERC1155BatchReceived(
address _operator,
address _from,
uint256[] calldata _ids,
uint256[] calldata _values,
bytes calldata _data
) external returns (bytes4);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface ERC721TokenReceiver {
/**
* @notice Handle the receipt of an NFT
* @dev The ERC721 smart contract calls this function on the recipient
* after a `transfer`. This function MAY throw to revert and reject the
* transfer. Return of other than the magic value MUST result in the
* transaction being reverted.
* Note: the contract address is always the message sender.
* @param _operator The address which called `safeTransferFrom` function.
* @param _from The address which previously owned the token.
* @param _tokenId The NFT identifier which is being transferred.
* @param _data Additional data with no specified format.
* @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
* unless throwing
*/
function onERC721Received(
address _operator,
address _from,
uint256 _tokenId,
bytes calldata _data
) external returns (bytes4);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/**
* @title ERC777TokensRecipient
* @dev Interface for contracts that will be called with the ERC777 token's `tokensReceived` method.
* The contract receiving the tokens must implement this interface in order to receive the tokens.
*/
interface ERC777TokensRecipient {
/**
* @dev Called by the ERC777 token contract after a successful transfer or a minting operation.
* @param operator The address of the operator performing the transfer or minting operation.
* @param from The address of the sender.
* @param to The address of the recipient.
* @param amount The amount of tokens that were transferred or minted.
* @param data Additional data that was passed during the transfer or minting operation.
* @param operatorData Additional data that was passed by the operator during the transfer or minting operation.
*/
function tokensReceived(
address operator,
address from,
address to,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @notice More details at https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by `interfaceId`.
* See the corresponding EIP section
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title Conversion - A contract that can convert to publicInputs compatible with UltraVerifier * @notice This contract is a library that provides functions to convert between different types * @author Anoy Roy Chowdhury - <[email protected]> */ library Conversion { /** * @notice Convert a bytes32 value to a padded bytes32 value * @param value The value to be converted to bytes32 */ function convertToPaddedByte32( bytes32 value ) internal pure returns (bytes32) { bytes32 paddedValue; paddedValue = bytes32(uint256(value) >> (31 * 8)); return paddedValue; } /** * @notice Convert the message hash to public inputs * @param _message The message hash * @param _hash The hash of the user that verifies the proof */ function convertToInputs( bytes32 _message, bytes32 _hash ) internal pure returns (bytes32[] memory) { bytes32[] memory byte32Inputs = new bytes32[](33); bytes32 messageHash = getEthSignedMessageHash(_message); for (uint256 i = 0; i < 32; i++) { byte32Inputs[i] = convertToPaddedByte32(messageHash[i]); } byte32Inputs[32] = _hash; return byte32Inputs; } /** * @notice Get the hash of a message that was signed * @param _messageHash The hash of the message that was signed */ function getEthSignedMessageHash( bytes32 _messageHash ) public pure returns (bytes32) { return keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", _messageHash ) ); } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title Enum - Collection of enums used in Fusion contracts. * @author Anoy Roy Chowdhury - <[email protected]> */ library Enum { enum Operation { Call, DelegateCall } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.0 <0.9.0; /** * @title Quote - Collection of structs used in Fusion gas quotes. * @author Anoy Roy Chowdhury - <[email protected]> */ library Quote { // GasQuote struct struct GasQuote { address token; uint256 gasPrice; uint256 baseGas; uint256 estimatedFees; address gasRecipient; uint48 deadline; } }
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import {Enum} from "./Enum.sol";
/**
* @title Transaction - Library for handling transactions in Fusion Wallet
* @author Anoy Roy Chowdhury - <[email protected]>
*/
library Transaction {
struct TransactionData {
address to;
uint256 value;
bytes data;
Enum.Operation operation;
uint256 gasLimit;
}
/**
* @notice Encode the transaction data with nonce
* @param _tx The transaction data
* @param _nonce The nonce of the Fusion Wallet
* @param _chainId The chain id of the network
* @param _token The token address
* @param _gasPrice The gas price
* @param _baseGas The base gas
*/
function encodeWithNonce(
TransactionData memory _tx,
uint256 _nonce,
uint256 _chainId,
address _token,
uint256 _gasPrice,
uint256 _baseGas,
uint48 _deadline
) internal pure returns (bytes memory) {
return
abi.encode(
_tx.to,
_tx.value,
_tx.data,
uint8(_tx.operation),
_nonce,
_chainId,
_token,
_gasPrice,
_baseGas,
_deadline,
_tx.gasLimit
);
}
/**
* @notice Get the hash of a transaction
* @param _tx The transaction data
* @param _nonce The nonce of the Fusion Wallet
* @param _chainId The chain id of the network
* @param _token The token address
* @param _gasPrice The gas price
* @param _baseGas The base gas
*/
function getTxHash(
TransactionData memory _tx,
uint256 _nonce,
uint256 _chainId,
address _token,
uint256 _gasPrice,
uint256 _baseGas,
uint48 _deadline
) internal pure returns (bytes32) {
return
keccak256(
encodeWithNonce(
_tx,
_nonce,
_chainId,
_token,
_gasPrice,
_baseGas,
_deadline
)
);
}
/**
* @notice Get the hash of a batch of transactions
* @param _txs All the transactions in the batch
* @param _nonce The nonce of the Fusion Wallet
* @param _chainId The chain id of the network
* @param _token The token address
* @param _gasPrice The gas price
* @param _baseGas The base gas
*/
function getTxBatchHash(
TransactionData[] memory _txs,
uint256 _nonce,
uint256 _chainId,
address _token,
uint256 _gasPrice,
uint256 _baseGas,
uint48 _deadline
) internal pure returns (bytes32) {
bytes memory txsData;
for (uint256 i = 0; i < _txs.length; i++) {
txsData = abi.encodePacked(
txsData,
encodeWithNonce(
_txs[i],
_nonce,
_chainId,
_token,
_gasPrice,
_baseGas,
_deadline
)
);
}
return keccak256(txsData);
}
}{
"optimizer": {
"enabled": true,
"runs": 800,
"details": {
"yulDetails": {
"optimizerSteps": "u"
}
}
},
"evmVersion": "paris",
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"DisabledModule","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"EnabledModule","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"FusionReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"txVerifier","type":"address"},{"indexed":false,"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"SetupFusion","type":"event"},{"inputs":[],"name":"TxHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TxVerifier","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"prevModule","type":"address"},{"internalType":"address","name":"module","type":"address"}],"name":"disableModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"enableModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"}],"name":"execTransactionFromModule","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_proof","type":"bytes"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"},{"internalType":"uint256","name":"gasLimit","type":"uint256"}],"internalType":"struct Transaction.TransactionData[]","name":"transactions","type":"tuple[]"}],"name":"executeBatchTx","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_proof","type":"bytes"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"},{"internalType":"uint256","name":"gasLimit","type":"uint256"}],"internalType":"struct Transaction.TransactionData[]","name":"transactions","type":"tuple[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"baseGas","type":"uint256"},{"internalType":"uint256","name":"estimatedFees","type":"uint256"},{"internalType":"address","name":"gasRecipient","type":"address"},{"internalType":"uint48","name":"deadline","type":"uint48"}],"internalType":"struct Quote.GasQuote","name":"quote","type":"tuple"}],"name":"executeBatchTxWithProvider","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_proof","type":"bytes"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"},{"internalType":"uint256","name":"gasLimit","type":"uint256"}],"internalType":"struct Transaction.TransactionData","name":"txData","type":"tuple"}],"name":"executeTx","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_proof","type":"bytes"},{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"},{"internalType":"uint256","name":"gasLimit","type":"uint256"}],"internalType":"struct Transaction.TransactionData","name":"txData","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"uint256","name":"baseGas","type":"uint256"},{"internalType":"uint256","name":"estimatedFees","type":"uint256"},{"internalType":"address","name":"gasRecipient","type":"address"},{"internalType":"uint48","name":"deadline","type":"uint48"}],"internalType":"struct Quote.GasQuote","name":"quote","type":"tuple"}],"name":"executeTxWithProvider","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"start","type":"address"},{"internalType":"uint256","name":"pageSize","type":"uint256"}],"name":"getModulesPaginated","outputs":[{"internalType":"address[]","name":"array","type":"address[]"},{"internalType":"address","name":"next","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"getStorageAt","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"isModuleEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_txVerifier","type":"address"},{"internalType":"bytes32","name":"_txHash","type":"bytes32"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setupFusion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"targetContract","type":"address"},{"internalType":"bytes","name":"calldataPayload","type":"bytes"}],"name":"simulateAndRevert","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6080604052346200002657620000146200005c565b6040516128c76200008182396128c790f35b600080fd5b6200003b6200003b6200003b9290565b90565b906200003b6200005262000058926200003b565b6200003b565b9055565b6200007e620000766200007060016200002b565b6200002b565b60036200003e565b56fe60806040526004361015610023575b361561001957600080fd5b610021611c3f565b005b60003560e01c806223de291461018257806301ffc9a71461017d578063150b7a02146101785780631626ba7e146101735780631692d4ef1461016e5780631db6f9b6146101695780632d9ad53d14610164578063468721a71461015f5780635624b25b1461015a5780635691126814610155578063610b592514610150578063aef8c46e1461014b578063b4faba0914610146578063bc197c8114610141578063be91404f1461013c578063c2ded10b14610137578063cc2f845214610132578063d087d2881461012d578063e009cfde14610128578063e4d52aa714610123578063f23a6e611461011e5763ffa1ad740361000e57610c2b565b610bac565b610b30565b610ae6565b610aa8565b610a79565b6109ba565b610959565b6108ea565b61084c565b6107eb565b6107b1565b61079a565b610709565b61065f565b610515565b6104e5565b610418565b6103c6565b610356565b6102d9565b610283565b6001600160a01b031690565b90565b6001600160a01b0381165b036101a857565b600080fd5b905035906101ba82610196565b565b806101a1565b905035906101ba826101bc565b909182601f830112156101a85781359167ffffffffffffffff83116101a85760200192600183028401116101a857565b60c0818303126101a85761021382826101ad565b9261022183602084016101ad565b9261022f81604085016101ad565b9261023d82606083016101c2565b92608082013567ffffffffffffffff81116101a8578361025e9184016101cf565b92909360a082013567ffffffffffffffff81116101a85761027f92016101cf565b9091565b346101a8576102933660046101ff565b505050505050505061002160405190565b0390f35b6001600160e01b031981166101a1565b905035906101ba826102a8565b906020828203126101a857610193916102b8565b346101a8576102a46102f46102ef3660046102c5565b610c46565b60405191829182901515815260200190565b906080828203126101a85761031b81836101ad565b9261032982602085016101ad565b9261033783604083016101c2565b92606082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a461037561036c366004610306565b93929092610cbf565b604051918291826001600160e01b0319909116815260200190565b9190916040818403126101a8576103a783826101c2565b92602082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a46103756103dc366004610390565b91610cfe565b60009103126101a857565b610193916008021c6001600160a01b031690565b9061019391546103ed565b61019360006002610401565b346101a8576104283660046103e2565b6102a461043361040c565b604051918291826001600160a01b03909116815260200190565b909182601f830112156101a85781359167ffffffffffffffff83116101a85760200192602083028401116101a857565b908160c09103126101a85790565b610100818303126101a857803567ffffffffffffffff81116101a857826104b39183016101cf565b929093602083013567ffffffffffffffff81116101a857826104dc60409461019393870161044d565b9490950161047d565b6104fc6104f336600461048b565b93929092610f66565b604051005b906020828203126101a857610193916101ad565b346101a8576102a46102f461052b366004610501565b6110db565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff82111761056857604052565b610530565b906101ba61057a60405190565b9283610546565b67ffffffffffffffff811161056857602090601f01601f19160190565b0190565b90826000939282370152565b909291926105c36105be82610581565b61056d565b93818552818301116101a8576101ba9160208501906105a2565b9080601f830112156101a857816020610193933591016105ae565b600211156101a857565b905035906101ba826105f8565b6080818303126101a85761062382826101ad565b9261063183602084016101c2565b9260408301359067ffffffffffffffff82116101a8576060610658826101939487016105dd565b9401610602565b346101a8576102a46102f461067536600461060f565b92919091611180565b91906040838203126101a85761019390602061069a82866101c2565b94016101c2565b60005b8381106106b45750506000910152565b81810151838201526020016106a4565b6106e56106ee60209361059e936106d9815190565b80835293849260200190565b958691016106a1565b601f01601f191690565b6020808252610193929101906106c4565b346101a8576102a461072561071f36600461067e565b90611221565b604051918291826106f8565b908160a09103126101a85790565b919091610100818403126101a857803567ffffffffffffffff81116101a8578361076a9183016101cf565b92909360208301359067ffffffffffffffff82116101a857604061079382610193948701610731565b940161047d565b6104fc6107a836600461073f565b92919091611340565b346101a8576104fc6107c4366004610501565b6115ff565b610193916008021c81565b9061019391546107c9565b610193600060036107d4565b346101a8576107fb3660046103e2565b6102a46108066107df565b6040519182918290815260200190565b9190916040818403126101a85761082d83826101ad565b92602082013567ffffffffffffffff81116101a85761019392016105dd565b346101a85761085c366004610816565b90611608565b9160a0838303126101a85761087782846101ad565b9261088583602083016101ad565b92604082013567ffffffffffffffff81116101a857816108a691840161044d565b929093606082013567ffffffffffffffff81116101a857836108c991840161044d565b929093608082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a4610375610900366004610862565b9695909594919493929361162b565b90916040828403126101a857813567ffffffffffffffff81116101a857836109389184016101cf565b929093602082013567ffffffffffffffff81116101a85761027f920161044d565b6104fc61096736600461090f565b92919091611661565b90916040828403126101a857813567ffffffffffffffff81116101a857836109999184016101cf565b929093602082013567ffffffffffffffff81116101a8576101939201610731565b6102a46102f46109cb366004610970565b916116c7565b91906040838203126101a85761019390602061069a82866101ad565b90610a0d610a066109fc845190565b8084529260200190565b9260200190565b9060005b818110610a1e5750505090565b909192610a44610a3d60019286516001600160a01b0316815260200190565b9460200190565b929101610a11565b92916020610a696101ba93604087019087820360008901526109ed565b9401906001600160a01b03169052565b346101a857610a92610a8c3660046109d1565b906117dd565b906102a4610a9f60405190565b92839283610a4c565b346101a857610ab83660046103e2565b6102a46108066119d2565b91906040838203126101a857610193906020610adf82866101ad565b94016101ad565b346101a8576104fc610af9366004610ac3565b90611ae4565b906080828203126101a857610b1481836101ad565b92610b2282602085016101c2565b9261033783604083016101ad565b346101a8576104fc610b43366004610aff565b93929092611b76565b91909160a0818403126101a857610b6383826101ad565b92610b7181602084016101ad565b92610b7f82604085016101c2565b92610b8d83606083016101c2565b92608082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a4610375610bc2366004610b4c565b94939093929192611c23565b90610bdb6105be83610581565b918252565b610bea6005610bce565b7f312e302e30000000000000000000000000000000000000000000000000000000602082015290565b610193610be0565b610193610c13565b610193610c1b565b346101a857610c3b3660046103e2565b6102a4610725610c23565b630271189760e51b6001600160e01b0319821614908115610c84575b8115610c6c575090565b6301ffc9a760e01b91506001600160e01b0319161490565b6001600160e01b03198116630a85bd0160e11b149150610c62565b610cb2610cac6101939290565b60e01b90565b6001600160e01b03191690565b5050505050610ccc600090565b5061019363150b7a02610c9f565b6101939081565b6101939054610cda565b61019390610187565b6101939054610ceb565b610d1e9290610d0d6003610ce1565b91610d186002610cf4565b93611c7b565b15610d3057610193631626ba7e610c9f565b61019363ffffffff610c9f565b3561019381610196565b35610193816101bc565b65ffffffffffff81166101a1565b3561019381610d51565b67ffffffffffffffff81116105685760208091020190565b91909160a0818403126101a857610d9860a061056d565b92610da381836101ad565b8452610db281602084016101c2565b6020850152604082013567ffffffffffffffff81116101a85782610ddd83608093610dfa96016105dd565b6040870152610def8360608301610602565b6060870152016101c2565b6080830152565b929190610e106105be82610d69565b93818552602080860192028101918383116101a85781905b838210610e36575050505050565b813567ffffffffffffffff81116101a857602091610e578784938701610d81565b815201910190610e28565b610193913691610e01565b15610e7457565b60405162461bcd60e51b815260206004820152601560248201527f467573696f6e3a20696e76616c69642070726f6f6600000000000000000000006044820152606490fd5b15610ec057565b60405162461bcd60e51b815260206004820152601c60248201527f467573696f6e3a20696e73756666696369656e742062616c616e6365000000006044820152606490fd5b6101936101936101939265ffffffffffff1690565b15610f2157565b60405162461bcd60e51b815260206004820152601960248201527f467573696f6e3a20646561646c696e65206578636565646564000000000000006044820152606490fd5b9193909293610f73611ca9565b90466000840194610f8386610d3d565b96602086019489610f9387610d47565b99604089019a610fa28c610d47565b9160a08b0197610fb189610d5f565b94610fbc908b610e62565b95610fc696611cf6565b610fd06003610ce1565b90610fdb6002610cf4565b92610fe594611c7b565b610fee90610e6d565b610ff785610d3d565b61100360608601610d47565b61100c91611e45565b61101590610eb9565b61101e90610d5f565b61102790610f05565b42111561103390610f1a565b5a9561103e91610e62565b61104790612030565b61105090610d47565b9261105a90610d47565b9060800161106790610d3d565b9161107190610d3d565b926101ba94612132565b6101876101936101939290565b6101939061107b565b6101936001611088565b610187610193610193926001600160a01b031690565b6101939061109b565b610193906110b1565b906110cd906110ba565b600052602052604060002090565b6110e3611091565b6110fe6001600160a01b0383165b916001600160a01b031690565b1415908161110a575090565b61111f915061111a9060016110c3565b610cf4565b61112f6110f16101876000611088565b141590565b1561113b57565b60405162461bcd60e51b815260206004820152601b60248201527f467573696f6e3a20554e415554484f52495a45445f4d4f44554c4500000000006044820152606490fd5b91610193939161118e600090565b506111b76111a061111a3360016110c3565b6111b06110f16101876000611088565b1415611134565b5a936122f4565b6101936101936101939290565b634e487b7160e01b600052601160045260246000fd5b818102929181159184041417156111f457565b6111cb565b369037565b906101ba61121461120e84610bce565b93610581565b601f1901602084016111f9565b9160209061124061123b61123560206111be565b856111e1565b6111fe565b9061124b60006111be565b848110156112675780860154848202858501015260010161124b565b50935091505090565b610193903690610d81565b903590601e1936829003018212156101a8570180359067ffffffffffffffff82116101a857602001913682900383136101a857565b634e487b7160e01b600052602160045260246000fd5b600211156112d057565b6112b0565b906101ba826112c6565b35610193816105f8565b6101939136916105ae565b156112fb57565b60405162461bcd60e51b815260206004820152601860248201527f467573696f6e3a20657865637574696f6e206661696c656400000000000000006044820152606490fd5b90919261134b611ca9565b46600083019361135a85610d3d565b9560208501938861136a86610d47565b9860408801996113798b610d47565b9160a08a019761138889610d5f565b9461139290611270565b9561139c9661235c565b6113a66003610ce1565b906113b16002610cf4565b926113bb94611c7b565b6113c490610e6d565b6113cd84610d3d565b6113d960608501610d47565b6113e291611e45565b6113eb90610eb9565b6113f490610d5f565b6113fd90610f05565b42111561140990610f1a565b5a9461141481610d3d565b9061142160208201610d47565b9061142f604082018261127b565b929061143d606084016112df565b9260800161144a90610d47565b93611454916112e9565b9061145e946122f4565b611047906112f4565b6101ba90611473612376565b6114a8565b906001600160a01b03905b9181191691161790565b9061149d6101936114a4926110ba565b8254611478565b9055565b6114b26000611088565b6001600160a01b0381166001600160a01b0383161480156115e3575b61159e576001906114f56110f16114e861111a86866110c3565b926001600160a01b031690565b0361155957816104337fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f84409361154a6115549461152f611091565b9061154f61154061111a84846110c3565b61154a86846110c3565b61148d565b6110c3565b0390a1565b60405162461bcd60e51b815260206004820152601560248201527f467573696f6e3a204d4f44554c455f45584953545300000000000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601e60248201527f467573696f6e3a20494e56414c49445f4d4f44554c455f4144445245535300006044820152606490fd5b506115ef610187611091565b6001600160a01b038316146114ce565b6101ba90611467565b6000918291602082519201905af46000523d6020523d600060403e60403d016000fd5b505050505050505061163b600090565b5061019363bc197c81610c9f565b6116566101936101939290565b65ffffffffffff1690565b916116bd6116b86116c2946101ba96946116ae61167c611ca9565b6116a860004661168b82611088565b906116968c8c610e62565b946116a0846111be565b948594611649565b95611cf6565b610d0d6003610ce1565b610e6d565b610e62565b612030565b91611729611763926117226116b8610193966116e1600090565b506116ea611ca9565b936116ae46956000966116fc88611088565b916117068b611270565b926117108a6111be565b92839261171c8c611649565b9561235c565b8201610d3d565b61173560208301610d47565b611742604084018461127b565b61175d6080611756606088999599016112df565b9601610d47565b956112e9565b916122f4565b90610bdb6105be83610d69565b906101ba61121461178684611769565b93610d69565b634e487b7160e01b600052603260045260246000fd5b906117ab825190565b8110156117bc576020809102010190565b61178c565b60001981146111f45760010190565b919082039182116111f457565b90916117e7611091565b6001600160a01b0381166001600160a01b0384161415806119bc575b6119775760009061181460006111be565b85146119325761111a9361182786611776565b91829661183460006111be565b946118436001988995866110c3565b975b61189a575b50506001600160a01b03166001600160a01b03861603611868575052565b61189691945061188361187d611889926111be565b846117d0565b856117a2565b516001600160a01b031690565b9252565b90919294966118ab61018783611088565b6001600160a01b038216141580611916575b8061190d575b1561190457906118fe6118f861111a846118f28a9897966118e48e8c6117a2565b906001600160a01b03169052565b876110c3565b986117c1565b95611845565b9694929161184a565b508288106118c3565b506001600160a01b0384166001600160a01b03821614156118bd565b60405162461bcd60e51b815260206004820152601960248201527f467573696f6e3a20494e56414c49445f504147455f53495a45000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601c60248201527f467573696f6e3a20494e56414c49445f53544152545f4d4f44554c45000000006044820152606490fd5b506119cd6119c9846110db565b1590565b611803565b6101936004610ce1565b906101ba916119e9612376565b6119f36000611088565b916001600160a01b0383166001600160a01b038216148015611ac8575b61159e57600191611a2461111a82856110c3565b611a366001600160a01b0384166110f1565b03611a83577faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace40542769361154a838561154f6104339561154a611a7c61111a866115549c6110c3565b91846110c3565b60405162461bcd60e51b815260206004820152601660248201527f467573696f6e3a20494e56414c49445f4d4f44554c45000000000000000000006044820152606490fd5b50611ad4610187611091565b6001600160a01b03821614611a10565b906101ba916119dc565b15611af557565b60405162461bcd60e51b815260206004820152601b60248201527f467573696f6e3a20616c726561647920696e697469616c697a656400000000006044820152606490fd5b9060001990611483565b90611b526101936114a49290565b8254611b3a565b6001600160a01b0390911681526040810192916101ba9160200152565b91611c087f6a1a2249c74c6602d92273c1b532a3b45cdc3e69299742bd0d941f1ec1575dc595611c0e9395611bc4611bae6002610cf4565b611bbe6110f16101876000611088565b14611aee565b611bed611bd16003610ce1565b611bbe611be9610193611be460006111be565b6111be565b9190565b611bf886600261148d565b611c03876003611b44565b6112e9565b906124b3565b611554611c1a60405190565b92839283611b59565b505050505050611c31600090565b5061019363f23a6e61610c9f565b611c48336110ba565b7f2bee3931a0bb0eccf837f383a9616f04ff50f842ab65661d06c3bc24f85e6410611c7260405190565b348152602090a2565b916101939493611c9391611c8d600090565b50612548565b91612675565b90611b526101936114a4926111be565b611cb36004610ce1565b610193600182016004611c99565b61059e611cd992602092611cd3815190565b94859290565b938491016106a1565b611cf0906101939392611cc1565b90611cc1565b959493929190606096611d0960006111be565b975b611d16610193835190565b891015611d7257611d59611d65611d6c92611d418b8b8b8f8b8b611d3b8f938d6117a2565b5161277d565b90611d4b60405190565b938492602084019283611ce2565b90810382520382610546565b9860010190565b97611d0b565b975050505050505050611d8d611d86825190565b9160200190565b2090565b60ff81166101a1565b905051906101ba82611d91565b906020828203126101a85761019391611d9a565b6040513d6000823e3d90fd5b905051906101ba826101bc565b906020828203126101a85761019391611dc7565b611df56101936101939290565b60ff1690565b60ff908116911690039060ff82116111f457565b60ff16604d81116111f457600a0a90565b634e487b7160e01b600052601260045260246000fd5b8115611e40570490565b611e20565b90611e536101876000611088565b6001600160a01b03831614611fc457611e73611e6e836110ba565b6110ba565b916020611e7f60405190565b63313ce56760e01b815293849060049082905afa908115611f8557611ef093600092611f8a575b50611eb5611e6e6020926110ba565b611ebe306110ba565b90611ec860405190565b958692839182916370a0823160e01b8352600483016001600160a01b03909116815260200190565b03915afa928315611f8557600093611f3e575b50610193611f2f92611f29611f24611be994611f1f6012611de8565b611dfb565b611e0f565b90611e36565b10611f3957600190565b600090565b611be9919350611f2f92611f29611f24611f726101939460203d602011611f7e575b611f6a8183610546565b810190611dd4565b96945050509250611f03565b503d611f60565b611dbb565b6020919250611e6e611fb4611eb592843d8611611fbd575b611fac8183610546565b810190611da7565b93925050611ea6565b503d611fa2565b9050611f2f611be9611fd5306110ba565b319290565b61019390516112d5565b15611feb57565b60405162461bcd60e51b815260206004820152601e60248201527f467573696f6e3a20626174636820657865637574696f6e206661696c656400006044820152606490fd5b90600061203d60006111be565b612048610193855190565b8110156120d757806120cc6120c7612076856120676120d2968a6117a2565b5101516001600160a01b031690565b8761208c602061208687846117a2565b51015190565b604061209887846117a2565b510151906120c16080612086896120bb60606120b4838a6117a2565b5101611fda565b966117a2565b936122f4565b611fe4565b60010190565b61203d565b50509050565b919082018092116111f457565b3d15612104576120f93d610bce565b903d6000602084013e565b606090565b8015156101a1565b905051906101ba82612109565b906020828203126101a85761019391612111565b61214e92612144612149925a906117d0565b6120dd565b6111e1565b9060009161215e61018784611088565b6001600160a01b038516146122cf57612179611e6e856110ba565b91602061218560405190565b63313ce56760e01b815293849060049082905afa948515611f85576121fd6121c8869594611f29611f2461221d9a89986000916122b0575b50611f1f6012611de8565b926121ee6121d560405190565b63a9059cbb60e01b602082015294859260248401611b59565b60208201810382520383610546565b82602083519301915af1906122106120ea565b9082612268575b50501590565b61222357565b60405162461bcd60e51b815260206004820152601b60248201527f467573696f6e3a20666565207472616e73666572206661696c656400000000006044820152606490fd5b90915061227f611be9612279845190565b926111be565b14908115612290575b503880612217565b6122aa9150602061229f825190565b81830101910161211e565b38612288565b6122c9915060203d602011611fbd57611fac8183610546565b386121bd565b61221d93509082916122e060405190565b90818003925af16122ef6120ea565b501590565b9394936000938493929061231161230b60016112d5565b916112d5565b14841461234257506020825192019086f491612339611be96101935a935b611f29603f6111be565b1061234057565bfe5b6020835193019187f191612339611be96101935a9361232f565b61236b9695949392919061277d565b611d8d611d86825190565b612382610187306110ba565b330361238a57565b60405162461bcd60e51b815260206004820152601560248201527f4f4e4c595f43414c4c41424c455f42595f53454c4600000000000000000000006044820152606490fd5b156123d657565b60405162461bcd60e51b815260206004820152601b60248201527f4d6f64756c657320616c726561647920696e697469616c697a656400000000006044820152606490fd5b1561242257565b60405162461bcd60e51b815260206004820152600e60248201527f496e76616c6964204d6f64756c650000000000000000000000000000000000006044820152606490fd5b1561246e57565b60405162461bcd60e51b815260206004820152601360248201527f4d6f64756c65207365747570206661696c6564000000000000000000000000006044820152606490fd5b906001916125036124c2611091565b6101876124d261111a83886110c3565b916124f96124e06000611088565b936124f36001600160a01b0386166110f1565b146123cf565b61154a81886110c3565b6001600160a01b0382160361251757505050565b6101ba926125439261253061252b846127e6565b61241b565b61253a60006111be565b600019936122f4565b612467565b919061256561255f61255a60216111be565b611776565b9361282b565b9061257060006111be565b602061257b816111be565b8210156125d2578110156117bc576125cd906120cc6125c07fff0000000000000000000000000000000000000000000000000000000000000086841a60f81b16612869565b6125ca83896117a2565b52565b612570565b505061019391509291926125ca6125e960206111be565b846117a2565b91906106ee816126068161059e9560209181520190565b80956105a2565b9061261c610a066109fc845190565b9060005b81811061262d5750505090565b909192612643610a3d6001928651815260200190565b929101612620565b91610193939161266791604085019185830360008701526125ef565b91602081840391015261260d565b60209291612691611e6e6126b59661268b600090565b506110ba565b9161269b60405190565b95869485938493633a94343960e21b85526004850161264b565b03915afa908115611f85576000916126cb575090565b610193915060203d6020116126ed575b6126e58183610546565b81019061211e565b503d6126db565b610193906112d5565b98969492919b9a999795939b6101608a019160008b01612724916001600160a01b03169052565b60208a015288810360408a015261273a916106c4565b60ff9a909a166060880152608087015260a08601526001600160a01b031660c085015260e084015261010083015265ffffffffffff166101208201526101400152565b909561019395611d599395612790606090565b5083516001600160a01b0316956127a8602086015190565b9760408601519a6127ce60806127c86127c360608b01611fda565b6126f4565b98015190565b966127d860405190565b9c8d9b60208d019b8c6126fd565b3b6127f4611be960006111be565b1190565b9061059e610bdb6020937f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0190565b61236b61283760405190565b8092611d596020830191826127f8565b610193906111be565b61019390612864611be96101939460ff1690565b901c90565b611be46128816101939261287b600090565b50612847565b61288b60f8611de8565b9061285056fea2646970667358221220c253f285f65c7e3ee8518f5424e7d87ea9dcc6824c3df2e2eb62034e0d16d0ed64736f6c63430008180033
Deployed Bytecode
0x60806040526004361015610023575b361561001957600080fd5b610021611c3f565b005b60003560e01c806223de291461018257806301ffc9a71461017d578063150b7a02146101785780631626ba7e146101735780631692d4ef1461016e5780631db6f9b6146101695780632d9ad53d14610164578063468721a71461015f5780635624b25b1461015a5780635691126814610155578063610b592514610150578063aef8c46e1461014b578063b4faba0914610146578063bc197c8114610141578063be91404f1461013c578063c2ded10b14610137578063cc2f845214610132578063d087d2881461012d578063e009cfde14610128578063e4d52aa714610123578063f23a6e611461011e5763ffa1ad740361000e57610c2b565b610bac565b610b30565b610ae6565b610aa8565b610a79565b6109ba565b610959565b6108ea565b61084c565b6107eb565b6107b1565b61079a565b610709565b61065f565b610515565b6104e5565b610418565b6103c6565b610356565b6102d9565b610283565b6001600160a01b031690565b90565b6001600160a01b0381165b036101a857565b600080fd5b905035906101ba82610196565b565b806101a1565b905035906101ba826101bc565b909182601f830112156101a85781359167ffffffffffffffff83116101a85760200192600183028401116101a857565b60c0818303126101a85761021382826101ad565b9261022183602084016101ad565b9261022f81604085016101ad565b9261023d82606083016101c2565b92608082013567ffffffffffffffff81116101a8578361025e9184016101cf565b92909360a082013567ffffffffffffffff81116101a85761027f92016101cf565b9091565b346101a8576102933660046101ff565b505050505050505061002160405190565b0390f35b6001600160e01b031981166101a1565b905035906101ba826102a8565b906020828203126101a857610193916102b8565b346101a8576102a46102f46102ef3660046102c5565b610c46565b60405191829182901515815260200190565b906080828203126101a85761031b81836101ad565b9261032982602085016101ad565b9261033783604083016101c2565b92606082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a461037561036c366004610306565b93929092610cbf565b604051918291826001600160e01b0319909116815260200190565b9190916040818403126101a8576103a783826101c2565b92602082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a46103756103dc366004610390565b91610cfe565b60009103126101a857565b610193916008021c6001600160a01b031690565b9061019391546103ed565b61019360006002610401565b346101a8576104283660046103e2565b6102a461043361040c565b604051918291826001600160a01b03909116815260200190565b909182601f830112156101a85781359167ffffffffffffffff83116101a85760200192602083028401116101a857565b908160c09103126101a85790565b610100818303126101a857803567ffffffffffffffff81116101a857826104b39183016101cf565b929093602083013567ffffffffffffffff81116101a857826104dc60409461019393870161044d565b9490950161047d565b6104fc6104f336600461048b565b93929092610f66565b604051005b906020828203126101a857610193916101ad565b346101a8576102a46102f461052b366004610501565b6110db565b634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff82111761056857604052565b610530565b906101ba61057a60405190565b9283610546565b67ffffffffffffffff811161056857602090601f01601f19160190565b0190565b90826000939282370152565b909291926105c36105be82610581565b61056d565b93818552818301116101a8576101ba9160208501906105a2565b9080601f830112156101a857816020610193933591016105ae565b600211156101a857565b905035906101ba826105f8565b6080818303126101a85761062382826101ad565b9261063183602084016101c2565b9260408301359067ffffffffffffffff82116101a8576060610658826101939487016105dd565b9401610602565b346101a8576102a46102f461067536600461060f565b92919091611180565b91906040838203126101a85761019390602061069a82866101c2565b94016101c2565b60005b8381106106b45750506000910152565b81810151838201526020016106a4565b6106e56106ee60209361059e936106d9815190565b80835293849260200190565b958691016106a1565b601f01601f191690565b6020808252610193929101906106c4565b346101a8576102a461072561071f36600461067e565b90611221565b604051918291826106f8565b908160a09103126101a85790565b919091610100818403126101a857803567ffffffffffffffff81116101a8578361076a9183016101cf565b92909360208301359067ffffffffffffffff82116101a857604061079382610193948701610731565b940161047d565b6104fc6107a836600461073f565b92919091611340565b346101a8576104fc6107c4366004610501565b6115ff565b610193916008021c81565b9061019391546107c9565b610193600060036107d4565b346101a8576107fb3660046103e2565b6102a46108066107df565b6040519182918290815260200190565b9190916040818403126101a85761082d83826101ad565b92602082013567ffffffffffffffff81116101a85761019392016105dd565b346101a85761085c366004610816565b90611608565b9160a0838303126101a85761087782846101ad565b9261088583602083016101ad565b92604082013567ffffffffffffffff81116101a857816108a691840161044d565b929093606082013567ffffffffffffffff81116101a857836108c991840161044d565b929093608082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a4610375610900366004610862565b9695909594919493929361162b565b90916040828403126101a857813567ffffffffffffffff81116101a857836109389184016101cf565b929093602082013567ffffffffffffffff81116101a85761027f920161044d565b6104fc61096736600461090f565b92919091611661565b90916040828403126101a857813567ffffffffffffffff81116101a857836109999184016101cf565b929093602082013567ffffffffffffffff81116101a8576101939201610731565b6102a46102f46109cb366004610970565b916116c7565b91906040838203126101a85761019390602061069a82866101ad565b90610a0d610a066109fc845190565b8084529260200190565b9260200190565b9060005b818110610a1e5750505090565b909192610a44610a3d60019286516001600160a01b0316815260200190565b9460200190565b929101610a11565b92916020610a696101ba93604087019087820360008901526109ed565b9401906001600160a01b03169052565b346101a857610a92610a8c3660046109d1565b906117dd565b906102a4610a9f60405190565b92839283610a4c565b346101a857610ab83660046103e2565b6102a46108066119d2565b91906040838203126101a857610193906020610adf82866101ad565b94016101ad565b346101a8576104fc610af9366004610ac3565b90611ae4565b906080828203126101a857610b1481836101ad565b92610b2282602085016101c2565b9261033783604083016101ad565b346101a8576104fc610b43366004610aff565b93929092611b76565b91909160a0818403126101a857610b6383826101ad565b92610b7181602084016101ad565b92610b7f82604085016101c2565b92610b8d83606083016101c2565b92608082013567ffffffffffffffff81116101a85761027f92016101cf565b346101a8576102a4610375610bc2366004610b4c565b94939093929192611c23565b90610bdb6105be83610581565b918252565b610bea6005610bce565b7f312e302e30000000000000000000000000000000000000000000000000000000602082015290565b610193610be0565b610193610c13565b610193610c1b565b346101a857610c3b3660046103e2565b6102a4610725610c23565b630271189760e51b6001600160e01b0319821614908115610c84575b8115610c6c575090565b6301ffc9a760e01b91506001600160e01b0319161490565b6001600160e01b03198116630a85bd0160e11b149150610c62565b610cb2610cac6101939290565b60e01b90565b6001600160e01b03191690565b5050505050610ccc600090565b5061019363150b7a02610c9f565b6101939081565b6101939054610cda565b61019390610187565b6101939054610ceb565b610d1e9290610d0d6003610ce1565b91610d186002610cf4565b93611c7b565b15610d3057610193631626ba7e610c9f565b61019363ffffffff610c9f565b3561019381610196565b35610193816101bc565b65ffffffffffff81166101a1565b3561019381610d51565b67ffffffffffffffff81116105685760208091020190565b91909160a0818403126101a857610d9860a061056d565b92610da381836101ad565b8452610db281602084016101c2565b6020850152604082013567ffffffffffffffff81116101a85782610ddd83608093610dfa96016105dd565b6040870152610def8360608301610602565b6060870152016101c2565b6080830152565b929190610e106105be82610d69565b93818552602080860192028101918383116101a85781905b838210610e36575050505050565b813567ffffffffffffffff81116101a857602091610e578784938701610d81565b815201910190610e28565b610193913691610e01565b15610e7457565b60405162461bcd60e51b815260206004820152601560248201527f467573696f6e3a20696e76616c69642070726f6f6600000000000000000000006044820152606490fd5b15610ec057565b60405162461bcd60e51b815260206004820152601c60248201527f467573696f6e3a20696e73756666696369656e742062616c616e6365000000006044820152606490fd5b6101936101936101939265ffffffffffff1690565b15610f2157565b60405162461bcd60e51b815260206004820152601960248201527f467573696f6e3a20646561646c696e65206578636565646564000000000000006044820152606490fd5b9193909293610f73611ca9565b90466000840194610f8386610d3d565b96602086019489610f9387610d47565b99604089019a610fa28c610d47565b9160a08b0197610fb189610d5f565b94610fbc908b610e62565b95610fc696611cf6565b610fd06003610ce1565b90610fdb6002610cf4565b92610fe594611c7b565b610fee90610e6d565b610ff785610d3d565b61100360608601610d47565b61100c91611e45565b61101590610eb9565b61101e90610d5f565b61102790610f05565b42111561103390610f1a565b5a9561103e91610e62565b61104790612030565b61105090610d47565b9261105a90610d47565b9060800161106790610d3d565b9161107190610d3d565b926101ba94612132565b6101876101936101939290565b6101939061107b565b6101936001611088565b610187610193610193926001600160a01b031690565b6101939061109b565b610193906110b1565b906110cd906110ba565b600052602052604060002090565b6110e3611091565b6110fe6001600160a01b0383165b916001600160a01b031690565b1415908161110a575090565b61111f915061111a9060016110c3565b610cf4565b61112f6110f16101876000611088565b141590565b1561113b57565b60405162461bcd60e51b815260206004820152601b60248201527f467573696f6e3a20554e415554484f52495a45445f4d4f44554c4500000000006044820152606490fd5b91610193939161118e600090565b506111b76111a061111a3360016110c3565b6111b06110f16101876000611088565b1415611134565b5a936122f4565b6101936101936101939290565b634e487b7160e01b600052601160045260246000fd5b818102929181159184041417156111f457565b6111cb565b369037565b906101ba61121461120e84610bce565b93610581565b601f1901602084016111f9565b9160209061124061123b61123560206111be565b856111e1565b6111fe565b9061124b60006111be565b848110156112675780860154848202858501015260010161124b565b50935091505090565b610193903690610d81565b903590601e1936829003018212156101a8570180359067ffffffffffffffff82116101a857602001913682900383136101a857565b634e487b7160e01b600052602160045260246000fd5b600211156112d057565b6112b0565b906101ba826112c6565b35610193816105f8565b6101939136916105ae565b156112fb57565b60405162461bcd60e51b815260206004820152601860248201527f467573696f6e3a20657865637574696f6e206661696c656400000000000000006044820152606490fd5b90919261134b611ca9565b46600083019361135a85610d3d565b9560208501938861136a86610d47565b9860408801996113798b610d47565b9160a08a019761138889610d5f565b9461139290611270565b9561139c9661235c565b6113a66003610ce1565b906113b16002610cf4565b926113bb94611c7b565b6113c490610e6d565b6113cd84610d3d565b6113d960608501610d47565b6113e291611e45565b6113eb90610eb9565b6113f490610d5f565b6113fd90610f05565b42111561140990610f1a565b5a9461141481610d3d565b9061142160208201610d47565b9061142f604082018261127b565b929061143d606084016112df565b9260800161144a90610d47565b93611454916112e9565b9061145e946122f4565b611047906112f4565b6101ba90611473612376565b6114a8565b906001600160a01b03905b9181191691161790565b9061149d6101936114a4926110ba565b8254611478565b9055565b6114b26000611088565b6001600160a01b0381166001600160a01b0383161480156115e3575b61159e576001906114f56110f16114e861111a86866110c3565b926001600160a01b031690565b0361155957816104337fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f84409361154a6115549461152f611091565b9061154f61154061111a84846110c3565b61154a86846110c3565b61148d565b6110c3565b0390a1565b60405162461bcd60e51b815260206004820152601560248201527f467573696f6e3a204d4f44554c455f45584953545300000000000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601e60248201527f467573696f6e3a20494e56414c49445f4d4f44554c455f4144445245535300006044820152606490fd5b506115ef610187611091565b6001600160a01b038316146114ce565b6101ba90611467565b6000918291602082519201905af46000523d6020523d600060403e60403d016000fd5b505050505050505061163b600090565b5061019363bc197c81610c9f565b6116566101936101939290565b65ffffffffffff1690565b916116bd6116b86116c2946101ba96946116ae61167c611ca9565b6116a860004661168b82611088565b906116968c8c610e62565b946116a0846111be565b948594611649565b95611cf6565b610d0d6003610ce1565b610e6d565b610e62565b612030565b91611729611763926117226116b8610193966116e1600090565b506116ea611ca9565b936116ae46956000966116fc88611088565b916117068b611270565b926117108a6111be565b92839261171c8c611649565b9561235c565b8201610d3d565b61173560208301610d47565b611742604084018461127b565b61175d6080611756606088999599016112df565b9601610d47565b956112e9565b916122f4565b90610bdb6105be83610d69565b906101ba61121461178684611769565b93610d69565b634e487b7160e01b600052603260045260246000fd5b906117ab825190565b8110156117bc576020809102010190565b61178c565b60001981146111f45760010190565b919082039182116111f457565b90916117e7611091565b6001600160a01b0381166001600160a01b0384161415806119bc575b6119775760009061181460006111be565b85146119325761111a9361182786611776565b91829661183460006111be565b946118436001988995866110c3565b975b61189a575b50506001600160a01b03166001600160a01b03861603611868575052565b61189691945061188361187d611889926111be565b846117d0565b856117a2565b516001600160a01b031690565b9252565b90919294966118ab61018783611088565b6001600160a01b038216141580611916575b8061190d575b1561190457906118fe6118f861111a846118f28a9897966118e48e8c6117a2565b906001600160a01b03169052565b876110c3565b986117c1565b95611845565b9694929161184a565b508288106118c3565b506001600160a01b0384166001600160a01b03821614156118bd565b60405162461bcd60e51b815260206004820152601960248201527f467573696f6e3a20494e56414c49445f504147455f53495a45000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601c60248201527f467573696f6e3a20494e56414c49445f53544152545f4d4f44554c45000000006044820152606490fd5b506119cd6119c9846110db565b1590565b611803565b6101936004610ce1565b906101ba916119e9612376565b6119f36000611088565b916001600160a01b0383166001600160a01b038216148015611ac8575b61159e57600191611a2461111a82856110c3565b611a366001600160a01b0384166110f1565b03611a83577faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace40542769361154a838561154f6104339561154a611a7c61111a866115549c6110c3565b91846110c3565b60405162461bcd60e51b815260206004820152601660248201527f467573696f6e3a20494e56414c49445f4d4f44554c45000000000000000000006044820152606490fd5b50611ad4610187611091565b6001600160a01b03821614611a10565b906101ba916119dc565b15611af557565b60405162461bcd60e51b815260206004820152601b60248201527f467573696f6e3a20616c726561647920696e697469616c697a656400000000006044820152606490fd5b9060001990611483565b90611b526101936114a49290565b8254611b3a565b6001600160a01b0390911681526040810192916101ba9160200152565b91611c087f6a1a2249c74c6602d92273c1b532a3b45cdc3e69299742bd0d941f1ec1575dc595611c0e9395611bc4611bae6002610cf4565b611bbe6110f16101876000611088565b14611aee565b611bed611bd16003610ce1565b611bbe611be9610193611be460006111be565b6111be565b9190565b611bf886600261148d565b611c03876003611b44565b6112e9565b906124b3565b611554611c1a60405190565b92839283611b59565b505050505050611c31600090565b5061019363f23a6e61610c9f565b611c48336110ba565b7f2bee3931a0bb0eccf837f383a9616f04ff50f842ab65661d06c3bc24f85e6410611c7260405190565b348152602090a2565b916101939493611c9391611c8d600090565b50612548565b91612675565b90611b526101936114a4926111be565b611cb36004610ce1565b610193600182016004611c99565b61059e611cd992602092611cd3815190565b94859290565b938491016106a1565b611cf0906101939392611cc1565b90611cc1565b959493929190606096611d0960006111be565b975b611d16610193835190565b891015611d7257611d59611d65611d6c92611d418b8b8b8f8b8b611d3b8f938d6117a2565b5161277d565b90611d4b60405190565b938492602084019283611ce2565b90810382520382610546565b9860010190565b97611d0b565b975050505050505050611d8d611d86825190565b9160200190565b2090565b60ff81166101a1565b905051906101ba82611d91565b906020828203126101a85761019391611d9a565b6040513d6000823e3d90fd5b905051906101ba826101bc565b906020828203126101a85761019391611dc7565b611df56101936101939290565b60ff1690565b60ff908116911690039060ff82116111f457565b60ff16604d81116111f457600a0a90565b634e487b7160e01b600052601260045260246000fd5b8115611e40570490565b611e20565b90611e536101876000611088565b6001600160a01b03831614611fc457611e73611e6e836110ba565b6110ba565b916020611e7f60405190565b63313ce56760e01b815293849060049082905afa908115611f8557611ef093600092611f8a575b50611eb5611e6e6020926110ba565b611ebe306110ba565b90611ec860405190565b958692839182916370a0823160e01b8352600483016001600160a01b03909116815260200190565b03915afa928315611f8557600093611f3e575b50610193611f2f92611f29611f24611be994611f1f6012611de8565b611dfb565b611e0f565b90611e36565b10611f3957600190565b600090565b611be9919350611f2f92611f29611f24611f726101939460203d602011611f7e575b611f6a8183610546565b810190611dd4565b96945050509250611f03565b503d611f60565b611dbb565b6020919250611e6e611fb4611eb592843d8611611fbd575b611fac8183610546565b810190611da7565b93925050611ea6565b503d611fa2565b9050611f2f611be9611fd5306110ba565b319290565b61019390516112d5565b15611feb57565b60405162461bcd60e51b815260206004820152601e60248201527f467573696f6e3a20626174636820657865637574696f6e206661696c656400006044820152606490fd5b90600061203d60006111be565b612048610193855190565b8110156120d757806120cc6120c7612076856120676120d2968a6117a2565b5101516001600160a01b031690565b8761208c602061208687846117a2565b51015190565b604061209887846117a2565b510151906120c16080612086896120bb60606120b4838a6117a2565b5101611fda565b966117a2565b936122f4565b611fe4565b60010190565b61203d565b50509050565b919082018092116111f457565b3d15612104576120f93d610bce565b903d6000602084013e565b606090565b8015156101a1565b905051906101ba82612109565b906020828203126101a85761019391612111565b61214e92612144612149925a906117d0565b6120dd565b6111e1565b9060009161215e61018784611088565b6001600160a01b038516146122cf57612179611e6e856110ba565b91602061218560405190565b63313ce56760e01b815293849060049082905afa948515611f85576121fd6121c8869594611f29611f2461221d9a89986000916122b0575b50611f1f6012611de8565b926121ee6121d560405190565b63a9059cbb60e01b602082015294859260248401611b59565b60208201810382520383610546565b82602083519301915af1906122106120ea565b9082612268575b50501590565b61222357565b60405162461bcd60e51b815260206004820152601b60248201527f467573696f6e3a20666565207472616e73666572206661696c656400000000006044820152606490fd5b90915061227f611be9612279845190565b926111be565b14908115612290575b503880612217565b6122aa9150602061229f825190565b81830101910161211e565b38612288565b6122c9915060203d602011611fbd57611fac8183610546565b386121bd565b61221d93509082916122e060405190565b90818003925af16122ef6120ea565b501590565b9394936000938493929061231161230b60016112d5565b916112d5565b14841461234257506020825192019086f491612339611be96101935a935b611f29603f6111be565b1061234057565bfe5b6020835193019187f191612339611be96101935a9361232f565b61236b9695949392919061277d565b611d8d611d86825190565b612382610187306110ba565b330361238a57565b60405162461bcd60e51b815260206004820152601560248201527f4f4e4c595f43414c4c41424c455f42595f53454c4600000000000000000000006044820152606490fd5b156123d657565b60405162461bcd60e51b815260206004820152601b60248201527f4d6f64756c657320616c726561647920696e697469616c697a656400000000006044820152606490fd5b1561242257565b60405162461bcd60e51b815260206004820152600e60248201527f496e76616c6964204d6f64756c650000000000000000000000000000000000006044820152606490fd5b1561246e57565b60405162461bcd60e51b815260206004820152601360248201527f4d6f64756c65207365747570206661696c6564000000000000000000000000006044820152606490fd5b906001916125036124c2611091565b6101876124d261111a83886110c3565b916124f96124e06000611088565b936124f36001600160a01b0386166110f1565b146123cf565b61154a81886110c3565b6001600160a01b0382160361251757505050565b6101ba926125439261253061252b846127e6565b61241b565b61253a60006111be565b600019936122f4565b612467565b919061256561255f61255a60216111be565b611776565b9361282b565b9061257060006111be565b602061257b816111be565b8210156125d2578110156117bc576125cd906120cc6125c07fff0000000000000000000000000000000000000000000000000000000000000086841a60f81b16612869565b6125ca83896117a2565b52565b612570565b505061019391509291926125ca6125e960206111be565b846117a2565b91906106ee816126068161059e9560209181520190565b80956105a2565b9061261c610a066109fc845190565b9060005b81811061262d5750505090565b909192612643610a3d6001928651815260200190565b929101612620565b91610193939161266791604085019185830360008701526125ef565b91602081840391015261260d565b60209291612691611e6e6126b59661268b600090565b506110ba565b9161269b60405190565b95869485938493633a94343960e21b85526004850161264b565b03915afa908115611f85576000916126cb575090565b610193915060203d6020116126ed575b6126e58183610546565b81019061211e565b503d6126db565b610193906112d5565b98969492919b9a999795939b6101608a019160008b01612724916001600160a01b03169052565b60208a015288810360408a015261273a916106c4565b60ff9a909a166060880152608087015260a08601526001600160a01b031660c085015260e084015261010083015265ffffffffffff166101208201526101400152565b909561019395611d599395612790606090565b5083516001600160a01b0316956127a8602086015190565b9760408601519a6127ce60806127c86127c360608b01611fda565b6126f4565b98015190565b966127d860405190565b9c8d9b60208d019b8c6126fd565b3b6127f4611be960006111be565b1190565b9061059e610bdb6020937f19457468657265756d205369676e6564204d6573736167653a0a3332000000008152601c0190565b61236b61283760405190565b8092611d596020830191826127f8565b610193906111be565b61019390612864611be96101939460ff1690565b901c90565b611be46128816101939261287b600090565b50612847565b61288b60f8611de8565b9061285056fea2646970667358221220c253f285f65c7e3ee8518f5424e7d87ea9dcc6824c3df2e2eb62034e0d16d0ed64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Token Allocations
FRAX
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| FRAXTAL | 100.00% | $0.969839 | 0.000000001676 | <$0.000001 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.