Skip to main content

Security Considerations

Lockdown Mode

To improve user security, the EVC introduces the LOCKDOWN MODE. This mode, which can only be activated by the owner, applies to all their accounts simultaneously. Once activated, the EVC significantly reduces its functionality across the owner's accounts. In this state, the owner is restricted to managing operators and nonces, while operators are restricted to revoke their own permissions. With LOCKDOWN MODE active, neither the owner nor the operators can carry any other operations on the EVC. Notably, calling external smart contracts on behalf of the owner or any of their accounts is prohibited. However, authorized controllers can still control collaterals for the accounts even under lockdown. This mode is particularly useful in emergency situations, such as when a malicious operator has been added or a harmful permit message has been signed, necessitating immediate action to safeguard the user's assets.

Permit Disabled Mode

Another feature to improve user security is the PERMIT DISABLED MODE. This mode, which can only be activated by the owner, applies to all their accounts simultaneously. Once activated, the EVC no longer allows executing permits that were signed by the owner which activated this mode. This mode is particularly useful in emergency situations, such as when a harmful permit message has been signed, necessitating immediate action to safeguard the user's assets.

Authentication by Vaults

Vaults out-source their authentication to the EVC, but are responsible for authorization themselves.

In order to support sub-accounts, operators, and controlCollateral, vaults can be invoked via the EVC's call, batch, or controlCollateral functions, which will then execute the desired operations on the vault. However, the vault will see the EVC as the msg.sender.

When a vault detects that msg.sender is the EVC, it should call back into the EVC to retrieve the current execution context using getCurrentOnBehalfOfAccount. This will tell the vault two things:

  • The onBehalfOfAccount which indicates the account that has been authenticated by the EVC. The vault should consider this the "true" value of msg.sender for authorization purposes.
  • The controllerEnabled which indicates whether or not a vault is currently enabled as a controller for the onBehalfOfAccount account. This information is needed if the vault is performing an operation (such as a borrow) that requires it to be the controller for an account. The caller of getCurrentOnBehalfOfAccount itself passes the vault it is interested in via the controllerToCheck parameter. When controllerToCheck is set to the zero address, the value returned is always false.

EVC Contract Privileges

Because the EVC contract can be made to invoke any arbitrary target contract with any arbitrary calldata, it should never be given any privileges, or hold any native currency or tokens.

The only exception to this is mid-transaction inside of a batch. If one batch item temporarily moves value or tokens into the EVC, but a subsequent batch item moves it out, then as long as no untrusted code runs in between, it is safe. However, moving tokens to the EVC is often unnecessary because tokens can be moved immediately to their final destination with transferFrom and by setting various recipient parameters in contracts.

One exception to this is wrapping ETH into WETH. The deposit method will always credit the caller with the WETH tokens. In this case, the user must transfer the WETH in a subsequent batch item (ideally the batch item immediately after the deposit using call function).

One area where the untrustable EVC address may cause problems is tokens that implement hooks/callbacks, such as ERC-777 tokens. In this case, somebody could install a hook for the EVC as a recipient, and cause inbound transfers to fail, or possibly even be redirected. The EVC doesn't attempt to solve this issue and care should be taken when interacting with contracts which implement hooks/callbacks.

Read-only Re-entrancy

The non-transient storage maintained by the EVC can be read while checks are deferred. In particular, this includes the lists of collaterals and controllers registered for a given account.

This should not result in "read-only re-entrancy" problems, because each individual operation will leave these lists in a consistent state. In particular, for a controller to be released, that controller itself must invoke the release, which typically means the debt has been repaid.

If an external contract attempted to read the collateral or controller states of an account in order to enforce some policy of its own, then it is possible that a user could defer its liquidity check, repay the loan, invoke the external contract, and then re-take the loan. In this case the external contract would see the controller as being released. However, this same action could be done outside of a checks-deferrable call by simply taking a flash loan from an external system, rather than using the checks-deferrable call.