Feature Tip: Add private address tag to any address under My Name Tag !
This address is tagged based on Wintermute's post.
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
There are no matching entriesUpdate your filters to view other transactions | |||||||||
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x958260e1...fECc9025e The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Biz
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 999999 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.28;
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {BizGuard} from "./BizGuard.sol";
import {BizHandler} from "./BizHandler.sol";
/**
* @title Biz - A secure smart wallet for delegated EOAs using EIP-7702.
* @dev Most important concepts:
* - Biz is a stateless account implementation. Only relies on BizGuard for 4337 Flag & Nonce.
* - Biz allows 3 distinct validation & execution flows.
* - ERC-4337.
* - Self-Call.
* - Signature based. msg.sender Agnostic.
* - ERC-4337 support is optional and it is controlled by BizGuard for extra layer of security.
* - Biz supports ERC-7779.
* @author David Kim - @PowerStream3604
*/
contract Biz is BizHandler {
/// @dev The packed ERC4337 user operation (userOp) struct.
struct PackedUserOperation {
address sender;
uint256 nonce;
bytes initCode; // Factory address and `factoryData` (or empty).
bytes callData;
bytes32 accountGasLimits; // `verificationGas` (16 bytes) and `callGas` (16 bytes).
uint256 preVerificationGas;
bytes32 gasFees; // `maxPriorityFee` (16 bytes) and `maxFeePerGas` (16 bytes).
bytes paymasterAndData; // Paymaster fields (or empty).
bytes signature;
}
/// @dev Call struct for the `executeBatch` function.
struct Call {
address target;
uint256 value;
bytes data;
}
error OnlyEntryPoint();
error OnlySelf();
error InvalidSignature();
error ERC4337Disabled();
error InvalidERC4337Flag();
error ZeroAddressGuard();
error Invalid4337ExecutionSelector();
// keccak("Biz(bytes32 userOpHash)")
bytes32 private constant BIZ_USEROP_HASH = 0x4f51e7a567f083a31264743067875fc6a7ae45c32c5bd71f6a998c4625b13867;
// keccak("Biz(bytes32 msgHash)")
bytes32 private constant BIZ_MSG_HASH = 0x31322a37c2a66b24e1088197e5b24fcc050625c13d4b84c3eaa6a8be5270321d;
// keccak("Biz(bytes32 execHash)")
bytes32 private constant BIZ_EXEC_HASH = 0xec429430bbd6d0e373848272230d6fe2bac6319d903762e089c5cae97af53df0;
// keccak("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)")
bytes32 private constant BIZ_DOMAIN_SEPARATOR_HASH =
0xd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472;
// keccak("Biz(bool Flag4337)")
bytes32 private constant BIZ_4337_FLAG = 0xa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a4;
// keccak256("Biz")
bytes32 private constant BIZ_HASH = 0x906754a21e6afe7233c7ccce2787110e84157e1cbaa80e58656dff779193a5cd;
// keccak256("v1.0.0")
bytes32 private constant VERSION_HASH = 0x15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc;
uint256 private constant MAGIC_VALUE = 6789;
bytes4 internal constant ERC1271_SUCCESS = 0x1626ba7e;
bytes4 internal constant ERC1271_FAILURE = 0xffffffff;
BizGuard public immutable bizGuard;
bytes32 private immutable singletonSalt;
constructor(BizGuard _bizGuard) {
if (address(_bizGuard) == address(0)) revert ZeroAddressGuard();
bizGuard = _bizGuard;
singletonSalt = _addressToBytes32(address(this));
}
/// @dev Requires the caller to be EntryPoint.
modifier onlyEntryPoint() {
if (msg.sender != entryPoint()) revert OnlyEntryPoint();
_;
}
/// @dev Requires the caller to be Self.
modifier onlySelf() {
if (msg.sender != address(this)) revert OnlySelf();
_;
}
/// @dev Requires the BizGuard to enable ERC-4337.
modifier checkGuard() {
if (!bizGuard.is4337Enabled()) revert ERC4337Disabled();
_;
}
/**
* @notice Validates if the transient storage flag is set.
* @dev The transient storage tCounter is only set when the validateUserOp() is successful.
* For the validateUserOp() to be successful,
* - BizGuard should enable ERC-4337 flow
* - EntryPoint should be the msg.sender
* - Signature validation should pass
* tCounter is incremented per successful execution of validateUserOp()
* tCounter is decremented per successful execution of 4337 execution functions
* each ERC-4337 validation MUST be coupled with the execution functions. execute4337Op() or execute4337Ops().
*/
modifier check4337Flag() {
uint256 tCounter;
bool sFlagIsMagic;
assembly {
tCounter := tload(BIZ_4337_FLAG)
}
if (tCounter == 0) {
uint256 sFlag;
assembly {
sFlag := sload(BIZ_4337_FLAG)
}
if (sFlag != MAGIC_VALUE) revert InvalidERC4337Flag();
sFlagIsMagic = true;
}
_;
if (tCounter != 0) {
assembly {
tstore(BIZ_4337_FLAG, sub(tCounter, 1))
}
}
if (sFlagIsMagic) {
assembly {
sstore(BIZ_4337_FLAG, 0)
}
}
}
/**
* @notice Returns EntryPoint contract address.
* @return address of EntryPoint v0.7.0.
*/
function entryPoint() public view virtual returns (address) {
return 0x0000000071727De22E5E9d8BAf0edAc6f37da032;
}
/**
* @dev Provides the namespace of the account.
* @return string Biz namespace.
*/
function accountId() external pure override returns (string memory) {
return "TrustWallet.Biz.v1.0.0";
}
/**
* @notice Validates the UserOperation.
* @dev This function can only be called by the EntryPoint.
* It is a prerequisite to have BizGuard enable 4337 Flag.
* @param userOp PackedUserOperation to perform ERC-4337 validation & execution.
* @param userOpHash Bytes32 hash of UserOperation.
* @param missingAccountFunds Uint256 amount of funds to be sent to EntryPoint.
* @return validationData Uint256 validation result from the account.
*/
function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
external
onlyEntryPoint
checkGuard
returns (uint256 validationData)
{
bool isValid = _validateSignature(_getEncodedMsgHash(BIZ_USEROP_HASH, userOpHash), userOp.signature);
if (
bytes4(userOp.callData[:4]) != Biz.execute4337Op.selector
&& bytes4(userOp.callData[:4]) != Biz.execute4337Ops.selector
) revert Invalid4337ExecutionSelector();
if (isValid) {
_enable4337Flag();
validationData = 0;
} else {
validationData = 1;
}
assembly {
if missingAccountFunds { pop(call(gas(), caller(), missingAccountFunds, 0, 0, 0, 0)) }
}
}
/**
* @notice Validates if the signature is signed by Biz.
* @dev This function validates the signature if Biz indeed signed the given hash. It uses EIP-712.
* @param hash Bytes32 hash that is signed.
* @param signature Bytes signature to be validated.
* @return isValid Bytes4 indicating the success/failure of validation.
*/
function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 isValid) {
isValid =
_validateSignature(_getEncodedMsgHash(BIZ_MSG_HASH, hash), signature) ? ERC1271_SUCCESS : ERC1271_FAILURE;
}
/**
* @notice Executes the given data.
* @dev This function performs execution and should only be called by the owner EOA.
* @param target Address to perform execution.
* @param value Uint256 value of native coin.
* @param data Bytes calldata to execute.
*/
function execute(address target, uint256 value, bytes calldata data) external payable onlySelf {
_call(target, value, data);
}
/**
* @notice Batch executes the given data.
* @dev This function executes the array of Calls.
* @param calls Array of execution data
*/
function executeBatch(Call[] calldata calls) external payable onlySelf {
uint256 length = calls.length;
for (uint256 i; i < length; ++i) {
_call(calls[i].target, calls[i].value, calls[i].data);
}
}
/**
* @notice Executes the given data from ERC-4337 EntryPoint.
* @dev This function performs execution and should only be called by the EntryPoint.
* ERC-4337 Flag should be enabled, indicates the success of the coupled validation.
* @param target Address to perform execution.
* @param value Uint256 value of native coin.
* @param data Bytes calldata to execute.
*/
function execute4337Op(address target, uint256 value, bytes calldata data)
external
payable
onlyEntryPoint
check4337Flag
{
_call(target, value, data);
}
/**
* @notice Batch executes the given data from ERC-4337 EntryPoint.
* @dev This function performs execution and should only be called by the EntryPoint.
* ERC-4337 Flag should be enabled, indicates the success of the coupled validation.
* @param calls Array of execution data.
*/
function execute4337Ops(Call[] calldata calls) external payable onlyEntryPoint check4337Flag {
uint256 length = calls.length;
for (uint256 i; i < length; ++i) {
_call(calls[i].target, calls[i].value, calls[i].data);
}
}
/**
* @notice Batch executes the given data after performing signature validation.
* @dev This function performs execution and is only executed if signature validation is successful.
* @param calls Array of execution data.
*/
function executeWithSignature(Call[] calldata calls, bytes calldata signature) external payable {
if (
!_validateSignature(
_getEncodedMsgHash(BIZ_EXEC_HASH, keccak256(abi.encode(calls, bizGuard.incrementNonce()))), signature
)
) {
revert InvalidSignature();
}
uint256 length = calls.length;
for (uint256 i; i < length; ++i) {
_call(calls[i].target, calls[i].value, calls[i].data);
}
}
/**
* @notice Receives native coin without data.
*/
receive() external payable {}
/**
* @notice Accepts incoming calls (with or without value), to mimic an EOA.
*/
fallback() external payable {}
/**
* @notice Validates if the signature is signed by Biz.
* @dev Uses ECDSA from Openzeppelin library.
* @param hash Bytes32 hash that is signed.
* @param signature Bytes signature to be validated.
* @return isValid Bytes4 indicating the success/failure of validation.
*/
function _validateSignature(bytes32 hash, bytes calldata signature) private view returns (bool isValid) {
isValid = (address(this) == ECDSA.recover(hash, signature));
}
/**
* @notice Generate encoded message hash from raw hash.
* @dev Uses EIP-712 encoding to wrap hash with typehash & domain separator.
* @param typeHash Bytes32 of Biz message.
* @param hash Bytes32 original hash.
* @return encodedMsgHash Encoded message hash.
*/
function _getEncodedMsgHash(bytes32 typeHash, bytes32 hash) private view returns (bytes32 encodedMsgHash) {
bytes32 messageHash = keccak256(abi.encode(typeHash, hash));
encodedMsgHash = keccak256(abi.encodePacked("\x19\x01", _domainSeparator(), messageHash));
}
/**
* @notice Returns the domain separator
* @dev Includes the address of singleton for signature resilience when re-delegation happens.
* @return domainSeparator Bytes32 domain separator
*/
function _domainSeparator() private view returns (bytes32 domainSeparator) {
return keccak256(
abi.encode(BIZ_DOMAIN_SEPARATOR_HASH, BIZ_HASH, VERSION_HASH, block.chainid, address(this), singletonSalt)
);
}
/**
* @notice Executes the given data.
* @dev This function performs execution and should only be called by the owner EOA.
* @param target Address to perform execution.
* @param value Uint256 value of native coin.
* @param data Bytes calldata to execute.
*/
function _call(address target, uint256 value, bytes memory data) private {
(bool success, bytes memory result) = target.call{value: value}(data);
if (!success) {
assembly {
revert(add(result, 32), mload(result))
}
}
}
/**
* @notice Enable 4337 Flag in transient storage.
* @dev 4337 Flag can only be enabled when
* - BizGuard is enabled
* - Signature validation is successful
* - Validation call is from EntryPoint
*/
function _enable4337Flag() private {
assembly {
tstore(BIZ_4337_FLAG, add(tload(BIZ_4337_FLAG), 1))
}
}
/**
* @notice Converts address to Bytes32
* @dev Zero bytes are padded left. Address is positioned right.
* @param _address Address to be converted to Bytes32
*/
function _addressToBytes32(address _address) private pure returns (bytes32 result) {
assembly {
result := _address
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.20;
import {Ownable} from "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This extension of the {Ownable} contract includes a two-step mechanism to transfer
* ownership, where the new owner must call {acceptOwnership} in order to replace the
* old one. This can help prevent common mistakes, such as transfers of ownership to
* incorrect accounts, or to contracts that are unable to interact with the
* permission system.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*
* Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function tryRecover(
bytes32 hash,
bytes memory signature
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly ("memory-safe") {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.28;
import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol";
/**
* @title BizGuard - Guard contract for Biz.
* @dev Most important concepts:
* - BizGuard maintains the nonce of all Biz for signature validation.
* - BizGuard is an ownable smart contract with 4337 flag to enable/disable ERC-4337 of Biz.
* @author David Kim - @PowerStream3604
*/
contract BizGuard is Ownable2Step {
event FlagSet(bool flag);
mapping(address => uint256) public accountNonce;
bool erc4337Flag;
/**
* @notice constructor
* @dev Sets the initial owner of the account.
* @param owner address.
*/
constructor(address owner) Ownable(owner) {}
/**
* @notice Increment nonce of the msg.sender.
* @dev Nonce can only increment and not decrement.
* @return nonce uint256 nonce of the msg.sender.
*/
function incrementNonce() external returns (uint256 nonce) {
nonce = accountNonce[msg.sender];
unchecked {
++accountNonce[msg.sender];
}
}
/**
* @notice Return if the 4337 flag is enabled.
* @dev This view function is called by validateUserOp() in all Biz wallet.
* @return isEnabled bool flag whether 4337 is enabled.
*/
function is4337Enabled() external view returns (bool isEnabled) {
isEnabled = erc4337Flag;
}
/**
* @notice Set function to set 4337 Flag.
* @dev This function can only be called by the owner.
* @param flag bool value of the flag.
*/
function set4337Flag(bool flag) external onlyOwner {
erc4337Flag = flag;
emit FlagSet(flag);
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.28;
import {ERC721TokenReceiver} from "./interfaces/ERC721TokenReceiver.sol";
import {ERC1155TokenReceiver} from "./interfaces/ERC1155TokenReceiver.sol";
import {IERC165} from "./interfaces/IERC165.sol";
import {IERC7779} from "./interfaces/IERC7779.sol";
import {IERC1271} from "./interfaces/IERC1271.sol";
/**
* @title BizHandler - Handler contract for Biz.
* @author David Kim - @PowerStream3604
*/
abstract contract BizHandler is IERC7779, IERC165, ERC1155TokenReceiver, ERC721TokenReceiver {
// keccak256(abi.encode(uint256(keccak256(bytes("InteroperableDelegatedAccount.ERC.Storage"))) - 1)) & ~bytes32(uint256(0xff));
bytes32 internal constant ERC7779_STORAGE_BASE = 0xc473de86d0138e06e4d4918a106463a7cc005258d2e21915272bcb4594c18900;
struct ERC7779Storage {
bytes32[] storageBases;
}
/**
* @notice Returns if the interfaceId is supported by Biz.
* @param interfaceId Bytes4 interface id.
* @return bool Bool representing if interface id 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
|| interfaceId == type(IERC7779).interfaceId || interfaceId == type(IERC1271).interfaceId;
}
/**
* @notice Handles ERC721 Token callback.
* @return bytes4 Standardized onERC721Received selector.
*/
function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {
return this.onERC721Received.selector;
}
/**
* @notice Handles ERC1155 Token callback.
* @return bytes4 Standardized onERC1155Received selector.
*/
function onERC1155Received(address, address, uint256, uint256, bytes calldata)
external
pure
override
returns (bytes4)
{
return this.onERC1155Received.selector;
}
/**
* @notice Handles ERC1155 Token batch callback.
* @return bytes4 Standardized onERC1155BatchReceived selector.
*/
function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata)
external
pure
override
returns (bytes4)
{
return this.onERC1155BatchReceived.selector;
}
/**
* @notice Handles ERC777 Token callback.
* Does not return value, empty implementation.
*/
function tokensReceived(address, address, address, uint256, bytes calldata, bytes calldata) external pure {}
/**
* @notice Handles ERC677 Token callback.
* @return bool true.
*/
function onTokenTransfer(address, uint256, bytes calldata) external pure returns (bool) {
return true;
}
/**
* @dev Provides the namespace of the account.
* @return string Biz namespace.
*/
function accountId() external pure virtual returns (string memory) {}
/**
* @dev Provides the array of storage bases.
* @return bytes32[] of storage bases.
*/
function accountStorageBases() external view returns (bytes32[] memory) {
ERC7779Storage storage $;
assembly {
$.slot := ERC7779_STORAGE_BASE
}
return $.storageBases;
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.28;
// 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: Apache-2.0
pragma solidity 0.8.28;
/// @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: Apache-2.0
pragma solidity 0.8.28;
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided hash
* @param _hash Hash of the data to be signed
* @param _signature Signature byte array associated with _hash
*
* MUST return the bytes4 magic value 0x1626ba7e when function passes.
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
* MUST allow external calls
*/
function isValidSignature(bytes32 _hash, bytes memory _signature) external view returns (bytes4);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.28;
/// @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: Apache-2.0
pragma solidity 0.8.28;
interface IERC7779 {
/*
* @dev Provides the namespace of the account.
* namespace of accounts can possibly include, account version, account name, wallet vendor name, etc
* @notice this standard does not standardize the namespace format
* e.g., "v0.1.2.7702Account.WalletProjectA"
*/
function accountId() external view returns (string memory);
/*
* @dev Externally shares the storage bases that has been used throughout the account.
* Majority of 7702 accounts will have their distinctive storage base to reduce the chance of storage collision.
* This allows the external entities to know what the storage base is of the account.
* Wallets willing to redelegate already-delegated accounts should call accountStorageBase() to check if it confirms with the account it plans to redelegate.
*
* The bytes32 array should be stored at the storage slot: keccak(keccak('InteroperableDelegatedAccount.ERC.Storage')-1) & ~0xff
* This is an append-only array so newly redelegated accounts should not overwrite the storage at this slot, but just append their base to the array.
* This append operation should be done during the initialization of the account.
* This array should return a value of keccak hash unless using external storage.
*/
function accountStorageBases() external view returns (bytes32[] memory);
}{
"optimizer": {
"enabled": true,
"runs": 999999
},
"viaIR": true,
"evmVersion": "cancun",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract BizGuard","name":"_bizGuard","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"ERC4337Disabled","type":"error"},{"inputs":[],"name":"Invalid4337ExecutionSelector","type":"error"},{"inputs":[],"name":"InvalidERC4337Flag","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"OnlyEntryPoint","type":"error"},{"inputs":[],"name":"OnlySelf","type":"error"},{"inputs":[],"name":"ZeroAddressGuard","type":"error"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"accountId","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"accountStorageBases","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bizGuard","outputs":[{"internalType":"contract BizGuard","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"execute4337Op","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Biz.Call[]","name":"calls","type":"tuple[]"}],"name":"execute4337Ops","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Biz.Call[]","name":"calls","type":"tuple[]"}],"name":"executeBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Biz.Call[]","name":"calls","type":"tuple[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"executeWithSignature","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"isValid","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":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onTokenTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","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"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Biz.PackedUserOperation","name":"userOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"missingAccountFunds","type":"uint256"}],"name":"validateUserOp","outputs":[{"internalType":"uint256","name":"validationData","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
0x60c0346100a857601f611bba38819003918201601f19168301916001600160401b038311848410176100ac578084926020946040528339810103126100a857516001600160a01b0381168082036100a85715610099576080523060a052604051611af990816100c1823960805181818161071a015281816108e20152611025015260a051818181610518015281816112f201526117ee0152f35b63014254ed60e11b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610010575b005b5f3560e01c806223de291461011e57806301ffc9a714610119578063150b7a02146101145780631626ba7e1461010f57806319822f7c1461010a5780631d92e4b61461010557806326da7d881461010057806334fcd5be146100fb57806376276c82146100f65780638626e88b146100f15780639cfd7cff146100ec578063a4c0ed36146100e7578063b0d691fe146100e2578063b61d27f6146100dd578063bc197c81146100d8578063cf21ecab146100d35763f23a6e610361000e57611049565b610fdb565b610f05565b610ee2565b610e9a565b610e7d565b610dcb565b610cef565b610c1a565b610b7f565b610a4f565b610831565b61064b565b6103f5565b610364565b610205565b610173565b73ffffffffffffffffffffffffffffffffffffffff81160361014157565b5f80fd5b9181601f840112156101415782359167ffffffffffffffff8311610141576020838186019501011161014157565b346101415760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576101ad600435610123565b6101b8602435610123565b6101c3604435610123565b60843567ffffffffffffffff8111610141576101e3903690600401610145565b505060a43567ffffffffffffffff81116101415761000e903690600401610145565b346101415760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361014157807f4e2312e0000000000000000000000000000000000000000000000000000000006102b8921490811561033a575b8115610310575b81156102e6575b81156102bc575b5060405190151581529081906020820190565b0390f35b7f1626ba7e000000000000000000000000000000000000000000000000000000009150145f6102a5565b7f1adb9474000000000000000000000000000000000000000000000000000000008114915061029e565b7f01ffc9a70000000000000000000000000000000000000000000000000000000081149150610297565b7f150b7a020000000000000000000000000000000000000000000000000000000081149150610290565b346101415760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415761039e600435610123565b6103a9602435610123565b60643567ffffffffffffffff8111610141576103c9903690600401610145565b505060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b346101415760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760243560043567ffffffffffffffff82116101415761044a6105c5923690600401610145565b9160405160208101917f31322a37c2a66b24e1088197e5b24fcc050625c13d4b84c3eaa6a8be5270321d835260408201526040815261048a606082611107565b5190206105916105bd60405160208101907fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647282527f906754a21e6afe7233c7ccce2787110e84157e1cbaa80e58656dff779193a5cd60408201527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a08201527f000000000000000000000000000000000000000000000000000000000000000060c082015260c0815261054b60e082611107565b5190209260405192839160208301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611107565b519020611827565b15610622576102b87f1626ba7e000000000000000000000000000000000000000000000000000000005b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681529081906020820190565b6102b87fffffffff000000000000000000000000000000000000000000000000000000006105ef565b346101415760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760043567ffffffffffffffff8111610141576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261014157602435906044356f71727de22e5e9d8baf0edac6f37da03233036107d8576040517f7e97025600000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156107d3575f91610798575b5015610770576102b8926107609260040161121d565b6040519081529081906020820190565b7fd13d7835000000000000000000000000000000000000000000000000000000005f5260045ffd5b90506020813d6020116107cb575b816107b360209383611107565b8101031261014157518015158103610141575f61074a565b3d91506107a6565b61114d565b7fbd07c551000000000000000000000000000000000000000000000000000000005f5260045ffd5b9181601f840112156101415782359167ffffffffffffffff8311610141576020808501948460051b01011161014157565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760043567ffffffffffffffff81116101415761087b903690600401610800565b9060243567ffffffffffffffff81116101415761089c903690600401610145565b90604051917f627cdcb90000000000000000000000000000000000000000000000000000000083526020836004815f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af19182156107d35761093d61094293610946955f916109d3575b506040516109358161059160208201948c8c876114ae565b519020611721565b611827565b1590565b6109ab575f5b82811061095557005b806109a561096e61096960019487876115e7565b611654565b602061097b8488886115e7565b013561099f61099861098e868a8a6115e7565b6040810190611158565b369161169b565b916118ad565b0161094c565b7f8baa579f000000000000000000000000000000000000000000000000000000005f5260045ffd5b6109f5915060203d6020116109fb575b6109ed8183611107565b810190611461565b5f61091d565b503d6109e3565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610141576004359067ffffffffffffffff821161014157610a4b91600401610800565b9091565b610a5836610a02565b6f71727de22e5e9d8baf0edac6f37da03233036107d8575f917fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45c9182159182610b23575b90610aa7916116d1565b15610ad9575b50610ab457005b5f7fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a455005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45d5f610aad565b9350611a857fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45403610b5757600193610a9d565b7f33d7b3d6000000000000000000000000000000000000000000000000000000005f5260045ffd5b610b8836610a02565b303303610b985761000e916116d1565b7f14d4a4e8000000000000000000000000000000000000000000000000000000005f5260045ffd5b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261014157600435610bf681610123565b91602435916044359067ffffffffffffffff821161014157610a4b91600401610145565b610c2336610bc0565b9091926f71727de22e5e9d8baf0edac6f37da03233036107d8575f937fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45c9384159384610c7c575b610aa793929161099f91369161169b565b95509190611a857fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45403610b575760019591929091610c6b565b60206040818301928281528451809452019201905f5b818110610cd95750505090565b8251845260209384019390920191600101610ccc565b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576040518060207fc473de86d0138e06e4d4918a106463a7cc005258d2e21915272bcb4594c18900549182815201907fc473de86d0138e06e4d4918a106463a7cc005258d2e21915272bcb4594c189005f527fdb3901c0862740f848a4aebebd6b3d645e6b3bc6adf2cf46e83a846b3a343933905f5b818110610db5576102b885610da981870382611107565b60405191829182610cb6565b8254845260209093019260019283019201610d92565b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576040805190610e088183611107565b6016825260208201917f547275737457616c6c65742e42697a2e76312e302e300000000000000000000083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b3461014157610e8b36610bc0565b50505050602060405160018152f35b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760206040516f71727de22e5e9d8baf0edac6f37da0328152f35b610eeb36610bc0565b92919092303303610b985761000e9361099f91369161169b565b346101415760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014157610f3f600435610123565b610f4a602435610123565b60443567ffffffffffffffff811161014157610f6a903690600401610800565b505060643567ffffffffffffffff811161014157610f8c903690600401610800565b505060843567ffffffffffffffff811161014157610fae903690600401610145565b50506040517fbc197c81000000000000000000000000000000000000000000000000000000008152602090f35b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101415760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014157611083600435610123565b61108e602435610123565b60843567ffffffffffffffff8111610141576110ae903690600401610145565b505060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761114857604052565b6110da565b6040513d5f823e3d90fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610141570180359067ffffffffffffffff82116101415760200191813603831361014157565b906004116101415790600490565b919091357fffffffff00000000000000000000000000000000000000000000000000000000811692600481106111eb575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9061133c9093929360405160208101917f4f51e7a567f083a31264743067875fc6a7ae45c32c5bd71f6a998c4625b138678352604082015260408152611264606082611107565b51902061059161132560405160208101907fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647282527f906754a21e6afe7233c7ccce2787110e84157e1cbaa80e58656dff779193a5cd60408201527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a08201527f000000000000000000000000000000000000000000000000000000000000000060c082015260c0815261054b60e082611107565b519020611336610100840184611158565b91611827565b90606081017f76276c82000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000061139f6113996113938587611158565b906111a9565b906111b7565b1614159182611403575b50506113db57156113d2576113bc611864565b815f925b6113c75750565b5f80808093335af150565b816001926113c0565b7f568becaf000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f26da7d880000000000000000000000000000000000000000000000000000000092506113996113937fffffffff000000000000000000000000000000000000000000000000000000009361145793611158565b1614155f806113a9565b90816020910312610141575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b93929180604086016040875252606085019060608160051b87010191835f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1813603015b84831061150857505050505060209150930152565b90919293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a820301855286358281121561014157830173ffffffffffffffffffffffffffffffffffffffff813561156081610123565b1682526020810135602083015260408101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561014157016020813591019067ffffffffffffffff8111610141578036038213610141576115d8602092839260608681604060019901520191611470565b980197969501930191906114f3565b91908110156116275760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610141570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b3561165e81610123565b90565b67ffffffffffffffff811161114857601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926116a782611661565b916116b56040519384611107565b829481845281830111610141578281602093845f960137010152565b905f5b8181106116e057505050565b8061171b6116f160019385876115e7565b356116fb81610123565b60206117088487896115e7565b013561099f61099861098e86898b6115e7565b016116d4565b60405160208101917fec429430bbd6d0e373848272230d6fe2bac6319d903762e089c5cae97af53df08352604082015260408152611760606082611107565b51902061059161182160405160208101907fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647282527f906754a21e6afe7233c7ccce2787110e84157e1cbaa80e58656dff779193a5cd60408201527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a08201527f000000000000000000000000000000000000000000000000000000000000000060c082015260c0815261054b60e082611107565b51902090565b6118559061184f61185e9373ffffffffffffffffffffffffffffffffffffffff95369161169b565b906118fc565b9092919261196d565b16301490565b60017fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45c017fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45d565b915f928392602083519301915af13d156118f4573d906118cc82611661565b916118da6040519384611107565b82523d5f602084013e5b156118ec5750565b602081519101fd5b6060906118e4565b815191906041830361192c576119259250602082015190606060408401519301515f1a90611a34565b9192909190565b50505f9160029190565b6004111561194057565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b61197681611936565b8061197f575050565b61198881611936565b600181036119b8577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b6119c181611936565b600281036119f557507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b80611a01600392611936565b14611a095750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411611ab8579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156107d3575f5173ffffffffffffffffffffffffffffffffffffffff811615611aae57905f905f90565b505f906001905f90565b5050505f916003919056fea2646970667358221220c2db6d5abc3511f1c5db8e181b811a52e48e4f0b1fdfee2a9ecbcff3bfb11f5764736f6c634300081c00330000000000000000000000006067203e59e681396335940c4f2caf6b002815bc
Deployed Bytecode
0x60806040526004361015610010575b005b5f3560e01c806223de291461011e57806301ffc9a714610119578063150b7a02146101145780631626ba7e1461010f57806319822f7c1461010a5780631d92e4b61461010557806326da7d881461010057806334fcd5be146100fb57806376276c82146100f65780638626e88b146100f15780639cfd7cff146100ec578063a4c0ed36146100e7578063b0d691fe146100e2578063b61d27f6146100dd578063bc197c81146100d8578063cf21ecab146100d35763f23a6e610361000e57611049565b610fdb565b610f05565b610ee2565b610e9a565b610e7d565b610dcb565b610cef565b610c1a565b610b7f565b610a4f565b610831565b61064b565b6103f5565b610364565b610205565b610173565b73ffffffffffffffffffffffffffffffffffffffff81160361014157565b5f80fd5b9181601f840112156101415782359167ffffffffffffffff8311610141576020838186019501011161014157565b346101415760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576101ad600435610123565b6101b8602435610123565b6101c3604435610123565b60843567ffffffffffffffff8111610141576101e3903690600401610145565b505060a43567ffffffffffffffff81116101415761000e903690600401610145565b346101415760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361014157807f4e2312e0000000000000000000000000000000000000000000000000000000006102b8921490811561033a575b8115610310575b81156102e6575b81156102bc575b5060405190151581529081906020820190565b0390f35b7f1626ba7e000000000000000000000000000000000000000000000000000000009150145f6102a5565b7f1adb9474000000000000000000000000000000000000000000000000000000008114915061029e565b7f01ffc9a70000000000000000000000000000000000000000000000000000000081149150610297565b7f150b7a020000000000000000000000000000000000000000000000000000000081149150610290565b346101415760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415761039e600435610123565b6103a9602435610123565b60643567ffffffffffffffff8111610141576103c9903690600401610145565b505060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b346101415760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760243560043567ffffffffffffffff82116101415761044a6105c5923690600401610145565b9160405160208101917f31322a37c2a66b24e1088197e5b24fcc050625c13d4b84c3eaa6a8be5270321d835260408201526040815261048a606082611107565b5190206105916105bd60405160208101907fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647282527f906754a21e6afe7233c7ccce2787110e84157e1cbaa80e58656dff779193a5cd60408201527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a08201527f000000000000000000000000d2e28229f6f2c235e57de2ebc727025a1d0530fb60c082015260c0815261054b60e082611107565b5190209260405192839160208301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611107565b519020611827565b15610622576102b87f1626ba7e000000000000000000000000000000000000000000000000000000005b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681529081906020820190565b6102b87fffffffff000000000000000000000000000000000000000000000000000000006105ef565b346101415760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760043567ffffffffffffffff8111610141576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261014157602435906044356f71727de22e5e9d8baf0edac6f37da03233036107d8576040517f7e97025600000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006067203e59e681396335940c4f2caf6b002815bc165afa9081156107d3575f91610798575b5015610770576102b8926107609260040161121d565b6040519081529081906020820190565b7fd13d7835000000000000000000000000000000000000000000000000000000005f5260045ffd5b90506020813d6020116107cb575b816107b360209383611107565b8101031261014157518015158103610141575f61074a565b3d91506107a6565b61114d565b7fbd07c551000000000000000000000000000000000000000000000000000000005f5260045ffd5b9181601f840112156101415782359167ffffffffffffffff8311610141576020808501948460051b01011161014157565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760043567ffffffffffffffff81116101415761087b903690600401610800565b9060243567ffffffffffffffff81116101415761089c903690600401610145565b90604051917f627cdcb90000000000000000000000000000000000000000000000000000000083526020836004815f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006067203e59e681396335940c4f2caf6b002815bc165af19182156107d35761093d61094293610946955f916109d3575b506040516109358161059160208201948c8c876114ae565b519020611721565b611827565b1590565b6109ab575f5b82811061095557005b806109a561096e61096960019487876115e7565b611654565b602061097b8488886115e7565b013561099f61099861098e868a8a6115e7565b6040810190611158565b369161169b565b916118ad565b0161094c565b7f8baa579f000000000000000000000000000000000000000000000000000000005f5260045ffd5b6109f5915060203d6020116109fb575b6109ed8183611107565b810190611461565b5f61091d565b503d6109e3565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610141576004359067ffffffffffffffff821161014157610a4b91600401610800565b9091565b610a5836610a02565b6f71727de22e5e9d8baf0edac6f37da03233036107d8575f917fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45c9182159182610b23575b90610aa7916116d1565b15610ad9575b50610ab457005b5f7fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a455005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45d5f610aad565b9350611a857fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45403610b5757600193610a9d565b7f33d7b3d6000000000000000000000000000000000000000000000000000000005f5260045ffd5b610b8836610a02565b303303610b985761000e916116d1565b7f14d4a4e8000000000000000000000000000000000000000000000000000000005f5260045ffd5b60607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261014157600435610bf681610123565b91602435916044359067ffffffffffffffff821161014157610a4b91600401610145565b610c2336610bc0565b9091926f71727de22e5e9d8baf0edac6f37da03233036107d8575f937fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45c9384159384610c7c575b610aa793929161099f91369161169b565b95509190611a857fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45403610b575760019591929091610c6b565b60206040818301928281528451809452019201905f5b818110610cd95750505090565b8251845260209384019390920191600101610ccc565b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576040518060207fc473de86d0138e06e4d4918a106463a7cc005258d2e21915272bcb4594c18900549182815201907fc473de86d0138e06e4d4918a106463a7cc005258d2e21915272bcb4594c189005f527fdb3901c0862740f848a4aebebd6b3d645e6b3bc6adf2cf46e83a846b3a343933905f5b818110610db5576102b885610da981870382611107565b60405191829182610cb6565b8254845260209093019260019283019201610d92565b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610141576040805190610e088183611107565b6016825260208201917f547275737457616c6c65742e42697a2e76312e302e300000000000000000000083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b3461014157610e8b36610bc0565b50505050602060405160018152f35b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101415760206040516f71727de22e5e9d8baf0edac6f37da0328152f35b610eeb36610bc0565b92919092303303610b985761000e9361099f91369161169b565b346101415760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014157610f3f600435610123565b610f4a602435610123565b60443567ffffffffffffffff811161014157610f6a903690600401610800565b505060643567ffffffffffffffff811161014157610f8c903690600401610800565b505060843567ffffffffffffffff811161014157610fae903690600401610145565b50506040517fbc197c81000000000000000000000000000000000000000000000000000000008152602090f35b34610141575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006067203e59e681396335940c4f2caf6b002815bc168152f35b346101415760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014157611083600435610123565b61108e602435610123565b60843567ffffffffffffffff8111610141576110ae903690600401610145565b505060206040517ff23a6e61000000000000000000000000000000000000000000000000000000008152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761114857604052565b6110da565b6040513d5f823e3d90fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610141570180359067ffffffffffffffff82116101415760200191813603831361014157565b906004116101415790600490565b919091357fffffffff00000000000000000000000000000000000000000000000000000000811692600481106111eb575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b9061133c9093929360405160208101917f4f51e7a567f083a31264743067875fc6a7ae45c32c5bd71f6a998c4625b138678352604082015260408152611264606082611107565b51902061059161132560405160208101907fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647282527f906754a21e6afe7233c7ccce2787110e84157e1cbaa80e58656dff779193a5cd60408201527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a08201527f000000000000000000000000d2e28229f6f2c235e57de2ebc727025a1d0530fb60c082015260c0815261054b60e082611107565b519020611336610100840184611158565b91611827565b90606081017f76276c82000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000061139f6113996113938587611158565b906111a9565b906111b7565b1614159182611403575b50506113db57156113d2576113bc611864565b815f925b6113c75750565b5f80808093335af150565b816001926113c0565b7f568becaf000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f26da7d880000000000000000000000000000000000000000000000000000000092506113996113937fffffffff000000000000000000000000000000000000000000000000000000009361145793611158565b1614155f806113a9565b90816020910312610141575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b93929180604086016040875252606085019060608160051b87010191835f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1813603015b84831061150857505050505060209150930152565b90919293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a820301855286358281121561014157830173ffffffffffffffffffffffffffffffffffffffff813561156081610123565b1682526020810135602083015260408101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561014157016020813591019067ffffffffffffffff8111610141578036038213610141576115d8602092839260608681604060019901520191611470565b980197969501930191906114f3565b91908110156116275760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610141570190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b3561165e81610123565b90565b67ffffffffffffffff811161114857601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926116a782611661565b916116b56040519384611107565b829481845281830111610141578281602093845f960137010152565b905f5b8181106116e057505050565b8061171b6116f160019385876115e7565b356116fb81610123565b60206117088487896115e7565b013561099f61099861098e86898b6115e7565b016116d4565b60405160208101917fec429430bbd6d0e373848272230d6fe2bac6319d903762e089c5cae97af53df08352604082015260408152611760606082611107565b51902061059161182160405160208101907fd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac5647282527f906754a21e6afe7233c7ccce2787110e84157e1cbaa80e58656dff779193a5cd60408201527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a08201527f000000000000000000000000d2e28229f6f2c235e57de2ebc727025a1d0530fb60c082015260c0815261054b60e082611107565b51902090565b6118559061184f61185e9373ffffffffffffffffffffffffffffffffffffffff95369161169b565b906118fc565b9092919261196d565b16301490565b60017fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45c017fa77908bfab24e6768503125e99551a4fa5c3c75f3106fee5dea5ac0cebc017a45d565b915f928392602083519301915af13d156118f4573d906118cc82611661565b916118da6040519384611107565b82523d5f602084013e5b156118ec5750565b602081519101fd5b6060906118e4565b815191906041830361192c576119259250602082015190606060408401519301515f1a90611a34565b9192909190565b50505f9160029190565b6004111561194057565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b61197681611936565b8061197f575050565b61198881611936565b600181036119b8577ff645eedf000000000000000000000000000000000000000000000000000000005f5260045ffd5b6119c181611936565b600281036119f557507ffce698f7000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b80611a01600392611936565b14611a095750565b7fd78bce0c000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411611ab8579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156107d3575f5173ffffffffffffffffffffffffffffffffffffffff811615611aae57905f905f90565b505f906001905f90565b5050505f916003919056fea2646970667358221220c2db6d5abc3511f1c5db8e181b811a52e48e4f0b1fdfee2a9ecbcff3bfb11f5764736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.