UMA Trigger Factory

The UMATriggerFactory deploys an automated trigger contract, which moves into a TRIGGERED state if the UMA Optimistic Oracle answers "YES" to a YES-OR-NO query, e.g., "Was protocol ABCD hacked on or after block 42." Since queries are user-provided, UMA Triggers can offer protection for any arbitrary event.

Determine Trigger Parameters

The UMATriggerFactory's deployTrigger function can be used to deploy a new UMA trigger:

struct TriggerMetadata {
  // The name that should be used for safety modules that use the trigger.
  string name;
  // A human-readable description of the trigger.
  string description;
  // The URI of a logo image to represent the trigger.
  string logoURI;
  // Any extra metadata for the trigger.
  string extraData;
}

/// @notice Call this function to deploy a UMATrigger.
/// @param _query The query that the trigger will send to the UMA Optimistic
/// Oracle for evaluation.
/// @param _rewardToken The token used to pay the reward to users that propose
/// answers to the query. The reward token must be approved by UMA governance.
/// Approved tokens can be found with the UMA AddressWhitelist contract on each
/// chain supported by UMA.
/// @param _rewardAmount The amount of rewardToken that will be paid as a
/// reward to anyone who proposes an answer to the query.
/// @param _refundRecipient Default address that will recieve any leftover
/// rewards at UMA query settlement time.
/// @param _bondAmount The amount of `rewardToken` that must be staked by a
/// user wanting to propose or dispute an answer to the query. See UMA's price
/// dispute workflow for more information. It's recommended that the bond
/// amount be a significant value to deter addresses from proposing malicious,
/// false, or otherwise self-interested answers to the query.
/// @param _proposalDisputeWindow The window of time in seconds within which a
/// proposed answer may be disputed. See UMA's "customLiveness" setting for
/// more information. It's recommended that the dispute window be fairly long
/// (12-24 hours), given the difficulty of assessing expected queries (e.g.
/// "Was protocol ABCD hacked") and the amount of funds potentially at stake.
/// @param _metadata See TriggerMetadata for more info.
function deployTrigger(
    string memory _query,
    IERC20 _rewardToken,
    uint256 _rewardAmount,
    address _refundRecipient,
    uint256 _bondAmount,
    uint256 _proposalDisputeWindow,
    TriggerMetadata memory _metadata
) external returns (UMATrigger);

For more information on the expected format/structure of query strings, see the official UMIP-107 documentation.

If you're looking for inspiration or examples, existing queries can be viewed here.

Deploy Trigger

Once you've decided on the parameters for the trigger, you can deploy it as follows:

// Define your parameters.
string memory _query;
IERC20 _rewardToken;
uint256 _rewardAmount;
address _refundRecipient;
uint256 _bondAmount;
uint256 _proposalDisputeWindow;
string _name;
string _description;
string _logoURI;
string _extraData;
address _umaTriggerFactoryAddress;

// Instantiate the trigger factory.
UMATriggerFactory _factory = UMATriggerFactory(_umaTriggerFactoryAddress);

// Check to see if a trigger has already been deployed with your desired configs.
address _availableTrigger = _factory.findAvailableTrigger(
  _query,
  _rewardToken,
  _rewardAmount,
  _refundRecipient,
  _bondAmount,
  _proposalDisputeWindow
);

if (_availableTrigger == address(0)) {

  // There is no available trigger with your desired configuration. We will
  // have to deploy a new one! First, we approve the factory to transfer the
  // reward for us.
  rewardToken.approve(address(_factory), _rewardAmount);

  // Then we deploy the trigger.
  _availableTrigger = address(
    _factory.deployTrigger(
      _query,
      _rewardToken,
      _rewardAmount,
      _refundRecipient,
      _bondAmount,
      _proposalDisputeWindow,
      TriggerMetadata(_name, _description, _logoURI, _extraData)
    )
  );
  emit log("New trigger deployed \o/");

} else {

  // A trigger exactly like the one you wanted already exists!
  // Since triggers can be re-used, there's no need to deploy a new one.
  emit log("Found existing trigger with specified configs");

}

emit log_named_address(
  "Your trigger is available at this address:",
  _availableTrigger
);

Note:

  • The reward token is used to incentivize users to answer the query correctly. The reward token must be whitelisted by UMA; attempts to deploy a trigger with an unsupported token will revert.

  • The reward amount must be pre-approved for the factory to spend; otherwise, the deploy will revert.

For the addresses of factories deployed to various chains, see Contracts Deployment Registry.

Last updated