Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions contracts/EulerLimitsHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface EulerPool {
struct Params {
// Entities
address vault0;
address vault1;
address eulerAccount;
// Curve
uint112 equilibriumReserve0;
uint112 equilibriumReserve1;
uint256 priceX;
uint256 priceY;
uint256 concentrationX;
uint256 concentrationY;
// Fees
uint256 fee;
uint256 protocolFee;
address protocolFeeRecipient;
}

function getParams() external view returns (Params memory);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 status);
}

interface IEVault {
function debtOf(address account) external view returns (uint256);
function maxDeposit(address account) external view returns (uint256);
function cash() external view returns (uint256);
function caps() external view returns (uint256, uint16);
function totalBorrows() external view returns (uint256);
function convertToAssets(uint256 shares) external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
}

contract EulerLimitsHelper {
uint256 private constant _MAX_U112 = type(uint112).max;

function calcLimits(EulerPool _pool) external view returns (uint256, uint256, uint256, uint256) {
EulerPool.Params memory params = _pool.getParams();
(uint112 reserve0, uint112 reserve1,) = _pool.getReserves();

IEVault vault0 = IEVault(params.vault0);
IEVault vault1 = IEVault(params.vault1);
return (_calcInLimit(params.eulerAccount, vault0), _calcInLimit(params.eulerAccount, vault1),
_calcOutLimit(params.eulerAccount, vault0, reserve0), _calcOutLimit(params.eulerAccount, vault1, reserve1));
}

function _calcInLimit(address eulerAccount, IEVault vault) internal view returns (uint256) {
uint256 maxDeposit = vault.debtOf(eulerAccount) + vault.maxDeposit(eulerAccount);
return maxDeposit < _MAX_U112 ? maxDeposit : _MAX_U112;
}

function _calcOutLimit(address eulerAccount, IEVault vault, uint112 reserveLimit) internal view returns (uint256) {
uint256 outLimit = _MAX_U112;

// Reserve limit
if (reserveLimit < outLimit) {
outLimit = reserveLimit;
}

// Cash and borrow cap logic
{
uint256 cash = vault.cash();
if (cash < outLimit) {
outLimit = cash;
}

(, uint16 borrowCap) = vault.caps();
uint256 maxWithdraw = _decodeCap(uint256(borrowCap));
maxWithdraw = vault.totalBorrows() > maxWithdraw ? 0 : maxWithdraw - vault.totalBorrows();
if (maxWithdraw < outLimit) {
maxWithdraw += vault.convertToAssets(vault.balanceOf(eulerAccount));
if (maxWithdraw < outLimit) outLimit = maxWithdraw;
}
}

return outLimit;
}

function _decodeCap(uint256 amountCap) internal pure returns (uint256) {
if (amountCap == 0) return type(uint256).max;

unchecked {
// Cannot overflow because this is less than 2**256:
// 10**(2**6 - 1) * (2**10 - 1) = 1.023e+66
return 10 ** (amountCap & 63) * (amountCap >> 6) / 100;
}
}
}
75 changes: 75 additions & 0 deletions deployments/mainnet/EulerLimitsHelper.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"address": "0xC6c5782fF1f5B8C6e58db0C2Deb6E29C076Aa59E",
"abi": [
{
"inputs": [
{
"internalType": "contract EulerPool",
"name": "_pool",
"type": "address"
}
],
"name": "calcLimits",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
],
"transactionHash": "0x5b726bcec76fde578669d20c983e67cb474d43e565d6035a3dc06c2edca369c7",
"receipt": {
"to": null,
"from": "0x56E44874F624EbDE6efCc783eFD685f0FBDC6dcF",
"contractAddress": "0xC6c5782fF1f5B8C6e58db0C2Deb6E29C076Aa59E",
"transactionIndex": 211,
"gasUsed": "539385",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"blockHash": "0x510f4dda68d20dfa92374c59d2134a63eb7f84cbfdee8f93a5074f1928342fa1",
"transactionHash": "0x5b726bcec76fde578669d20c983e67cb474d43e565d6035a3dc06c2edca369c7",
"logs": [],
"blockNumber": 23618332,
"cumulativeGasUsed": "23293329",
"status": 1,
"byzantium": true
},
"args": [],
"numDeployments": 1,
"solcInputHash": "5413c6519d55f07f47211190948b7958",
"metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract EulerPool\",\"name\":\"_pool\",\"type\":\"address\"}],\"name\":\"calcLimits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/EulerLimitsHelper.sol\":\"EulerLimitsHelper\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/EulerLimitsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\ninterface EulerPool {\\n struct Params {\\n // Entities\\n address vault0;\\n address vault1;\\n address eulerAccount;\\n // Curve\\n uint112 equilibriumReserve0;\\n uint112 equilibriumReserve1;\\n uint256 priceX;\\n uint256 priceY;\\n uint256 concentrationX;\\n uint256 concentrationY;\\n // Fees\\n uint256 fee;\\n uint256 protocolFee;\\n address protocolFeeRecipient;\\n }\\n\\n function getParams() external view returns (Params memory);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 status);\\n}\\n\\ninterface IEVault {\\n function debtOf(address account) external view returns (uint256);\\n function maxDeposit(address account) external view returns (uint256);\\n function cash() external view returns (uint256);\\n function caps() external view returns (uint256, uint16);\\n function totalBorrows() external view returns (uint256);\\n function convertToAssets(uint256 shares) external view returns (uint256);\\n function balanceOf(address account) external view returns (uint256);\\n}\\n\\ncontract EulerLimitsHelper {\\n uint256 private constant _MAX_U112 = type(uint112).max;\\n\\n function calcLimits(EulerPool _pool) external view returns (uint256, uint256, uint256, uint256) {\\n EulerPool.Params memory params = _pool.getParams();\\n (uint112 reserve0, uint112 reserve1,) = _pool.getReserves();\\n\\n IEVault vault0 = IEVault(params.vault0);\\n IEVault vault1 = IEVault(params.vault1);\\n return (_calcInLimit(params.eulerAccount, vault0), _calcInLimit(params.eulerAccount, vault1),\\n _calcOutLimit(params.eulerAccount, vault0, reserve0), _calcOutLimit(params.eulerAccount, vault1, reserve1));\\n }\\n\\n function _calcInLimit(address eulerAccount, IEVault vault) internal view returns (uint256) {\\n uint256 maxDeposit = vault.debtOf(eulerAccount) + vault.maxDeposit(eulerAccount);\\n return maxDeposit < _MAX_U112 ? maxDeposit : _MAX_U112;\\n }\\n\\n function _calcOutLimit(address eulerAccount, IEVault vault, uint112 reserveLimit) internal view returns (uint256) {\\n uint256 outLimit = _MAX_U112;\\n\\n // Reserve limit\\n if (reserveLimit < outLimit) {\\n outLimit = reserveLimit;\\n }\\n\\n // Cash and borrow cap logic\\n {\\n uint256 cash = vault.cash();\\n if (cash < outLimit) {\\n outLimit = cash;\\n }\\n\\n (, uint16 borrowCap) = vault.caps();\\n uint256 maxWithdraw = _decodeCap(uint256(borrowCap));\\n maxWithdraw = vault.totalBorrows() > maxWithdraw ? 0 : maxWithdraw - vault.totalBorrows();\\n if (maxWithdraw < outLimit) {\\n maxWithdraw += vault.convertToAssets(vault.balanceOf(eulerAccount));\\n if (maxWithdraw < outLimit) outLimit = maxWithdraw;\\n }\\n }\\n\\n return outLimit;\\n }\\n\\n function _decodeCap(uint256 amountCap) internal pure returns (uint256) {\\n if (amountCap == 0) return type(uint256).max;\\n\\n unchecked {\\n // Cannot overflow because this is less than 2**256:\\n // 10**(2**6 - 1) * (2**10 - 1) = 1.023e+66\\n return 10 ** (amountCap & 63) * (amountCap >> 6) / 100;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc4b65c14c1f90a6d264b0fbdf09da780af6c21afe06f8ca12ef067618919d9b0\",\"license\":\"MIT\"}},\"version\":1}",
"bytecode": "0x60808060405234610016576108da908161001b8239f35b5f80fdfe60806040908082526004361015610014575f80fd5b5f3560e01c63e615c0fa14610027575f80fd5b346101a7576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a7576004359273ffffffffffffffffffffffffffffffffffffffff908185168095036101a7577f5e615a6b000000000000000000000000000000000000000000000000000000008452610180938481600481895afa9485156102d2575f956101bd575b50506060600494958251958680927f0902f1ac0000000000000000000000000000000000000000000000000000000082525afa80156101b3575f945f91610154575b509461014160809684835116928486888301511691019561013961012186838a5116610393565b9961012f84848b5116610393565b96838a51166104d0565b9651166104d0565b9382519586528501528301526060820152f35b9450506060843d6060116101ab575b81610170606093836102dc565b810103126101a7576101818461033e565b948161018e85870161033e565b95015163ffffffff8116036101a75794936101416100fa565b5f80fd5b3d9150610163565b50513d5f823e3d90fd5b8181809397503d83116102cb575b6101d581836102dc565b810103126101a75781519081019080821067ffffffffffffffff83111761029e5760049560609284526102078161031d565b825261021486820161031d565b8683015261022384820161031d565b8483015261023283820161033e565b838301526102426080820161033e565b608083015260a081015160a083015260c081015160c083015260e081015160e083015261010080820151908301526101208082015190830152610140808201519083015261029461016080920161031d565b90820152946100b8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b503d6101cb565b82513d5f823e3d90fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761029e57604052565b519073ffffffffffffffffffffffffffffffffffffffff821682036101a757565b51906dffffffffffffffffffffffffffff821682036101a757565b9190820180921161036657565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff80921691604051917fd283e75f000000000000000000000000000000000000000000000000000000008352168060048301526020918281602481875afa9182156104945783915f9361049f575b506024604051809681937f402d267d00000000000000000000000000000000000000000000000000000000835260048301525afa918215610494575f92610462575b506104429250610359565b6dffffffffffffffffffffffffffff8082101561045d575090565b905090565b90915082813d831161048d575b61047981836102dc565b810103126101a7576104429151905f610437565b503d61046f565b6040513d5f823e3d90fd5b8281939294503d83116104c9575b6104b781836102dc565b810103126101a757829051915f6103f5565b503d6104ad565b6dffffffffffffffffffffffffffff80931683811061085e575b5073ffffffffffffffffffffffffffffffffffffffff809216916040918251907f961be391000000000000000000000000000000000000000000000000000000008252602091600490838183818a5afa90811561081f575f91610831575b50878110610829575b5084517f18e22d98000000000000000000000000000000000000000000000000000000008152858183818a5afa90811561081f575f916107e3575b5061ffff61059a9116610866565b85517f47bd37180000000000000000000000000000000000000000000000000000000090818152858185818c5afa9081156107d9579083915f916107a8575b50111561071b5750505f935b8785106105f7575b5050505050505090565b8551927f70a0823100000000000000000000000000000000000000000000000000000000845216818301528282602481895afa91821561071157908392915f926106df575b50602490865197889384927f07a2d13a0000000000000000000000000000000000000000000000000000000084528301525afa9283156106d657505f926106a4575b506106899250610359565b81811061069c575b8080808080806105ed565b90505f610691565b90915082813d83116106cf575b6106bb81836102dc565b810103126101a7576106899151905f61067e565b503d6106b1565b513d5f823e3d90fd5b8381949293503d831161070a575b6106f781836102dc565b810103126101a75790518291602461063c565b503d6106ed565b85513d5f823e3d90fd5b8651908152848184818b5afa90811561079e575f91610771575b50810390811161074557936105e5565b6011827f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b90508481813d8311610797575b61078881836102dc565b810103126101a757515f610735565b503d61077e565b87513d5f823e3d90fd5b809250878092503d83116107d2575b6107c181836102dc565b810103126101a7578290515f6105d9565b503d6107b7565b88513d5f823e3d90fd5b90508581813d8311610818575b6107fa81836102dc565b810103126101a75783015161ffff811681036101a75761ffff61058c565b503d6107f0565b86513d5f823e3d90fd5b96505f610551565b90508381813d8311610857575b61084881836102dc565b810103126101a757515f610548565b503d61083e565b92505f6104ea565b801561087f5780603f60649260061c9116600a0a020490565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9056fea26469706673582212206b8eba4352e1a0c445b213ca7abe70e45dfe90db7a53a228294997808554b6dc64736f6c63430008170033",
"deployedBytecode": "0x60806040908082526004361015610014575f80fd5b5f3560e01c63e615c0fa14610027575f80fd5b346101a7576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101a7576004359273ffffffffffffffffffffffffffffffffffffffff908185168095036101a7577f5e615a6b000000000000000000000000000000000000000000000000000000008452610180938481600481895afa9485156102d2575f956101bd575b50506060600494958251958680927f0902f1ac0000000000000000000000000000000000000000000000000000000082525afa80156101b3575f945f91610154575b509461014160809684835116928486888301511691019561013961012186838a5116610393565b9961012f84848b5116610393565b96838a51166104d0565b9651166104d0565b9382519586528501528301526060820152f35b9450506060843d6060116101ab575b81610170606093836102dc565b810103126101a7576101818461033e565b948161018e85870161033e565b95015163ffffffff8116036101a75794936101416100fa565b5f80fd5b3d9150610163565b50513d5f823e3d90fd5b8181809397503d83116102cb575b6101d581836102dc565b810103126101a75781519081019080821067ffffffffffffffff83111761029e5760049560609284526102078161031d565b825261021486820161031d565b8683015261022384820161031d565b8483015261023283820161033e565b838301526102426080820161033e565b608083015260a081015160a083015260c081015160c083015260e081015160e083015261010080820151908301526101208082015190830152610140808201519083015261029461016080920161031d565b90820152946100b8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b503d6101cb565b82513d5f823e3d90fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761029e57604052565b519073ffffffffffffffffffffffffffffffffffffffff821682036101a757565b51906dffffffffffffffffffffffffffff821682036101a757565b9190820180921161036657565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b73ffffffffffffffffffffffffffffffffffffffff80921691604051917fd283e75f000000000000000000000000000000000000000000000000000000008352168060048301526020918281602481875afa9182156104945783915f9361049f575b506024604051809681937f402d267d00000000000000000000000000000000000000000000000000000000835260048301525afa918215610494575f92610462575b506104429250610359565b6dffffffffffffffffffffffffffff8082101561045d575090565b905090565b90915082813d831161048d575b61047981836102dc565b810103126101a7576104429151905f610437565b503d61046f565b6040513d5f823e3d90fd5b8281939294503d83116104c9575b6104b781836102dc565b810103126101a757829051915f6103f5565b503d6104ad565b6dffffffffffffffffffffffffffff80931683811061085e575b5073ffffffffffffffffffffffffffffffffffffffff809216916040918251907f961be391000000000000000000000000000000000000000000000000000000008252602091600490838183818a5afa90811561081f575f91610831575b50878110610829575b5084517f18e22d98000000000000000000000000000000000000000000000000000000008152858183818a5afa90811561081f575f916107e3575b5061ffff61059a9116610866565b85517f47bd37180000000000000000000000000000000000000000000000000000000090818152858185818c5afa9081156107d9579083915f916107a8575b50111561071b5750505f935b8785106105f7575b5050505050505090565b8551927f70a0823100000000000000000000000000000000000000000000000000000000845216818301528282602481895afa91821561071157908392915f926106df575b50602490865197889384927f07a2d13a0000000000000000000000000000000000000000000000000000000084528301525afa9283156106d657505f926106a4575b506106899250610359565b81811061069c575b8080808080806105ed565b90505f610691565b90915082813d83116106cf575b6106bb81836102dc565b810103126101a7576106899151905f61067e565b503d6106b1565b513d5f823e3d90fd5b8381949293503d831161070a575b6106f781836102dc565b810103126101a75790518291602461063c565b503d6106ed565b85513d5f823e3d90fd5b8651908152848184818b5afa90811561079e575f91610771575b50810390811161074557936105e5565b6011827f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b90508481813d8311610797575b61078881836102dc565b810103126101a757515f610735565b503d61077e565b87513d5f823e3d90fd5b809250878092503d83116107d2575b6107c181836102dc565b810103126101a7578290515f6105d9565b503d6107b7565b88513d5f823e3d90fd5b90508581813d8311610818575b6107fa81836102dc565b810103126101a75783015161ffff811681036101a75761ffff61058c565b503d6107f0565b86513d5f823e3d90fd5b96505f610551565b90508381813d8311610857575b61084881836102dc565b810103126101a757515f610548565b503d61083e565b92505f6104ea565b801561087f5780603f60649260061c9116600a0a020490565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9056fea26469706673582212206b8eba4352e1a0c445b213ca7abe70e45dfe90db7a53a228294997808554b6dc64736f6c63430008170033",
"devdoc": {
"kind": "dev",
"methods": {},
"version": 1
},
"userdoc": {
"kind": "user",
"methods": {},
"version": 1
},
"storageLayout": {
"storage": [],
"types": null
}
}
Loading
Loading