Gearbox Core
As illustrated in Architecture, Gearbox Core is a service layer which provides unified services including six component: AddressProvider, PoolRegistry, ACL, WETHGateway, AccountFactory, PriceOracle.
These services are provided by serveal smart contracts: AddressProvider, AccountFactory, ContractsRegister, WETHGateway, ACL&ACL Trait, DataCompressor and Oracles.
In this section we'll dig deeper into these smart contracts.
AddressProvider
AddressProvider keeps addresses of core contracts which is used for smart contract address discovery. Continuing from the simple example we built previously, we can start to use other functionality of AddressProvider.
note
We assume that you're running a Mainnet fork by now. Please refer to the last step in Gearbox SDK and Mainnet Forking for instructions.
Create a new source file scripts/gearbox-discovery.ts and query the latest vesion of Gearbox Contract.
Let's take a look at the code. We can see that the code queries the address of contracts register contractsRegisterAddress
from addressProvider
and gets the list of pools and credit managers from contractsRegister
. After quering the address of AccountFactory from AddressProvider and connecting to AccountFactory, we can get the accounts stats from AccountFactory
.
scripts/gearbox-discovery.tsjsx
async function main() {// If you don't specify a //url//, Ethers connects to the default// (i.e. ``http:/\/localhost:8545``)const provider = new ethers.providers.JsonRpcProvider();// The address of Gearbox's AddressProvider contractconst addressProvider = AddressProvider__factory.connect(ADDRESS_PROVIDER_ADDRESS, provider);// Start to query AddressProvider//// Get the latest version of Gearbox's contractsconst version = await addressProvider.version();console.log("version of Gearbox Contract is ", version);// Get ContractsRegisterconst contractsRegisterAddress = await addressProvider.getContractsRegister();console.log("ContractsRegisterAddress is ", contractsRegisterAddress);//******************** ContractsRegister ********************const contractsRegister = ContractsRegister__factory.connect(contractsRegisterAddress, provider);const poolList = await contractsRegister.getPools();console.log("Pool List: ", poolList);const creditManagerList = await contractsRegister.getCreditManagers();console.log("Credit Manager List: ", creditManagerList);//******************** ContractsRegister ********************// Get ACLconst ACLAddress = await addressProvider.getACL();console.log("ACL is ", ACLAddress);// Get PriceOracleconst priceOracleAddress = await addressProvider.getPriceOracle();console.log("PriceOracle is ", priceOracleAddress);// Get AccountFactoryconst accountFactoryAddress = await addressProvider.getAccountFactory();console.log("AccountFactory is ", accountFactoryAddress);//******************** AccountFactory ********************const accountFactory = AccountFactory__factory.connect(accountFactoryAddress, provider);const countCreditAccount = await accountFactory.countCreditAccounts();console.log("Count of Credit Accounts: ", countCreditAccount);const countCreditAccountInStock = await accountFactory.countCreditAccountsInStock();console.log("Count of Credit Accounts InStock: ", countCreditAccountInStock);//******************** AccountFactory ********************// Get DataCompressorconst dataCompressorAddress = await addressProvider.getDataCompressor();console.log("DataCompressor is ", dataCompressorAddress);// Get WETH Tokenconst WETHGateway = await addressProvider.getWETHGateway();console.log("WETHGateway is ", WETHGateway);}
scripts/gearbox-discovery.tsjsx
async function main() {// If you don't specify a //url//, Ethers connects to the default// (i.e. ``http:/\/localhost:8545``)const provider = new ethers.providers.JsonRpcProvider();// The address of Gearbox's AddressProvider contractconst addressProvider = AddressProvider__factory.connect(ADDRESS_PROVIDER_ADDRESS, provider);// Start to query AddressProvider//// Get the latest version of Gearbox's contractsconst version = await addressProvider.version();console.log("version of Gearbox Contract is ", version);// Get ContractsRegisterconst contractsRegisterAddress = await addressProvider.getContractsRegister();console.log("ContractsRegisterAddress is ", contractsRegisterAddress);//******************** ContractsRegister ********************const contractsRegister = ContractsRegister__factory.connect(contractsRegisterAddress, provider);const poolList = await contractsRegister.getPools();console.log("Pool List: ", poolList);const creditManagerList = await contractsRegister.getCreditManagers();console.log("Credit Manager List: ", creditManagerList);//******************** ContractsRegister ********************// Get ACLconst ACLAddress = await addressProvider.getACL();console.log("ACL is ", ACLAddress);// Get PriceOracleconst priceOracleAddress = await addressProvider.getPriceOracle();console.log("PriceOracle is ", priceOracleAddress);// Get AccountFactoryconst accountFactoryAddress = await addressProvider.getAccountFactory();console.log("AccountFactory is ", accountFactoryAddress);//******************** AccountFactory ********************const accountFactory = AccountFactory__factory.connect(accountFactoryAddress, provider);const countCreditAccount = await accountFactory.countCreditAccounts();console.log("Count of Credit Accounts: ", countCreditAccount);const countCreditAccountInStock = await accountFactory.countCreditAccountsInStock();console.log("Count of Credit Accounts InStock: ", countCreditAccountInStock);//******************** AccountFactory ********************// Get DataCompressorconst dataCompressorAddress = await addressProvider.getDataCompressor();console.log("DataCompressor is ", dataCompressorAddress);// Get WETH Tokenconst WETHGateway = await addressProvider.getWETHGateway();console.log("WETHGateway is ", WETHGateway);}
Run this code by executing this shell command:
bash
npx hardhat run scripts/gearbox-discovery.ts
bash
npx hardhat run scripts/gearbox-discovery.ts
This should produce the following output:
·-----------------|-------------· | Contract Name · Size (KB) │ ·-----------------|-------------· version of Gearbox Contract is BigNumber { value: "1" } ContractsRegister is 0xA50d4E7D8946a7c90652339CDBd262c375d54D99 ACL is 0x523dA3a8961E4dD4f6206DBf7E6c749f51796bb3 PriceOracle is 0x0e74a08443c5E39108520589176Ac12EF65AB080 AccountFactory is 0x444CD42BaEdDEB707eeD823f7177b9ABcC779C04 DataCompressor is 0x0050b1ABD1DD2D9b01ce954E663ff3DbCa9193B1 WETHGateway is 0x4F952c4C5415B2609899AbDC2F8F352F600d14D6
·-----------------|-------------· | Contract Name · Size (KB) │ ·-----------------|-------------· version of Gearbox Contract is BigNumber { value: "1" } ContractsRegister is 0xA50d4E7D8946a7c90652339CDBd262c375d54D99 ACL is 0x523dA3a8961E4dD4f6206DBf7E6c749f51796bb3 PriceOracle is 0x0e74a08443c5E39108520589176Ac12EF65AB080 AccountFactory is 0x444CD42BaEdDEB707eeD823f7177b9ABcC779C04 DataCompressor is 0x0050b1ABD1DD2D9b01ce954E663ff3DbCa9193B1 WETHGateway is 0x4F952c4C5415B2609899AbDC2F8F352F600d14D6
ContractsRegister
ContractsRegister maintains all the pools and credit managers.
The ContractsRegister
can be retrieved by querying AddressProvider
.
ContractsRegister
exports two functions that we can use, getpools
and getCreditManagers
.
The gearbox-sdk
allows us to import ContractsRegister__factory
to perform these operations.
We'll add some code in scripts/gearbox-discovery.ts
between ContractsRegister
and ACL
to use this functionality.
scripts/gearbox-discovery.tsjsx
...// Get ContractsRegisterconst contractsRegisterAddress = await addressProvider.getContractsRegister();console.log("ContractsRegisterAddress is ", contractsRegisterAddress);//******************** ContractsRegister ********************const contractsRegister = ContractsRegister__factory.connect(contractsRegisterAddress, provider);const poolList = await contractsRegister.getPools();console.log("Pool List: ", poolList);const creditManagerList = await contractsRegister.getCreditManagers();console.log("Credit Manager List: ", creditManagerList);//******************** ContractsRegister ********************...
scripts/gearbox-discovery.tsjsx
...// Get ContractsRegisterconst contractsRegisterAddress = await addressProvider.getContractsRegister();console.log("ContractsRegisterAddress is ", contractsRegisterAddress);//******************** ContractsRegister ********************const contractsRegister = ContractsRegister__factory.connect(contractsRegisterAddress, provider);const poolList = await contractsRegister.getPools();console.log("Pool List: ", poolList);const creditManagerList = await contractsRegister.getCreditManagers();console.log("Credit Manager List: ", creditManagerList);//******************** ContractsRegister ********************...
Run this code by executing this shell command:
bash
npx hardhat run scripts/gearbox-discovery.ts
bash
npx hardhat run scripts/gearbox-discovery.ts
This should produce the following output, where we can see the pool list and credit account list:
·-----------------|-------------· | Contract Name · Size (KB) │ ·-----------------|-------------· version of Gearbox Contract is BigNumber { value: "1" } ContractsRegister is 0xA50d4E7D8946a7c90652339CDBd262c375d54D99 Pool List: [ '0x24946bCbBd028D5ABb62ad9B635EB1b1a67AF668', '0x86130bDD69143D8a4E5fc50bf4323D48049E98E4', '0xB03670c20F87f2169A7c4eBE35746007e9575901', '0xB2A015c71c17bCAC6af36645DEad8c572bA08A08' ] Credit Manager List: [ '0x777E23A2AcB2fCbB35f6ccF98272d03C722Ba6EB', '0x2664cc24CBAd28749B3Dd6fC97A6B402484De527', '0x968f9a68a98819E2e6Bb910466e191A7b6cf02F0', '0xC38478B0A4bAFE964C3526EEFF534d70E1E09017' ] ACL is 0x523dA3a8961E4dD4f6206DBf7E6c749f51796bb3 PriceOracle is 0x0e74a08443c5E39108520589176Ac12EF65AB080 AccountFactory is 0x444CD42BaEdDEB707eeD823f7177b9ABcC779C04 DataCompressor is 0x0050b1ABD1DD2D9b01ce954E663ff3DbCa9193B1 WETHGateway is 0x4F952c4C5415B2609899AbDC2F8F352F600d14D6
·-----------------|-------------· | Contract Name · Size (KB) │ ·-----------------|-------------· version of Gearbox Contract is BigNumber { value: "1" } ContractsRegister is 0xA50d4E7D8946a7c90652339CDBd262c375d54D99 Pool List: [ '0x24946bCbBd028D5ABb62ad9B635EB1b1a67AF668', '0x86130bDD69143D8a4E5fc50bf4323D48049E98E4', '0xB03670c20F87f2169A7c4eBE35746007e9575901', '0xB2A015c71c17bCAC6af36645DEad8c572bA08A08' ] Credit Manager List: [ '0x777E23A2AcB2fCbB35f6ccF98272d03C722Ba6EB', '0x2664cc24CBAd28749B3Dd6fC97A6B402484De527', '0x968f9a68a98819E2e6Bb910466e191A7b6cf02F0', '0xC38478B0A4bAFE964C3526EEFF534d70E1E09017' ] ACL is 0x523dA3a8961E4dD4f6206DBf7E6c749f51796bb3 PriceOracle is 0x0e74a08443c5E39108520589176Ac12EF65AB080 AccountFactory is 0x444CD42BaEdDEB707eeD823f7177b9ABcC779C04 DataCompressor is 0x0050b1ABD1DD2D9b01ce954E663ff3DbCa9193B1 WETHGateway is 0x4F952c4C5415B2609899AbDC2F8F352F600d14D6
ACL
ACL keeps permissions for different addresses. For the moment, it keeps 2 different roles:
- PausableAdmin: Can pause and unpause contracts
- Configurator: Can configure contracts parameters
This part is mainly related to security and we can see from this article how it will be used.
WETHGateway
ETH <=> WETH wrapper for Gearbox protocol. It implements IWETHGateway interface.
AccountFactory
Reusable Credit Accounts are one of the main innovations of Gearbox. Users rent a predeployed credit account smart contract from the protocol, and thus save on deployment gas costs.
Each time, when a user opens a credit account in Gearbox protocol, CreditManager
takes a pre-deployed credit account contract from the AccountFactory
and when the user closes the credit account, CreditManager
returns it.
If AccountFactory
has no pre-deployed contracts, it clones it using https://eips.ethereum.org/EIPS/eip-1167
Advantages
Gas efficiency: This solution is much more gas-efficient, because it doesn't require creating a new contract each time and has minimal operational overhead.
Hacker-proof: Contract funds are allocated on isolated contracts which makes a possible attack more complex and less economically reasonable. Furthermore, the gearbox protocol uses anomaly detection to pause contracts and keep funds safe if suspicious behavior is found. User can protect their funds by splitting them between a few virtual accounts, and it makes the attack less economic reasonable.
Balance transparency on Etherscan: Trader or farmer could check all their transactions on Etherscan if they know at which block they start and finish virtual account renting.
Ethereum network ecology: It generates significantly less data in comparison with deployment credit contract for each new customer, and consume significantly less gas than keeping all balances in one place. As result it makes less impact on Ethereum infrastructure.
Implementation
AccountFactory
supplies a Credit Account to CreditManager
on demand and keeps them when they are not used.
The account factory uses a list to keep credit accounts and two pointers: head and tail.
When a user open a credit account, CreditManager
will ask AccountFactory
for a virtual account by calling function takeCreditAccount
which takes one CreditAccount
from the head pointer. When returns a CreditAccount
, AccountFactory
adds it to the tail.
DataCompressor
DataCompressor
collects data from different contracts in order to transmit this information in an aggregated way to a dApp.
Let's list some main function in DataCompressor
:
getCreditAccountList(address borrower)
for getting the list ofCreditAccountData
s of a specified borrowergetCreditAccountData(address _creditManager, address borrower)
for gettingCreditAccountData
of a specified borrower under a specifiedCreditManager
getCreditAccountDataExtended(address creditManager, address borrower)
for gettingCreditAccountDataExtended
of a specified borrower under a specifiedCreditManager
,CreditAccountDataExtended
is the extension types ofCreditAccountData
, you can checkTypes.sol
for more details.getCreditManagersList(address borrower)
for getting list ofCreditManagerData
of a specified borrowergetPoolsList()
for getting list ofPoolData
info
Datacompressor has an unstable API
Because most of the functions need a borrower
address as parameter, we are unable to demo its output. You can use your (test) wallet to open an account and try to use it yourself.