New implementation for Controller

Controller contract in crvUSD (the one which handles borrows and returns) has several minor bugfixes. They are not affecting any funds, however make life of frontend devs better. Full diff of the changes can be found on GitHub. The new implementation doesn’t (and cannot) be replaced in existing markets

Brief description of changes:

  • max_borrowable() did not take into account any existing debt, not distinguishing between creating a new loan and borrowing more. As a result, calculation for borrow_more() can unnecessarily bump into debt ceiling. An optional argument for passing existing debt of a user is added to the method (L463, L489).
  • repay_extended() can use callbacks to sell collateral to repay (when deleveraging). That, however, was not correctly passed into Repay event. And although there is a UserState event which can be used as a workaround, it is appropriate to fix this behavior. The remains of collateral returned by the callback are subtracted from initial collateral xy[1] instead of zeroing it for logging in L889.
  • repay() doesn’t have to be payable because it never receives ETH (L751).
  • The changes above could not fit into the 24K bytecode size limit. So few more changes had to be introduced to compress the bytecode - removing temporary variables when they are used only once, replacing safe math with unsafe when necessary checks are done anyway beforehand in the code.

Deployment address

Deployment is done at

How to verify

Etherscan doesn’t yet all allow to verify blueprints. However, the deployment script allows to do such a verification:

$ ape run scripts/ verify --network ethereum:mainnet:alchemy
Blueprints match the ones deployed on chain