The FVM runtime does not provide much rich, contextual, or historical data about SPs. Even if it did, it would be gas intensive in a L1 smart contract environment to make accurate risk computations on-chain. The ADO is an off-chain data aggregator that allows the pools to receive any real-time and/or historical data on SPs securely and at a very low cost. Each pool can receive its own unique data from the ADO, allowing maximum flexibility.
When an Agent wants to take an action like borrowing funds from a pool, it must first make a request to the ADO to get a credential. The ADO issues a signed credential to the Agent containing the latest snapshot of data concerning the associated Agent and all of its associated miner actors. The Agent then takes this credential to the pool it wants to borrow from, which the pool uses to make a decision about approving the action.
The Signed Credential contains the following data:
struct VerifiableCredential {
/**
* The issuer of the credential
* Must be a valid VC Issuer recognized by the Router
*/
address issuer;
/**
* The id of the agent to which the credential is issued
*/
uint256 subject;
/**
* The epoch in which the credential was signed and issued
*/
uint256 epochIssued;
/**
* The epoch in which the credential expires
* Approximately a 10 minute period of epochs
*/
uint256 epochValidUntil;
/**
* The value change associated with the action
* For instance, in a `borrow` action, `value` would be set to the borrow amount
*/
uint256 value;
/**
* The action associated with the credential
* Actions must correspond to the `msg.sig` of the function where the credential is used
*/
bytes4 action;
/**
* The miner ID that is the target of the action
* Not all actions require a target - for instance, `borrow` does not require a target, since the borrower is the Agent and not a specific miner
* An action like `pullFunds` requires a target, since the Agent is not the miner where funds are being pulled
*/
uint64 target;
/**
* The bytes representation of `AgentData` (listed below)
*/
AgentData claim;
}
struct AgentData {
/**
* The total value of the Agent's assets
* This encompasses:
* - The liquid funds (WFIL + FIL) in the Agent contract
* - The vesting + locked + available funds in each of the Agent's miners
*/
uint256 agentValue;
/**
* Also known as “liquidation value” - collateralValue is 50% of the `agentValue` and is a heuristic for managing available funds + vesting funds + pledged funds - hypothetical termination penalties
*/
uint256 collateralValue;
/**
* The daily fee for sector fault penalties for any of the Agent's faulty sectors
*/
uint256 expectedDailyFaultPenalties;
/**
* The aggregated block rewards expected to be earned by this Agent's miners in the next 24h
*/
uint256 expectedDailyRewards;
/**
* A numerical representation of the Agent's financial risk
* To keep rates fixed, the Infinity Pool hardcodes every SP's
*/
uint256 gcred;
/**
* The aggregated quality adjusted power of all of the Agent's miners
*/
uint256 qaPower;
/**
* The total amount of FIL borrowed by the Agent
*/
uint256 principal;
/**
* The total amount of faulty sectors summed up across all the Agent's miners
*/
uint256 faultySectors;
/**
* The total amount of live sectors summed up across all the Agent's miners
*/
uint256 liveSectors;
/**
* An energy efficiency score computed by the Filecoin Green API
*/
uint256 greenScore;
}
Requester Keys
For security protection, it's important that one Agent cannot request a Signed Credential for another Agent. In order to prevent this from happening, every agent stores an ADORequesterKey address, which is set upon the agent’s creation.
Whoever makes requests to the ADO must hold the private key associated with the ADORequesterKey in order to receive a Signed Credential. Every time a request is made to the ADO for a credential, the requester signs the request as a Json Web Signature and sends it to the ADO. The ADO then validates that the request was signed by the private key holder of ADORequesterKey. This ensures agents can only request signed credentials for themselves.