fix: reputation curve fixed

This commit is contained in:
PedroCailleret
2022-12-04 01:51:20 -03:00
parent fc478dc12f
commit eb4cca9c12
22 changed files with 136 additions and 183 deletions

View File

@@ -3,19 +3,16 @@ pragma solidity 0.8.9;
import { IReputation } from "./lib/interfaces/IReputation.sol";
import { Owned } from "./lib/auth/Owned.sol";
import { FixedPointMathLib as WADMath } from "./lib/utils/FixedPointMathLib.sol";
contract Reputation is IReputation, Owned(msg.sender) {
using WADMath for uint256;
/// @dev Asymptote numerator constant value for the `limiter` fx.
uint256 public constant maxLimit = 1e6;
/// @dev Denominator's constant operand for the `limiter` fx.
uint256 public constant magicValue = 2.5e11;
constructor() /* */ {
/* */
}
// prettier-ignore
// solhint-disable-next-line no-empty-blocks
constructor(/* */) {/* */}
function limiter(
uint256 _userCredit
@@ -25,23 +22,58 @@ contract Reputation is IReputation, Owned(msg.sender) {
override(IReputation)
returns (uint256 _spendLimit)
{
// _spendLimit = 1 + ( ( maxLimit * _userCredit ) / sqrt( magicValue * ( _userCredit * _userCredit ) ) );
// return _spendLimit;
_spendLimit = (1 +
((maxLimit * _userCredit) /
sqrt(
magicValue + (_userCredit * _userCredit)
)));
}
unchecked {
uint256 numeratorWad = maxLimit.mulWadDown(
_userCredit
);
uint256 userCreditSquaredWad = _userCredit
.mulWadDown(_userCredit);
uint256 denominatorSqrtWad = (
userCreditSquaredWad.mulWadDown(magicValue)
).sqrt();
/// @notice Taken from Solmate's FixedPointMathLib.
/// (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
function sqrt(
uint256 x
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
let y := x // We start y at x, which will help us make our initial estimate.
_spendLimit = (1 +
(numeratorWad).divWadDown(
denominatorSqrtWad
));
z := 181 // The "correct" value is 1, but this saves a multiplication later.
// We check y >= 2^(k + 8) but shift right by k bits
// each branch to ensure that if x >= 256, then y >= 256.
if iszero(
lt(y, 0x10000000000000000000000000000000000)
) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
// There is no overflow risk here since y < 2^136 after the first branch above.
z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.
// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := sub(z, lt(div(x, z), z))
}
}
}