Controller Overview
The RCA Controller contract functions as the hub for all RCA shields (of which there may be hundreds). It was created to deal with ecosystem changes that should affect all shields without requiring updates to be made on each shield individually. It also helps the frontend with events launched on each transaction so that monitoring is not necessary on a large number of contracts.
All functions called by shields need to include liquidated amount and proof regardless of whether it will be used so that, in the case of a new liquidation having occurred, that can be checked and updated.
_update
Update is probably the most important function of the controller. Each shield call will initiate an update and it checks whether that shield has been updated since the last time any system-wide variable (withdrawalDelay, APR, liquidation, percent reserved, discount, and treasury). If it hasn’t, it will call the shield to update whatever necessary.
In the case of an APR update, the controller will also call the shield’s update function, which keeps track of any fees owed. The shield will then charge fees correctly for the different amounts of time the old and new APR were enacted. One thing this doesn’t account for is percentReserved and liquidation amounts happening within the same update period, which would otherwise be natively accounted for in the shield’s update. This was a decision made on purpose when weighing the extra complication/cost against the negligible effect it being off may have.
mint
This function checks for updates on any ecosystem variables that may need to be updated on shield, verifies capacity signature, then emits an event.
Verifying capacity signature is the only unique part. We have a capacity oracle (random EOA) that will sign transaction details and the transaction will be allowed if the signature is valid. Because of high gas costs, complications arising from price fluctuations/multiple blockchains, and a relative lack of harm in the worst case scenario, a centralized solution for capacity verification makes the most sense.
redeemRequest
Easy one. Updates like all other shield functions then emits an event, nothing special here.
redeemFinalize
Another easy one. Updates then emits.
purchase
This updates and emits like the others, but also verifies price of the underlying token.
With our Merkle tree setup a price and the proof for the price is input to the initial function on the shield base, that is passed to controller, then it verifies here. If it does not verify correctly, it will revert.
initializeShield
This doesn’t launch contracts as a factory might but just adds them to the shield mapping so that they can launch events and be kept track of, then initializes the shield with some variables so that we don’t have to individually. If a shield is to be cancelled, it being able to interact with controller should not be changed as that would block people from withdrawing. Cancelling a shield can be purely an off-chain decision by the DAO to simply agree, “we’re not gonna payout hacks on this anymore.”