Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xDEd25342...320CA2587 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
LinearStepFunctionInterestSetter
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later /* Copyright 2023 Dolomite. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ pragma solidity ^0.8.9; import { Require } from "@dolomite-exchange/modules-base/contracts/protocol/lib/Require.sol"; import { ILinearStepFunctionInterestSetter } from "./interfaces/ILinearStepFunctionInterestSetter.sol"; /** * @title LinearStepFunctionInterestSetter * @author Dolomite * * @notice Applies a linear utilization model to reach the optimal utilization until interest rates reach 90% * utilization. Then interest rates scale linearly to 100% APR. */ contract LinearStepFunctionInterestSetter is ILinearStepFunctionInterestSetter { // =============== Constants =============== bytes32 private constant _FILE = "LinearStepFunctionInterestSetter"; uint256 public constant ONE_HUNDRED_PERCENT = 1 ether; uint256 public constant SECONDS_IN_A_YEAR = 60 * 60 * 24 * 365; // =============== Immutable Storage =============== uint256 public immutable override LOWER_OPTIMAL_PERCENT; // solhint-disable-line uint256 public immutable override UPPER_OPTIMAL_PERCENT; // solhint-disable-line uint256 public immutable override OPTIMAL_UTILIZATION; // solhint-disable-line uint256 public immutable REMAINING_OPTIMAL_UTILIZATION; // solhint-disable-line constructor( uint256 _lowerOptimalPercent, uint256 _upperOptimalPercent, uint256 _optimalUtilization ) { Require.that( _lowerOptimalPercent < _upperOptimalPercent, _FILE, "Lower optimal percent too high" ); Require.that( _optimalUtilization < ONE_HUNDRED_PERCENT && _optimalUtilization > 0, _FILE, "Invalid optimal utilization" ); LOWER_OPTIMAL_PERCENT = _lowerOptimalPercent; UPPER_OPTIMAL_PERCENT = _upperOptimalPercent; OPTIMAL_UTILIZATION = _optimalUtilization; REMAINING_OPTIMAL_UTILIZATION = ONE_HUNDRED_PERCENT - OPTIMAL_UTILIZATION; } function getInterestRate( address /* token */, uint256 _borrowWei, uint256 _supplyWei ) external override view returns (InterestRate memory) { if (_borrowWei == 0) { return InterestRate({ value: 0 }); } else if (_supplyWei == 0) { return InterestRate({ value: (LOWER_OPTIMAL_PERCENT + UPPER_OPTIMAL_PERCENT) / SECONDS_IN_A_YEAR }); } uint256 utilization = _borrowWei * ONE_HUNDRED_PERCENT / _supplyWei; if (utilization >= ONE_HUNDRED_PERCENT) { return InterestRate({ value: (LOWER_OPTIMAL_PERCENT + UPPER_OPTIMAL_PERCENT) / SECONDS_IN_A_YEAR }); } else if (utilization > OPTIMAL_UTILIZATION) { // interest is equal to lowerOptimalPercent + linear progress to upperOptimalPercent APR uint256 utilizationDiff = utilization - OPTIMAL_UTILIZATION; uint256 interestToAdd = UPPER_OPTIMAL_PERCENT * utilizationDiff / REMAINING_OPTIMAL_UTILIZATION; return InterestRate({ value: (interestToAdd + LOWER_OPTIMAL_PERCENT) / SECONDS_IN_A_YEAR }); } else { return InterestRate({ value: LOWER_OPTIMAL_PERCENT * utilization / OPTIMAL_UTILIZATION / SECONDS_IN_A_YEAR }); } } function interestSetterType() external override pure returns (InterestSetterType) { return InterestSetterType.Linear; } }
// SPDX-License-Identifier: GPL-3.0-or-later /* Copyright 2023 Dolomite This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ pragma solidity ^0.8.9; /** * @title IDolomiteInterestSetter * @author Dolomite * * @notice This interface defines the functions that for an interest setter that can be used to determine the interest * rate of a market. */ interface IDolomiteInterestSetter { // ============ Enum ============ enum InterestSetterType { None, Linear, DoubleExponential, Other } // ============ Structs ============ struct InterestRate { uint256 value; } // ============ Functions ============ /** * Get the interest rate of a token given some borrowed and supplied amounts * * @param token The address of the ERC20 token for the market * @param borrowWei The total borrowed token amount for the market * @param supplyWei The total supplied token amount for the market * @return The interest rate per second */ function getInterestRate( address token, uint256 borrowWei, uint256 supplyWei ) external view returns (InterestRate memory); function interestSetterType() external pure returns (InterestSetterType); }
// SPDX-License-Identifier: Apache-2.0 /* Copyright 2019 dYdX Trading Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ pragma solidity ^0.8.9; /** * @title Require * @author dYdX * * @notice Stringifies parameters to pretty-print revert messages. Costs more gas than regular require() */ library Require { // ============ Constants ============ uint256 private constant _ASCII_ZERO = 48; // '0' uint256 private constant _ASCII_RELATIVE_ZERO = 87; // 'a' - 10 uint256 private constant _ASCII_LOWER_EX = 120; // 'x' bytes2 private constant _COLON = 0x3a20; // ': ' bytes2 private constant _COMMA = 0x2c20; // ', ' bytes2 private constant _LPAREN = 0x203c; // ' <' bytes1 private constant _RPAREN = 0x3e; // '>' uint256 private constant _FOUR_BIT_MASK = 0xf; // ============ Library Functions ============ function that( bool must, bytes32 file, bytes32 reason ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason) ) ) ); } } function that( bool must, bytes32 file, bytes32 reason, uint256 payloadA ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason), _LPAREN, _stringify(payloadA), _RPAREN ) ) ); } } function that( bool must, bytes32 file, bytes32 reason, uint256 payloadA, uint256 payloadB ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason), _LPAREN, _stringify(payloadA), _COMMA, _stringify(payloadB), _RPAREN ) ) ); } } function that( bool must, bytes32 file, bytes32 reason, address payloadA ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason), _LPAREN, _stringify(payloadA), _RPAREN ) ) ); } } function that( bool must, bytes32 file, bytes32 reason, address payloadA, uint256 payloadB ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason), _LPAREN, _stringify(payloadA), _COMMA, _stringify(payloadB), _RPAREN ) ) ); } } function that( bool must, bytes32 file, bytes32 reason, address payloadA, uint256 payloadB, uint256 payloadC ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason), _LPAREN, _stringify(payloadA), _COMMA, _stringify(payloadB), _COMMA, _stringify(payloadC), _RPAREN ) ) ); } } function that( bool must, bytes32 file, bytes32 reason, bytes32 payloadA ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason), _LPAREN, _stringify(payloadA), _RPAREN ) ) ); } } function that( bool must, bytes32 file, bytes32 reason, bytes32 payloadA, uint256 payloadB, uint256 payloadC ) internal pure { if (!must) { revert( string( abi.encodePacked( stringifyTruncated(file), _COLON, stringifyTruncated(reason), _LPAREN, _stringify(payloadA), _COMMA, _stringify(payloadB), _COMMA, _stringify(payloadC), _RPAREN ) ) ); } } // ============ Private Functions ============ function stringifyTruncated( bytes32 input ) internal pure returns (bytes memory) { // put the input bytes into the result bytes memory result = abi.encodePacked(input); // determine the length of the input by finding the location of the last non-zero byte for (uint256 i = 32; i > 0; ) { // reverse-for-loops with unsigned integer i--; // find the last non-zero byte in order to determine the length if (result[i] != 0) { uint256 length = i + 1; /* solhint-disable-next-line no-inline-assembly */ assembly { mstore(result, length) // r.length = length; } return result; } } // all bytes are zero return new bytes(0); } function stringifyFunctionSelector( bytes4 input ) internal pure returns (bytes memory) { uint256 z = uint256(bytes32(input) >> 224); // bytes4 are "0x" followed by 4 bytes of data which take up 2 characters each bytes memory result = new bytes(10); // populate the result with "0x" result[0] = bytes1(uint8(_ASCII_ZERO)); result[1] = bytes1(uint8(_ASCII_LOWER_EX)); // for each byte (starting from the lowest byte), populate the result with two characters for (uint256 i = 0; i < 4; i++) { // each byte takes two characters uint256 shift = i * 2; // populate the least-significant character result[9 - shift] = _char(z & _FOUR_BIT_MASK); z = z >> 4; // populate the most-significant character result[8 - shift] = _char(z & _FOUR_BIT_MASK); z = z >> 4; } return result; } function _stringify( uint256 input ) private pure returns (bytes memory) { if (input == 0) { return "0"; } // get the final string length uint256 j = input; uint256 length; while (j != 0) { length++; j /= 10; } // allocate the string bytes memory bstr = new bytes(length); // populate the string starting with the least-significant character j = input; for (uint256 i = length; i > 0; ) { // reverse-for-loops with unsigned integer i--; // take last decimal digit bstr[i] = bytes1(uint8(_ASCII_ZERO + (j % 10))); // remove the last decimal digit j /= 10; } return bstr; } function _stringify( address input ) private pure returns (bytes memory) { uint256 z = uint256(uint160(input)); // addresses are "0x" followed by 20 bytes of data which take up 2 characters each bytes memory result = new bytes(42); // populate the result with "0x" result[0] = bytes1(uint8(_ASCII_ZERO)); result[1] = bytes1(uint8(_ASCII_LOWER_EX)); // for each byte (starting from the lowest byte), populate the result with two characters for (uint256 i = 0; i < 20; i++) { // each byte takes two characters uint256 shift = i * 2; // populate the least-significant character result[41 - shift] = _char(z & _FOUR_BIT_MASK); z = z >> 4; // populate the most-significant character result[40 - shift] = _char(z & _FOUR_BIT_MASK); z = z >> 4; } return result; } function _stringify( bytes32 input ) private pure returns (bytes memory) { uint256 z = uint256(input); // bytes32 are "0x" followed by 32 bytes of data which take up 2 characters each bytes memory result = new bytes(66); // populate the result with "0x" result[0] = bytes1(uint8(_ASCII_ZERO)); result[1] = bytes1(uint8(_ASCII_LOWER_EX)); // for each byte (starting from the lowest byte), populate the result with two characters for (uint256 i = 0; i < 32; i++) { // each byte takes two characters uint256 shift = i * 2; // populate the least-significant character result[65 - shift] = _char(z & _FOUR_BIT_MASK); z = z >> 4; // populate the most-significant character result[64 - shift] = _char(z & _FOUR_BIT_MASK); z = z >> 4; } return result; } function _char( uint256 input ) private pure returns (bytes1) { // return ASCII digit (0-9) if (input < 10) { return bytes1(uint8(input + _ASCII_ZERO)); } // return ASCII letter (a-f) return bytes1(uint8(input + _ASCII_RELATIVE_ZERO)); } }
// SPDX-License-Identifier: GPL-3.0-or-later /* Copyright 2023 Dolomite This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ pragma solidity ^0.8.9; import { IDolomiteInterestSetter } from "@dolomite-exchange/modules-base/contracts/protocol/interfaces/IDolomiteInterestSetter.sol"; // solhint-disable-line max-line-length /** * @title ILinearStepFunctionInterestSetter * @author Dolomite * * Interface for a contract that uses linear step functions to set interest rates. */ interface ILinearStepFunctionInterestSetter is IDolomiteInterestSetter { function LOWER_OPTIMAL_PERCENT() external view returns (uint256); function UPPER_OPTIMAL_PERCENT() external view returns (uint256); function OPTIMAL_UTILIZATION() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later /* Copyright 2023 Dolomite This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ pragma solidity ^0.8.9; import { IDolomiteInterestSetter } from "@dolomite-exchange/modules-base/contracts/protocol/interfaces/IDolomiteInterestSetter.sol"; // solhint-disable-line max-line-length /** * @title TestInterestSetter * @author Dolomite * * @notice Interface contract for setting the interest rate for certain tokens for testing */ contract TestInterestSetter is IDolomiteInterestSetter { mapping (address => InterestRate) public g_interestRates; // solhint-disable-line var-name-mixedcase function setInterestRate( address token, InterestRate calldata rate ) external { g_interestRates[token] = rate; } function getInterestRate( address token, uint256 /* borrowWei */, uint256 /* supplyWei */ ) external view returns (InterestRate memory) { return g_interestRates[token]; } function interestSetterType() external pure returns (InterestSetterType) { return InterestSetterType.Other; } }
{ "optimizer": { "enabled": true, "runs": 200, "details": { "yul": false } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"_lowerOptimalPercent","type":"uint256"},{"internalType":"uint256","name":"_upperOptimalPercent","type":"uint256"},{"internalType":"uint256","name":"_optimalUtilization","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"LOWER_OPTIMAL_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_HUNDRED_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTIMAL_UTILIZATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REMAINING_OPTIMAL_UTILIZATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECONDS_IN_A_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPPER_OPTIMAL_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_borrowWei","type":"uint256"},{"internalType":"uint256","name":"_supplyWei","type":"uint256"}],"name":"getInterestRate","outputs":[{"components":[{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IDolomiteInterestSetter.InterestRate","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestSetterType","outputs":[{"internalType":"enum IDolomiteInterestSetter.InterestSetterType","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"}]
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063dd0081c71161005b578063dd0081c714610123578063e1169a2e14610132578063e8177dcf14610159578063ee15144b1461017957600080fd5b80632f1ca9e31461008d578063a57e84af146100ca578063c4fa17a4146100f1578063cf762dfa146100fc575b600080fd5b6100b47f00000000000000000000000000000000000000000000000002c68af0bb14000081565b6040516100c19190610538565b60405180910390f35b6100b47f0000000000000000000000000000000000000000000000000cc47f20295c000081565b6100b46301e1338081565b6100b47f0000000000000000000000000000000000000000000000000b1a2bc2ec50000081565b6100b4670de0b6b3a764000081565b6100b47f000000000000000000000000000000000000000000000000011c37937e08000081565b61016c610167366004610590565b610188565b6040516100c191906105f7565b60016040516100c1919061064e565b604080516020810190915260008152826101b1575060408051602081019091526000815261042f565b816102255760405180602001604052806301e133807f0000000000000000000000000000000000000000000000000cc47f20295c00007f000000000000000000000000000000000000000000000000011c37937e0800006102129190610672565b61021c91906106a0565b9052905061042f565b60008261023a670de0b6b3a7640000866106b4565b61024491906106a0565b9050670de0b6b3a764000081106102c65760405180602001604052806301e133807f0000000000000000000000000000000000000000000000000cc47f20295c00007f000000000000000000000000000000000000000000000000011c37937e0800006102b19190610672565b6102bb91906106a0565b81525091505061042f565b7f0000000000000000000000000000000000000000000000000b1a2bc2ec5000008111156103c857600061031a7f0000000000000000000000000000000000000000000000000b1a2bc2ec500000836106d3565b905060007f00000000000000000000000000000000000000000000000002c68af0bb140000610369837f0000000000000000000000000000000000000000000000000cc47f20295c00006106b4565b61037391906106a0565b905060405180602001604052806301e133807f000000000000000000000000000000000000000000000000011c37937e080000846103b19190610672565b6103bb91906106a0565b815250935050505061042f565b60405180602001604052806301e133807f0000000000000000000000000000000000000000000000000b1a2bc2ec500000847f000000000000000000000000000000000000000000000000011c37937e08000061042591906106b4565b6102b191906106a0565b9392505050565b826104945761044482610499565b6101d160f51b61045383610499565b60405160200161046593929190610748565b60408051601f198184030181529082905262461bcd60e51b825261048b916004016107ab565b60405180910390fd5b505050565b60606000826040516020016104ae91906107c2565b60408051601f19818403018152919052905060205b801561051957806104d3816107d7565b9150508181815181106104e8576104e86107ee565b01602001516001600160f81b03191615610514576000610509826001610672565b835250909392505050565b6104c3565b505060408051600081526020810190915292915050565b805b82525050565b602081016105468284610530565b92915050565b60006001600160a01b038216610546565b6105668161054c565b811461057157600080fd5b50565b80356105468161055d565b80610566565b80356105468161057f565b6000806000606084860312156105a8576105a8600080fd5b60006105b48686610574565b93505060206105c586828701610585565b92505060406105d686828701610585565b9150509250925092565b805160208301906105f18482610530565b50505050565b6020810161054682846105e0565b634e487b7160e01b600052602160045260246000fd5b6004811061057157610571610605565b806106358161061b565b919050565b60006105468261062b565b6105328161063a565b602081016105468284610645565b634e487b7160e01b600052601160045260246000fd5b600082198211156106855761068561065c565b500190565b634e487b7160e01b600052601260045260246000fd5b6000826106af576106af61068a565b500490565b60008160001904831182151516156106ce576106ce61065c565b500290565b6000828210156106e5576106e561065c565b500390565b60005b838110156107055781810151838201526020016106ed565b838111156105f15750506000910152565b6000610720825190565b61072e8185602086016106ea565b9290920192915050565b6001600160f01b03198116610532565b60006107548286610716565b91506107608285610738565b6002820191506107708284610716565b95945050505050565b6000610783825190565b80845260208401935061079a8185602086016106ea565b601f01601f19169290920192915050565b6020808252810161042f8184610779565b80610532565b60006107ce82846107bc565b50602001919050565b6000816107e6576107e661065c565b506000190190565b634e487b7160e01b600052603260045260246000fdfea26469706673582212208f1bbf8f003b127e5a061f32cfb59895794df3b7d964e22e82bb247705caf67064736f6c63430008090033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.