Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | Amount | ||
|---|---|---|---|---|---|---|
| 29069386 | 198 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
InstructionStorage
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 1000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.26;
import {Constants} from "../libraries/Constants.sol";
import {InstructionLib} from "../libraries/Instruction.sol";
import {IInstructionStorage} from "./interfaces/IInstructionStorage.sol";
/// @title InstructionStorage
/// @author Otim Labs, Inc.
/// @notice external storage contract for storing Instruction execution state
contract InstructionStorage is IInstructionStorage {
//slither-disable-start too-many-digits
/// @notice hash of the "delegation designator" i.e. keccak256(0xef0100 || delegate_address)
bytes32 public immutable designatorHash;
/// @notice reverts if the modified function is not called from within the code of a delegated EOA
/// @dev if the EOA codehash matches `designator`, the EOA is delegated to some contract,
/// and if msg.sender is not equal to tx.origin, the EOA has not called the function directly
modifier fromDelegateCodeOnly() {
// IInstructionStorage.DataCorruptionAttempted.selector = 0xabdc7b7a
bytes32 designatorHash_ = designatorHash;
assembly {
// revert if msg.sender == tx.origin OR msg.sender.codehash != delegateCodehash
// from innermost to outermost:
// 1. retrieve the codehash of the msg.sender
// 2. load `delegateCodehash` from storage (slot 0 is the address of the `owner` and slot 1 is the `delegateCodehash`)
// 3. compare the codehash of msg.sender to the `delegateCodehash`
// 4. if they are not equal, revert
// 5. compare msg.sender to tx.origin
// 6. if they are equal, revert
if or(eq(caller(), origin()), iszero(eq(extcodehash(caller()), designatorHash_))) {
// store `IInstructionStorage.DataCorruptionAttempted.selector` in memory.
// memory bytes [0, 27] are zero and bytes [28, 31] are the 4-byte-long selector
mstore(0x0, 0xabdc7b7a)
// decoding this revert statement: we revert starting at memory byte 28 with a length of 4
// to return the selector as the reason for the revert
revert(0x1c, 0x4)
}
}
_;
}
constructor() {
// construct the "delegation designator", then hash it.
// OtimDelegate will deploy this contract so msg.sender will be the address of the delegate contract
designatorHash = keccak256(abi.encodePacked(Constants.EIP7702_PREFIX, msg.sender));
}
/// @inheritdoc IInstructionStorage
function incrementExecutionCounter(bytes32 instructionId) external fromDelegateCodeOnly {
assembly {
// store msg.sender in memory: bytes [0, 11] are 0, bytes [12, 31] are msg.sender address
mstore(0x0, caller())
// store `instructionId` in memory bytes [32, 63]
mstore(0x20, instructionId)
// compute the keccak256 hash of memory bytes [0, 63] to use as the storage `key`
let key := keccak256(0x0, 0x40)
// from innermost to outermost:
// 1. load the storage value at `key`. This value is structured as follows:
// byte 0 is free,
// byte 1 is the `deactivated` boolean,
// bytes [2, 16] are the `counter`,
// bytes [17, 31] are the `lastExecuted` timestamp
// 2. discard `lastExecuted` by masking out the last 15 bytes
// 3. increment `counter` by 1 (add 1 left-shifted by 15 bytes to the retrieved storage value)
// 4. set the last 15 bytes of the storage value to the current block.timestamp
// 5. store the updated storage value at `key`
/// @dev casting `block.timestamp` from uint256 to uint120 is safe because it will only overflow
/// 2^120 seconds after epoch which is approximately 40 Octillion years from now... we'll have a v2 by then :)
/// Similarly, using a uint120 for the `counter` is safe because it will only overflow after
/// 2^120 executions (approximately 1 Undecillion executions). Also, despite this being completely infeasible,
/// if `counter` were to overflow, it would simply set the `deactivated` boolean to true, making it
/// impossible to execute the Instruction again.
sstore(
key,
or(
add(
and(sload(key), 0xffffffffffffffffffffffffffffffffff000000000000000000000000000000),
0x1000000000000000000000000000000
),
timestamp()
)
)
}
}
/// @inheritdoc IInstructionStorage
function incrementAndDeactivate(bytes32 instructionId) external fromDelegateCodeOnly {
assembly {
// store msg.sender in memory: bytes [0, 11] are 0, bytes [12, 31] are msg.sender address
mstore(0x0, caller())
// store `instructionId` in memory bytes [32, 63]
mstore(0x20, instructionId)
// compute the keccak256 hash of memory bytes [0, 63] to use as the storage `key`
let key := keccak256(0x0, 0x40)
// from innermost to outermost:
// 1. load the storage value at `key`. This value is structured as follows:
// byte 0 is free,
// byte 1 is the `deactivated` boolean,
// bytes [2, 16] are the `counter`,
// bytes [17, 31] are the `lastExecuted` timestamp
// 2. discard `lastExecuted` by masking out the last 15 bytes
// 3. increment `counter` by 1 (add 1 left-shifted by 15 bytes to the retrieved storage value)
// 4. set the last 15 bytes of the storage value to the current block.timestamp
// 5. set the `deactivated` boolean to true
// 6. store the updated storage value at `key`
sstore(
key,
or(
or(
add(
and(sload(key), 0xffffffffffffffffffffffffffffffffff000000000000000000000000000000),
0x1000000000000000000000000000000
),
timestamp()
),
0x1000000000000000000000000000000000000000000000000000000000000
)
)
}
}
/// @inheritdoc IInstructionStorage
function deactivateStorage(bytes32 instructionId) external fromDelegateCodeOnly {
assembly {
// store msg.sender in memory: bytes [0, 11] are 0, bytes [12, 31] are msg.sender address
mstore(0x0, caller())
// store `instructionId` in memory bytes [32, 63]
mstore(0x20, instructionId)
// compute the keccak256 hash of memory bytes [0, 63] to use as the storage `key`
let key := keccak256(0x0, 0x40)
// 1. load the storage value at `key`
// 2. set the `deactivated` boolean to true
// 3. store the updated storage value at `key`
sstore(key, or(sload(key), 0x1000000000000000000000000000000000000000000000000000000000000))
}
}
/// @inheritdoc IInstructionStorage
function isDeactivated(bytes32 instructionId) external view returns (bool) {
assembly {
// store msg.sender in memory: bytes [0, 11] are 0, bytes [12, 31] are msg.sender address
mstore(0x0, caller())
// store `instructionId` in memory bytes [32, 63]
mstore(0x20, instructionId)
// compute the keccak256 hash of memory bytes [0, 63] to use as the storage `key`
let key := keccak256(0x0, 0x40)
// 1. load the storage value at `key`
// 2. right-shift the loaded storage value by 30 bytes to get the `deactivated` boolean
// 3. store the `deactivated` boolean in memory bytes [0, 31]
mstore(0x0, shr(0xf0, sload(key)))
// return the `deactivated` boolean (memory starting at 0 with a length of 32)
return(0x0, 0x20)
}
}
/// @inheritdoc IInstructionStorage
function getExecutionState(bytes32 instructionId) external view returns (InstructionLib.ExecutionState memory) {
assembly {
// store msg.sender in memory: bytes [0, 11] are 0, bytes [12, 31] are msg.sender address
mstore(0x0, caller())
// store `instructionId` in memory bytes [32, 63]
mstore(0x20, instructionId)
// compute the keccak256 hash of memory bytes [0, 63] to use as the storage `key`
let key := keccak256(0x0, 0x40)
// load the storage value at `key` into `value`
let value := sload(key)
// load the 32-byte word at memory location 0x40 into `ptr`. This is the location of the next free slot in memory
/// @dev we have to use free memory slots to store return values here because they are more than 64 bytes
let ptr := mload(0x40)
// 1. right-shift `value` by 30 bytes to get the `deactivated` boolean
// 2. store this at memory location `ptr`
mstore(ptr, shr(0xf0, value))
// 1. right-shift `value` by 15 bytes to get rid of `lastExecuted`
// 2. mask out the first 17 bytes of `value` to get `counter`
// 3. store this at memory location `ptr` + 32 bytes
mstore(add(ptr, 0x20), and(0xffffffffffffffffffffffffffffff, shr(0x78, value)))
// 1. mask out the first 17 bytes of `value` to get `lastExecuted`
// 2. store this at memory location `ptr` + 64 bytes
mstore(add(ptr, 0x40), and(0xffffffffffffffffffffffffffffff, value))
// return `deactivated`, `counter`, and `lastExecuted` as separate values
// by returning memory starting at `ptr` with a length of 96 bytes
return(ptr, 0x60)
}
}
/// @notice returns the execution state of an Instruction for a particular user
/// @param instructionId - unique identifier for an Instruction
/// @param user - address of the EOA to return execution state for
/// @return executionState - the current execution state of the Instruction
function getExecutionState(address user, bytes32 instructionId)
external
view
returns (InstructionLib.ExecutionState memory)
{
assembly {
// store `user` in memory: bytes [0, 11] are 0, bytes [12, 31] are `user`
mstore(0x0, user)
// store `instructionId` in memory bytes [32, 63]
mstore(0x20, instructionId)
// compute the keccak256 hash of memory bytes [0, 63] to use as the storage `key`
let key := keccak256(0x0, 0x40)
// load the storage value at `key` into `value`
let value := sload(key)
// load the 32-byte word at memory location 0x40 into `ptr`. This is the location of the next free slot in memory
let ptr := mload(0x40)
// 1. right-shift `value` by 30 bytes to get the `deactivated` boolean
// 2. store this at memory location `ptr`
mstore(ptr, shr(0xf0, value))
// 1. right-shift `value` by 15 bytes to get rid of `lastExecuted`
// 2. mask out the first 17 bytes of `value` to get `counter`
// 3. store this at memory location `ptr` + 32 bytes
mstore(add(ptr, 0x20), and(0xffffffffffffffffffffffffffffff, shr(0x78, value)))
// 1. mask out the first 17 bytes of `value` to get `lastExecuted`
// 2. store this at memory location `ptr` + 64 bytes
mstore(add(ptr, 0x40), and(0xffffffffffffffffffffffffffffff, value))
// return `deactivated`, `counter`, and `lastExecuted` as separate values
// by returning memory starting at `ptr` with a length of 96 bytes
return(ptr, 0x60)
}
}
//slither-disable-end too-many-digits
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.26;
/// @title Constants
/// @author Otim Labs, Inc.
/// @notice a library defining constants used throughout the protocol
library Constants {
/// @notice the EIP-712 signature prefix
bytes2 public constant EIP712_PREFIX = 0x1901;
/// @notice the EIP-7702 delegation designator prefix
bytes3 public constant EIP7702_PREFIX = 0xef0100;
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.26;
import {Constants} from "./Constants.sol";
/// @title InstructionLib
/// @author Otim Labs, Inc.
/// @notice a library defining the Instruction datatype and util functions
library InstructionLib {
/// @notice defines a signature
struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
}
/// @notice defines the ExecutionState datatype
/// @param deactivated - whether the Instruction has been deactivated
/// @param executionCount - the number of times the Instruction has been executed
/// @param lastExecuted - the unix timestamp of the last time the Instruction was executed
struct ExecutionState {
bool deactivated;
uint120 executionCount;
uint120 lastExecuted;
}
/// @notice defines the Instruction datatype
/// @param salt - a number to ensure the uniqueness of the Instruction
/// @param maxExecutions - the maximum number of times the Instruction can be executed
/// @param action - the address of the Action contract to be executed
/// @param arguments - the arguments to be passed to the Action contract
struct Instruction {
uint256 salt;
uint256 maxExecutions;
address action;
bytes arguments;
}
/// @notice abi.encodes and hashes an Instruction struct to create a unique Instruction identifier
/// @param instruction - an Instruction struct to hash
/// @return instructionId - unique identifier for the Instruction
function id(Instruction calldata instruction) internal pure returns (bytes32) {
return keccak256(abi.encode(instruction));
}
/// @notice calculates the EIP-712 hash for activating an Instruction
/// @param instruction - an Instruction struct to hash
/// @param domainSeparator - the EIP-712 domain separator for the verifying contract
/// @return hash - EIP-712 hash for activating `instruction`
function signingHash(
Instruction calldata instruction,
bytes32 domainSeparator,
bytes32 instructionTypeHash,
bytes32 argumentsHash
) internal pure returns (bytes32) {
return keccak256(
abi.encodePacked(
Constants.EIP712_PREFIX,
domainSeparator,
keccak256(
abi.encode(
instructionTypeHash,
instruction.salt,
instruction.maxExecutions,
instruction.action,
argumentsHash
)
)
)
);
}
/// @notice defines a deactivation instruction
/// @param instructionId - the unique identifier of the Instruction to deactivate
struct InstructionDeactivation {
bytes32 instructionId;
}
/// @notice the EIP-712 type-hash for an InstructionDeactivation
bytes32 public constant DEACTIVATION_TYPEHASH = keccak256("InstructionDeactivation(bytes32 instructionId)");
/// @notice calculates the EIP-712 hash for a InstructionDeactivation
/// @param deactivation - an InstructionDeactivation struct to hash
/// @param domainSeparator - the EIP-712 domain separator for the verifying contract
/// @return hash - EIP-712 hash for the `deactivation`
function signingHash(InstructionDeactivation calldata deactivation, bytes32 domainSeparator)
internal
pure
returns (bytes32)
{
return keccak256(
abi.encodePacked(
Constants.EIP712_PREFIX,
domainSeparator,
keccak256(abi.encode(DEACTIVATION_TYPEHASH, deactivation.instructionId))
)
);
}
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.26;
import {InstructionLib} from "../../libraries/Instruction.sol";
/// @title IInstructionStorage
/// @author Otim Labs, Inc.
/// @notice interface for InstructionStorage contract
interface IInstructionStorage {
error DataCorruptionAttempted();
/// @notice increments the execution counter for an Instruction and sets `lastExecuted` to current block.timestamp
/// @param instructionId - unique identifier for an Instruction
function incrementExecutionCounter(bytes32 instructionId) external;
/// @notice increments the execution counter for an Instruction, sets `lastExecuted` to current block.timestamp, and deactivates
/// @param instructionId - unique identifier for an Instruction
function incrementAndDeactivate(bytes32 instructionId) external;
/// @notice deactivates an Instruction's execution state in storage
/// @param instructionId - unique identifier for an Instruction
function deactivateStorage(bytes32 instructionId) external;
/// @notice returns the execution state of an Instruction for a particular user
/// @param user - the user the Instruction pertains to
/// @param instructionId - unique identifier for an Instruction
/// @return executionState - the current execution state of the Instruction
function getExecutionState(address user, bytes32 instructionId)
external
view
returns (InstructionLib.ExecutionState memory);
/// @notice returns the execution state of an Instruction for msg.sender
/// @param instructionId - unique identifier for an Instruction
/// @return executionState - the current execution state of the Instruction
function getExecutionState(bytes32 instructionId) external view returns (InstructionLib.ExecutionState memory);
/// @notice checks if an Instruction is deactivated for msg.sender
/// @param instructionId - unique identifier for an Instruction
/// @return deactivated - true if the Instruction is deactivated
function isDeactivated(bytes32 instructionId) external view returns (bool);
}{
"remappings": [
"@chainlink-contracts/=dependencies/smartcontractkit-chainlink-2.25.0/contracts/",
"@openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.4.0/",
"@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.4.0/",
"@uniswap-universal-router/=dependencies/@uniswap-universal-router-2.0.0/",
"@uniswap-v3-core/=dependencies/@uniswap-v3-core-1.0.2-solc-0.8-simulate/",
"@uniswap-v3-periphery/=dependencies/@uniswap-v3-periphery-1.4.4/",
"forge-std/=dependencies/forge-std-1.10.0/",
"@openzeppelin-contracts-5.4.0/=dependencies/@openzeppelin-contracts-5.4.0/",
"@uniswap-universal-router-2.0.0/=dependencies/@uniswap-universal-router-2.0.0/",
"@uniswap-v3-core-1.0.2-solc-0.8-simulate/=dependencies/@uniswap-v3-core-1.0.2-solc-0.8-simulate/contracts/",
"@uniswap-v3-periphery-1.4.4/=dependencies/@uniswap-v3-periphery-1.4.4/contracts/",
"@uniswap/=dependencies/@uniswap-v3-periphery-1.4.4/node_modules/@uniswap/",
"ds-test/=dependencies/@uniswap-universal-router-2.0.0/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=dependencies/@uniswap-universal-router-2.0.0/lib/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-gas-snapshot/=dependencies/@uniswap-universal-router-2.0.0/lib/permit2/lib/forge-gas-snapshot/src/",
"forge-std-1.10.0/=dependencies/forge-std-1.10.0/src/",
"openzeppelin-contracts/=dependencies/@uniswap-universal-router-2.0.0/lib/permit2/lib/openzeppelin-contracts/",
"permit2/=dependencies/@uniswap-universal-router-2.0.0/lib/permit2/",
"smartcontractkit-chainlink-2.25.0/=dependencies/smartcontractkit-chainlink-2.25.0/",
"solmate/=dependencies/@uniswap-universal-router-2.0.0/lib/solmate/src/",
"v3-periphery/=dependencies/@uniswap-universal-router-2.0.0/lib/v3-periphery/contracts/",
"v4-core/=dependencies/@uniswap-universal-router-2.0.0/lib/v4-periphery/lib/v4-core/src/",
"v4-periphery/=dependencies/@uniswap-universal-router-2.0.0/lib/v4-periphery/"
],
"optimizer": {
"enabled": true,
"runs": 1000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DataCorruptionAttempted","type":"error"},{"inputs":[{"internalType":"bytes32","name":"instructionId","type":"bytes32"}],"name":"deactivateStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"designatorHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"instructionId","type":"bytes32"}],"name":"getExecutionState","outputs":[{"components":[{"internalType":"bool","name":"deactivated","type":"bool"},{"internalType":"uint120","name":"executionCount","type":"uint120"},{"internalType":"uint120","name":"lastExecuted","type":"uint120"}],"internalType":"struct InstructionLib.ExecutionState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes32","name":"instructionId","type":"bytes32"}],"name":"getExecutionState","outputs":[{"components":[{"internalType":"bool","name":"deactivated","type":"bool"},{"internalType":"uint120","name":"executionCount","type":"uint120"},{"internalType":"uint120","name":"lastExecuted","type":"uint120"}],"internalType":"struct InstructionLib.ExecutionState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"instructionId","type":"bytes32"}],"name":"incrementAndDeactivate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"instructionId","type":"bytes32"}],"name":"incrementExecutionCounter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"instructionId","type":"bytes32"}],"name":"isDeactivated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a0604052348015600e575f80fd5b5060405161ef0160f01b60208201526001600160601b03193360601b16602382015260370160408051601f19818403018152919052805160209091012060805260805161040c61007b5f395f81816101490152818161017b015281816101f901526102db015261040c5ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c80638d5066a9116100585780638d5066a9146100fb578063cb4cf15b1461010e578063d300e03514610131578063f208d98914610144575f80fd5b806323fa8a4b1461007e5780633d71f9b91461009357806349d8033e146100a6575b5f80fd5b61009161008c3660046103b3565b610179565b005b6100916100a13660046103b3565b6101f7565b6100b96100b43660046103b3565b61026f565b604080518251151581526020808401516effffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060015b60405180910390f35b6100916101093660046103b3565b6102d9565b61012161011c3660046103b3565b610331565b60405190151581526020016100f2565b6100b961013f3660046103ca565b610349565b61016b7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100f2565b7f00000000000000000000000000000000000000000000000000000000000000003233908114903f82141517156101b75763abdc7b7a5f526004601cfd5b335f528160205260405f20600160f01b426f010000000000000000000000000000006effffffffffffffffffffffffffffff198454160117178155505050565b7f00000000000000000000000000000000000000000000000000000000000000003233908114903f82141517156102355763abdc7b7a5f526004601cfd5b335f528160205260405f20426f010000000000000000000000000000006effffffffffffffffffffffffffffff1983541601178155505050565b604080516060810182525f8082526020820181905291810191909152335f528160205260405f20805490506040518160f01c81528160781c6effffffffffffffffffffffffffffff166020820152816effffffffffffffffffffffffffffff166040820152606081f35b7f00000000000000000000000000000000000000000000000000000000000000003233908114903f82141517156103175763abdc7b7a5f526004601cfd5b335f528160205260405f20600160f01b8154178155505050565b5f335f528160205260405f20805460f01c5f5260205ff35b604080516060810182525f8082526020820181905291810191909152825f528160205260405f20805490506040518160f01c81528160781c6effffffffffffffffffffffffffffff166020820152816effffffffffffffffffffffffffffff166040820152606081f35b5f602082840312156103c3575f80fd5b5035919050565b5f80604083850312156103db575f80fd5b823573ffffffffffffffffffffffffffffffffffffffff811681146103fe575f80fd5b94602093909301359350505056
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061007a575f3560e01c80638d5066a9116100585780638d5066a9146100fb578063cb4cf15b1461010e578063d300e03514610131578063f208d98914610144575f80fd5b806323fa8a4b1461007e5780633d71f9b91461009357806349d8033e146100a6575b5f80fd5b61009161008c3660046103b3565b610179565b005b6100916100a13660046103b3565b6101f7565b6100b96100b43660046103b3565b61026f565b604080518251151581526020808401516effffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060015b60405180910390f35b6100916101093660046103b3565b6102d9565b61012161011c3660046103b3565b610331565b60405190151581526020016100f2565b6100b961013f3660046103ca565b610349565b61016b7f9b81987cf64360effca7ace696c28e35019fb60f68e9069af5db08f6411e1abd81565b6040519081526020016100f2565b7f9b81987cf64360effca7ace696c28e35019fb60f68e9069af5db08f6411e1abd3233908114903f82141517156101b75763abdc7b7a5f526004601cfd5b335f528160205260405f20600160f01b426f010000000000000000000000000000006effffffffffffffffffffffffffffff198454160117178155505050565b7f9b81987cf64360effca7ace696c28e35019fb60f68e9069af5db08f6411e1abd3233908114903f82141517156102355763abdc7b7a5f526004601cfd5b335f528160205260405f20426f010000000000000000000000000000006effffffffffffffffffffffffffffff1983541601178155505050565b604080516060810182525f8082526020820181905291810191909152335f528160205260405f20805490506040518160f01c81528160781c6effffffffffffffffffffffffffffff166020820152816effffffffffffffffffffffffffffff166040820152606081f35b7f9b81987cf64360effca7ace696c28e35019fb60f68e9069af5db08f6411e1abd3233908114903f82141517156103175763abdc7b7a5f526004601cfd5b335f528160205260405f20600160f01b8154178155505050565b5f335f528160205260405f20805460f01c5f5260205ff35b604080516060810182525f8082526020820181905291810191909152825f528160205260405f20805490506040518160f01c81528160781c6effffffffffffffffffffffffffffff166020820152816effffffffffffffffffffffffffffff166040820152606081f35b5f602082840312156103c3575f80fd5b5035919050565b5f80604083850312156103db575f80fd5b823573ffffffffffffffffffffffffffffffffffffffff811681146103fe575f80fd5b94602093909301359350505056
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.