Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Answer | 24472945 | 21 days ago | IN | 0 ETH | 0.00002824 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x3d602d80 | 24469601 | 22 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Minimal Proxy Contract for 0xc49c177736107fd8351ed6564136b9adbe5b1ec3
Contract Name:
PredictionPoll
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 99999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {PollStatus, IPredictionPoll, IPredictionOracle} from "./interfaces/IPredictionOracle.sol";
/**
* @title PredictionPoll
* @notice Individual poll contract storing question data and answer
* @dev Deployed by PredictionOracle for each poll
*/
contract PredictionPoll is IPredictionPoll {
/// @notice Factory contract address
address public factory;
/// @notice Arbitration started flag
bool public arbitrationStarted;
/// @notice Poll data storage
PollData private _pollData;
/// @notice Initialization flag to prevent re-initialization
bool private _initialized;
// ============================================
// CONSTANTS
// ============================================
/// @notice Arbitration submission window - time to request arbitration (24 hours = 288 epochs, as EPOCH_LENGTH = 5 minutes)
uint32 public constant ARBITRATION_SUBMISSION_WINDOW = 288;
/// @notice Arbitration escalation period - additional time when arbitration is started (36 hours = 432 epochs)
uint32 public constant ARBITRATION_ESCALATION_PERIOD = 432;
// ============================================
// MODIFIERS
// ============================================
/// @notice Restrict function to factory only
modifier onlyFactory() {
if (msg.sender != factory) revert OnlyFactory();
_;
}
/// @notice Restrict to one-time initialization
modifier initializer() {
if (_initialized) revert AlreadyInitialized();
_initialized = true;
_;
}
/// @notice Restrict function to arbiter only
modifier onlyArbiter() {
if (msg.sender != _pollData.arbiter) revert OnlyArbiter();
_;
}
/// @notice Restrict function to operator only
modifier onlyOperator() {
bool isOperator = IPredictionOracle(factory).isOperator(msg.sender);
if (!isOperator) revert OnlyOperator();
_;
}
/// @notice Validate that status is a valid resolution (not Pending)
modifier validResolutionStatus(PollStatus _status) {
if (_status == PollStatus.Pending) revert InvalidResolutionStatus();
_;
}
// ============================================
// CONSTRUCTOR
// ============================================
/**
* @notice Constructor for implementation contract
* @dev Immediately marks implementation as initialized to prevent direct use
* @dev Only clones can be properly initialized
*/
constructor() {
_initialized = true; // Lock implementation contract
}
// ============================================
// INITIALIZATION
// ============================================
/**
* @notice Initialize poll with data (called once after clone deployment)
* @dev Replaces constructor for clone pattern
* @dev Can only be called once
* @param _question Question text
* @param _rules Rules description
* @param _sources Source URLs array
* @param _deadlineEpoch Epoch when poll should be checked/resolved
* @param _creator Poll creator address
* @param _arbiter Arbiter address who can override poll status
* @param _category Poll type/category for frontend classification
*/
function initialize(
string memory _question,
string memory _rules,
string[] memory _sources,
uint32 _deadlineEpoch,
address _creator,
address _arbiter,
uint8 _category
) external initializer {
factory = msg.sender;
// Initialize poll data (omit default values for gas savings)
_pollData.question = _question;
_pollData.rules = _rules;
_pollData.sources = _sources;
_pollData.creator = _creator;
_pollData.arbiter = _arbiter;
_pollData.category = _category;
_pollData.finalizationEpoch =
_deadlineEpoch +
ARBITRATION_SUBMISSION_WINDOW; // can be changed by operator
_pollData.deadlineEpoch = _deadlineEpoch; // constant for now
// status defaults to Pending (0)
// resolutionReason defaults to "" (empty)
}
// ============================================
// EXTERNAL FUNCTIONS
// ============================================
/**
* @notice Set poll answer by operator
* @dev Can only be called by operators when status is Pending
* @dev Operator can only set answer when:
* - Current epoch >= deadlineEpoch
* - Current epoch < finalizationEpoch
* - Current status is Pending
* @param _status New status to set (Yes, No, or Unknown)
* @param _reason Explanation/reasoning for the resolution decision
*/
function setAnswer(
PollStatus _status,
string calldata _reason
) external onlyOperator validResolutionStatus(_status) {
uint32 currentEpoch = IPredictionOracle(factory).getCurrentEpoch();
// Check if poll is finalized
if (currentEpoch >= _pollData.finalizationEpoch) {
revert PollFinalized();
}
// Check epoch must be reached
if (currentEpoch < _pollData.deadlineEpoch) {
revert DeadlineEpochNotReached();
}
// Can only set answer if status is Pending
if (_pollData.status != PollStatus.Pending) {
revert StatusNotPending();
}
_pollData.status = _status;
_pollData.resolutionReason = _reason;
emit AnswerSet(_status, msg.sender, _reason);
}
/**
* @notice Update status during refresh
* @dev Only callable by factory
* @dev Cannot be called after finalization
* @dev Resets status to Pending and clears resolution reason
* @dev Does NOT change finalization epoch - it remains from initial creation
*/
function refreshPoll(bool _isFree) external onlyFactory returns (bool) {
(bool isFinalized, PollStatus status) = getFinalizedStatus();
if (isFinalized) return false;
if (_isFree) return status == PollStatus.Pending;
if (status == PollStatus.Unknown) {
_pollData.status = PollStatus.Pending;
_pollData.resolutionReason = ""; // Clear resolution reason when resetting to Pending
return true;
}
return false;
}
/**
* @notice Start arbitration process, extending the finalization deadline
* @dev Only callable by the arbiter
* @dev Extends finalization epoch by arbitration escalation period (36 hours)
* @dev Can only be called before current finalization epoch
*/
function startArbitration() external onlyArbiter {
uint32 currentEpoch = IPredictionOracle(factory).getCurrentEpoch();
uint32 oldFinalizationEpoch = _pollData.finalizationEpoch;
if (currentEpoch < _pollData.deadlineEpoch) {
revert DeadlineEpochNotReached();
}
// Cannot start arbitration after finalization
if (currentEpoch >= oldFinalizationEpoch) {
revert PollFinalized();
}
uint32 newFinalizationEpoch = currentEpoch +
ARBITRATION_ESCALATION_PERIOD;
_pollData.finalizationEpoch = newFinalizationEpoch;
arbitrationStarted = true;
emit ArbitrationStarted(
msg.sender,
oldFinalizationEpoch,
newFinalizationEpoch
);
}
/**
* @notice Resolve arbitration and set final answer
* @dev Can only be called by the arbiter
* @dev Arbiter can override any status before finalization
* @dev Sets finalization epoch to current epoch, making result immediately final
* @param _status New status to set (Yes, No, or Unknown)
* @param _reason Explanation/reasoning for the arbitration decision
*/
function resolveArbitration(
PollStatus _status,
string calldata _reason
) external onlyArbiter validResolutionStatus(_status) {
uint32 currentEpoch = IPredictionOracle(factory).getCurrentEpoch();
// Check if poll is finalized
if (currentEpoch >= _pollData.finalizationEpoch) {
revert PollFinalized();
}
if (!arbitrationStarted) {
revert ArbitrationNotStarted();
}
// Set the answer
_pollData.status = _status;
_pollData.resolutionReason = _reason;
// Finalize immediately - set finalization epoch to current epoch
_pollData.finalizationEpoch = currentEpoch;
emit AnswerSet(_status, msg.sender, _reason);
}
// ============================================
// VIEW FUNCTIONS
// ============================================
/**
* @notice Get current poll status
* @return Current status
*/
function getStatus() external view returns (PollStatus) {
return _pollData.status;
}
/**
* @notice Get complete poll data
* @return Complete PollData structure
*/
function getPollData() external view returns (PollData memory) {
return _pollData;
}
/**
* @notice Get poll creator address
* @return Creator address
*/
function getCreator() external view returns (address) {
return _pollData.creator;
}
/**
* @notice Get poll arbiter address
* @return Arbiter address
*/
function getArbiter() external view returns (address) {
return _pollData.arbiter;
}
/**
* @notice Get poll type
* @return Poll type/category
*/
function getPollType() external view returns (uint8) {
return _pollData.category;
}
/**
* @notice Get finalization epoch
* @return Finalization epoch number
*/
function getFinalizationEpoch() external view returns (uint32) {
return _pollData.finalizationEpoch;
}
/**
* @notice Get finalized status and current poll status
* @return isFinalized True if poll has reached finalization epoch and cannot be changed
* @return status Current poll status
*/
function getFinalizedStatus()
public
view
returns (bool isFinalized, PollStatus status)
{
uint32 currentEpoch = IPredictionOracle(factory).getCurrentEpoch();
isFinalized = currentEpoch >= _pollData.finalizationEpoch;
status = _pollData.status;
}
/**
* @notice Get deadline epoch
* @return Deadline epoch number
*/
function getDeadlineEpoch() external view returns (uint32) {
return _pollData.deadlineEpoch;
}
/**
* @notice Check if poll matches status and type filters
* @dev Optimized method to check both filters in single call
* @param _statusFilter Bit flags (1=Pending, 2=Yes, 4=No, 8=Unknown, 0=All)
* @param _typeFilter Bit flags for poll types (1<<N for type N, 0=All)
* @return True if poll matches both filters
*/
function matchesFilters(
uint256 _statusFilter,
uint256 _typeFilter
) external view returns (bool) {
// Check status filter (0 means all statuses)
bool statusMatch = _statusFilter == 0 ||
(_statusFilter & (1 << uint256(_pollData.status))) != 0;
// Check type filter (0 means all types)
bool typeMatch = _typeFilter == 0 ||
(_typeFilter & (1 << uint256(_pollData.category))) != 0;
return statusMatch && typeMatch;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
/**
* @title Poll Status Enum
* @notice Shared enumeration for poll status
*/
enum PollStatus {
Pending, // 0 - Initial state, awaiting answer
Yes, // 1 - Positive answer
No, // 2 - Negative answer
Unknown // 3 - Cannot determine answer at check time
}
/**
* @title PollInfo
* @notice Complete poll information for backend processing
*/
struct PollInfo {
address pollAddress;
string question;
string rules;
string[] sources;
uint32 deadlineEpoch; // target epoch when poll result should be resolved
uint32 finalizationEpoch; // Epoch when poll result becomes final and immutable
uint32 checkEpoch; // Epoch when poll should be checked/resolved by oracle operator
address creator;
address arbiter; // Arbiter address who can override poll status
PollStatus status;
uint8 category; // Poll type/category for classification
string resolutionReason; // Explanation/reasoning for the resolution decision
}
/**
* @title IPredictionPoll
* @notice Interface for PredictionPoll contract
*/
interface IPredictionPoll {
/// @notice Poll data structure
struct PollData {
string question; // Question text (max 200 chars)
string rules; // Rules description (max 1000 chars)
string[] sources; // Source URLs (max 3, 200 chars each)
address creator; // Poll creator address
address arbiter; // Arbiter address who can override poll status
PollStatus status; // Current poll status (packed with arbiter and category)
uint8 category; // Poll type/category (0-255, for frontend classification)
uint32 finalizationEpoch; // Epoch when poll result becomes final and immutable
uint32 deadlineEpoch; // target epoch when poll result should be resolved
string resolutionReason; // Explanation/reasoning for the resolution decision
}
// ============================================
// EVENTS
// ============================================
event AnswerSet(PollStatus status, address indexed setter, string reason);
/// @notice Emitted when arbitration is started
/// @param arbiter Address of the arbiter who started arbitration
/// @param oldFinalizationEpoch Previous finalization epoch
/// @param newFinalizationEpoch New finalization epoch after extension
event ArbitrationStarted(
address indexed arbiter,
uint32 oldFinalizationEpoch,
uint32 newFinalizationEpoch
);
// ============================================
// ERRORS
// ============================================
/// @notice Only factory can call this function
error OnlyFactory();
/// @notice Only operator can call this function
error OnlyOperator();
/// @notice Deadline epoch not reached yet
error DeadlineEpochNotReached();
/// @notice Status is not Pending - operator cannot override
error StatusNotPending();
/// @notice Arbitration has not started yet
error ArbitrationNotStarted();
/// @notice Poll has been finalized and cannot be changed
error PollFinalized();
/// @notice Only arbiter can call this function
error OnlyArbiter();
/// @notice Poll already initialized
error AlreadyInitialized();
/// @notice Cannot set status to Pending as resolution
error InvalidResolutionStatus();
// ============================================
// FUNCTIONS
// ============================================
function factory() external view returns (address);
function arbitrationStarted() external view returns (bool);
function ARBITRATION_SUBMISSION_WINDOW() external view returns (uint32);
function ARBITRATION_ESCALATION_PERIOD() external view returns (uint32);
function initialize(
string memory _question,
string memory _rules,
string[] memory _sources,
uint32 _deadlineEpoch,
address _creator,
address _arbiter,
uint8 _category
) external;
function setAnswer(PollStatus _status, string calldata _reason) external;
function resolveArbitration(
PollStatus _status,
string calldata _reason
) external;
function refreshPoll(bool _isFree) external returns (bool);
function getStatus() external view returns (PollStatus);
function getPollData() external view returns (PollData memory);
function getCreator() external view returns (address);
function getArbiter() external view returns (address);
function getPollType() external view returns (uint8);
function getFinalizationEpoch() external view returns (uint32);
function getDeadlineEpoch() external view returns (uint32);
function getFinalizedStatus()
external
view
returns (bool isFinalized, PollStatus status);
function matchesFilters(
uint256 _statusFilter,
uint256 _typeFilter
) external view returns (bool);
function startArbitration() external;
}
/**
* @title IPredictionOracle
* @notice Interface for PredictionOracle contract
*/
interface IPredictionOracle {
// ============================================
// EVENTS
// ============================================
/// @notice Emitted when new poll is created
event PollCreated(
address indexed pollAddress,
address indexed creator,
uint32 deadlineEpoch,
string question
);
/// @notice Emitted when poll check epoch is refreshed
event PollRefreshed(
address indexed pollAddress,
uint32 oldCheckEpoch,
uint32 newCheckEpoch,
bool wasFree
);
/// @notice Emitted when operator is added
event OperatorAdded(address indexed operator);
/// @notice Emitted when operator is removed
event OperatorRemoved(address indexed operator);
/// @notice Emitted when operator gas fee is updated
event OperatorGasFeeUpdated(uint256 newFee);
/// @notice Emitted when protocol fee is updated
event ProtocolFeeUpdated(uint256 newFee);
/// @notice Emitted when poll implementation is updated
event PollImplementationUpdated(
address indexed oldImplementation,
address indexed newImplementation
);
/// @notice Emitted when protocol fees are withdrawn
event ProtocolFeesWithdrawn(address indexed to, uint256 amount);
// ============================================
// ERRORS
// ============================================
error InvalidQuestionLength();
error InvalidRulesLength();
error TooManySources();
error InvalidSourceLength();
error InsufficientPayment();
error NoOperatorsAvailable();
error OperatorAlreadyExists();
error OperatorNotFound();
error CannotRemoveLastOperator();
error CannotRefreshYet();
error InvalidAddress();
error RefreshPaymentRequired();
error PollNotFound();
error WithdrawalFailed();
error InsufficientProtocolFees();
error InvalidTargetTimestamp();
error ForbiddenRefresh();
error ImplementationNotSet();
// ============================================
// POLL MANAGEMENT
// ============================================
function createPoll(
string calldata _question,
string calldata _rules,
string[] calldata _sources,
uint256 _targetTimestamp,
address _arbiter,
uint8 _category
) external payable returns (address pollAddress);
function refreshPollFree(address _pollAddress) external;
function refreshPollPaid(address _pollAddress) external payable;
// ============================================
// MANAGEMENT
// ============================================
function addOperator(address _operator) external;
function removeOperator(address _operator) external;
function getOperators() external view returns (address[] memory);
function getOperatorCount() external view returns (uint256);
function isOperator(address _addr) external view returns (bool);
function setOperatorGasFee(uint256 _fee) external;
function setProtocolFee(uint256 _fee) external;
function setPollImplementation(address _implementation) external;
function pause() external;
function unpause() external;
function withdrawProtocolFees(address payable _to) external;
// ============================================
// VIEW FUNCTIONS
// ============================================
function operatorGasFee() external view returns (uint256);
function protocolFee() external view returns (uint256);
function accumulatedProtocolFees() external view returns (uint256);
function pollImplementation() external view returns (address);
function MAX_QUESTION_LENGTH() external view returns (uint256);
function MAX_RULES_LENGTH() external view returns (uint256);
function MAX_SOURCES() external view returns (uint256);
function MAX_SOURCE_LENGTH() external view returns (uint256);
function PENDING_TIMEOUT_EPOCHS() external view returns (uint256);
function EPOCH_LENGTH() external view returns (uint256);
function getCurrentEpoch() external view returns (uint32);
function getPollsByEpochRange(
uint32 _fromEpoch,
uint32 _toEpoch,
uint256 _statusFilter,
uint256 _typeFilter,
uint256 _maxResults,
uint256 _startIndex
)
external
view
returns (PollInfo[] memory polls, uint32 nextEpoch, uint256 nextIndex);
function getPollsByEpochs(
uint32[] calldata _epochs,
uint256 _statusFilter,
uint256 _typeFilter,
uint256 _maxResults
) external view returns (PollInfo[] memory polls);
function getPollsByCreator(
address _creator,
uint256 _maxResults,
uint256 _offset
) external view returns (PollInfo[] memory polls, bool hasMore);
function getCurrentCheckEpoch(
address _pollAddress
) external view returns (uint32);
function verifyPollAddressExists(
address _pollAddress
) external view returns (bool);
function pollsByCheckEpoch(
uint32 _epoch,
uint256 _index
) external view returns (address);
function pollsByCreator(
address _creator,
uint256 _index
) external view returns (address);
}{
"optimizer": {
"enabled": true,
"runs": 99999
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ArbitrationNotStarted","type":"error"},{"inputs":[],"name":"DeadlineEpochNotReached","type":"error"},{"inputs":[],"name":"InvalidResolutionStatus","type":"error"},{"inputs":[],"name":"OnlyArbiter","type":"error"},{"inputs":[],"name":"OnlyFactory","type":"error"},{"inputs":[],"name":"OnlyOperator","type":"error"},{"inputs":[],"name":"PollFinalized","type":"error"},{"inputs":[],"name":"StatusNotPending","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum PollStatus","name":"status","type":"uint8"},{"indexed":true,"internalType":"address","name":"setter","type":"address"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"AnswerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"arbiter","type":"address"},{"indexed":false,"internalType":"uint32","name":"oldFinalizationEpoch","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newFinalizationEpoch","type":"uint32"}],"name":"ArbitrationStarted","type":"event"},{"inputs":[],"name":"ARBITRATION_ESCALATION_PERIOD","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ARBITRATION_SUBMISSION_WINDOW","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"arbitrationStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getArbiter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCreator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeadlineEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFinalizationEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFinalizedStatus","outputs":[{"internalType":"bool","name":"isFinalized","type":"bool"},{"internalType":"enum PollStatus","name":"status","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPollData","outputs":[{"components":[{"internalType":"string","name":"question","type":"string"},{"internalType":"string","name":"rules","type":"string"},{"internalType":"string[]","name":"sources","type":"string[]"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"arbiter","type":"address"},{"internalType":"enum PollStatus","name":"status","type":"uint8"},{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"uint32","name":"finalizationEpoch","type":"uint32"},{"internalType":"uint32","name":"deadlineEpoch","type":"uint32"},{"internalType":"string","name":"resolutionReason","type":"string"}],"internalType":"struct IPredictionPoll.PollData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPollType","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStatus","outputs":[{"internalType":"enum PollStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_question","type":"string"},{"internalType":"string","name":"_rules","type":"string"},{"internalType":"string[]","name":"_sources","type":"string[]"},{"internalType":"uint32","name":"_deadlineEpoch","type":"uint32"},{"internalType":"address","name":"_creator","type":"address"},{"internalType":"address","name":"_arbiter","type":"address"},{"internalType":"uint8","name":"_category","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_statusFilter","type":"uint256"},{"internalType":"uint256","name":"_typeFilter","type":"uint256"}],"name":"matchesFilters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isFree","type":"bool"}],"name":"refreshPoll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum PollStatus","name":"_status","type":"uint8"},{"internalType":"string","name":"_reason","type":"string"}],"name":"resolveArbitration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum PollStatus","name":"_status","type":"uint8"},{"internalType":"string","name":"_reason","type":"string"}],"name":"setAnswer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startArbitration","outputs":[],"stateMutability":"nonpayable","type":"function"}]Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.