80 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
| // SPDX-License-Identifier: MIT
 | |
| pragma solidity ^0.8.19;
 | |
| 
 | |
| import { IReputation } from "./lib/interfaces/IReputation.sol";
 | |
| 
 | |
| contract Reputation is IReputation {
 | |
|     /// @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(/*  */) payable {/*  */}
 | |
| 
 | |
|     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))
 | |
|         }
 | |
|     }
 | |
| }
 |