p2pix-smart-contracts/contracts/Reputation.sol

81 lines
2.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import { IReputation } from "./lib/interfaces/IReputation.sol";
import { Owned } from "./lib/auth/Owned.sol";
contract Reputation is IReputation, Owned(msg.sender) {
/// @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;
// prettier-ignore
// solhint-disable no-inline-assembly
// solhint-disable-next-line no-empty-blocks
constructor(/* */) {/* */}
function limiter(
uint256 _userCredit
)
external
pure
override(IReputation)
returns (uint256 _spendLimit)
{
_spendLimit = (1 +
((maxLimit * _userCredit) /
sqrt(
magicValue + (_userCredit * _userCredit)
)));
}
/// @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.
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))
}
}
}