ITriggerdefined in the
ITrigger.solfile in the
contracts/interface/folder. This abstract trigger contract serves as the base or parent contract for the trigger contract you will write for a protection market.
ITrigger.solabstract trigger contract first.
ITrigger.solfile, there are just a few lines to take note of:
ITrigger.solfile specifies the data types and identifiers for the basic properties of the contract and define the constructor arguments that will be passed in from a deployment script after the contract is deployed on the network.
ITrigger.solfile declares the
isTriggeredstate variable and declares a
TriggerActivated()event to emit if a condition has resulted in the
getPlatformIds()function is used to get an array of platform identifiers, which represent the protocols protected by this trigger contract.
checkTriggerCondition()function defines the logic that determines if the trigger condition for any of the protected protocols has occurred. This function is not implemented in the
ITrigger.solfile. You’ll implement the
checkTriggerCondition()function when you write the trigger contract that inherits from the abstract contract.
checkAndToggleTrigger()function sets the
trueif the condition defined for the
checkTriggerCondition()function is met. This function is implemented in the abstract contract and must not be modified.
ITrigger.solfile, you are ready to start coding your own trigger contract.
MockTrigger.solfile in the developer-guides repository as a starting point. To illustrate what’s involved, we’ll create an empty file and copy and paste portions of the
MockTriggerinto the custom contract.
TestTrigger.solby running the following command:
pragmato specify the compiler version this trigger contract requires. For example:
shouldTogglefunction in the
MockTriggercontract is only used for example purposes in that contract, so we don’t need to include it in our contract skeleton.
constructorarguments of the base contract depend on values that will be passed to the derived contract, they are defined like this in our
checkTriggerCondition()function. For example:
nameis similar to the ERC-20 name property.
symbolis similar to the ERC-20 symbol property.
descriptionof the trigger that describes what the trigger does.
. For a list of platform names and their ID numbers, see Platform identifiers for protocols.
checkTriggerCondition()function that you inherited from the abstract contract. The
checkTriggerCondition()function is where you write the core logic of your trigger contract, specifying the condition that should trigger protection for the protocol(s) defined by
checkTriggerCondition()functions are crucial to ensuring your trigger behaves properly, so read the following section carefully:
checkTriggerCondition()to execute some logic and return
trueif the trigger event has occurred, and return
isTriggeredvariable is through the
checkAndToggleTrigger()function inherited from the abstract contract. This function is implemented to conform to the interface and behavior expected by Cozy protection markets. The
checkAndToggleTrigger()function is called by a protection market to determine the trigger's state.
isTriggeredvariable—separate from the trigger contract's
isTriggeredvariable—which is initialized to
falseand toggled only once, when the trigger's
true. Because it can only be toggled once, to avoid confusion, it's recommended that triggers themselves should also follow the same convention of only allowing "one-way" toggles.
test/MockTrigger.test.ts. This file contains sample implementations of common test cases that you'll want to use when testing your trigger's functionality.
IInterestRateModel. By inheriting this contract, you'll have the correct interface and layout for building and deploying any interest rate model you would like to use.
Comptroller.getCToken(underlying, AddressZero)function. The Comptroller stores a mapping—called
getCToken—that maps an underlying token address to a trigger address to a market address. Money markets use the zero address as their
triggeraddress. If the
Comptroller.getCToken(underlying, AddressZero)check returns the zero address, a money market for the underlying token token does not exist, and you'll have to wait for one to be deployed by governance before continuing. (If you try to deploy without a supported underlying token money market, protection market deployment will revert).
create-protection-market.tsscript shows how to run this check when USDC is the underlying token. If a money market does exist, you can continue to the next step to deploy the final version of your trigger contract.
underlyingis the underlying token's address for this CozyToken market.
triggeris the address of your trigger contract.
interestRateModelis the address of your chosen interest rate model contract.
deployProtectionMarketis an overloaded function, when using ethers.js and the sample scripts to deploy a market, we must specify which syntax we're using.
interestRateModeladdresses. Note that you can change the interest rate model by submitting a governance proposal.
checkAndToggleTrigger()method immediately before every borrow and redeem action. This call is required to mitigate front-running. However, each call incurs a cost in gas for execution and this increases the cost of borrowing and redeeming funds.
pricePerShareas a trigger condition. Under normal operation, this value should only ever increase, though there are expected decreases immediately after each harvest. Therefore we may want to encode a trigger condition that says "if the value of
pricePerSharedrops and remains at some decreased value for X hours, toggle the trigger". This seems logical—if
pricePerSharedecreases, it may have been expected as part of a harvest, so let's wait to see if it recovers before toggling the trigger.
checkAndToggleTrigger()method. This method does not take any inputs, and therefore your trigger's condition cannot be dependent on function inputs or call data. This also means your trigger will not be able to use a Merkle proof to access and validate historical state. If you need access to historical state, you'll need to save data to storage on each call to