diff --git a/src/LeaseEscrowV1.sol b/src/LeaseEscrowV1.sol index 52df73c..17afa5d 100644 --- a/src/LeaseEscrowV1.sol +++ b/src/LeaseEscrowV1.sol @@ -13,10 +13,10 @@ contract LeaseEscrowV1 { uint256 public constant MAX_ESCROW = 50_000_000; uint32 public constant MAX_DURATION = 6 hours; uint32 public constant PROVISION_TIMEOUT = 10 minutes; - uint32 public constant DISPUTE_WINDOW = 24 hours; + uint32 public constant DISPUTE_WINDOW = 5 minutes; uint16 public constant PLATFORM_FEE_BPS = 1_000; uint16 public constant BPS_DENOMINATOR = 10_000; - uint16 public constant MAX_ACTIVE_LEASES = 25; + uint16 public constant MAX_ACTIVE_LEASES = 250; bytes32 public constant DOMAIN_TYPEHASH = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" @@ -348,6 +348,19 @@ contract LeaseEscrowV1 { _settle(leaseId, lease, usageSeconds, receiptHash); } + function adminClose(uint256 leaseId, bytes32 reasonHash) + external + onlyEmergencyAdmin + nonReentrant + { + Lease storage lease = _lease(leaseId); + LeaseStatus status = lease.status; + if (status == LeaseStatus.Finalized || status == LeaseStatus.Refunded) { + revert InvalidState(); + } + _refund(leaseId, lease, reasonHash); + } + function pause() external onlyEmergencyAdmin { if (paused) revert AlreadyPaused(); paused = true; diff --git a/src/NodeRegistryV1.sol b/src/NodeRegistryV1.sol index 5b1c2a9..15169a1 100644 --- a/src/NodeRegistryV1.sol +++ b/src/NodeRegistryV1.sol @@ -7,7 +7,7 @@ import { TokenTransfers } from "./lib/TokenTransfers.sol"; contract NodeRegistryV1 { using TokenTransfers for IERC20; - uint256 public constant MIN_BOND = 100_000_000; + uint256 public constant MIN_BOND = 1_000_000; uint256 public constant DAY = 24 hours; uint256 private constant SECP256K1N_DIV_2 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0; @@ -257,9 +257,8 @@ contract NodeRegistryV1 { && node.bond >= requiredBond(node.ratePerSecond); } - function requiredBond(uint128 ratePerSecond) public pure returns (uint256) { - uint256 dayRate = uint256(ratePerSecond) * DAY; - return dayRate > MIN_BOND ? dayRate : MIN_BOND; + function requiredBond(uint128) public pure returns (uint256) { + return MIN_BOND; } function domainSeparator() public view returns (bytes32) { diff --git a/test/LeaseEscrowV1.t.sol b/test/LeaseEscrowV1.t.sol index dc3459c..ab2fda8 100644 --- a/test/LeaseEscrowV1.t.sol +++ b/test/LeaseEscrowV1.t.sol @@ -80,9 +80,11 @@ contract LeaseEscrowV1Test { _registerNode(); } - function testBondTracksTwentyFourHoursOfGrossRate() public view { - require(registry.requiredBond(1_000) == 100_000_000, "minimum bond should apply"); - require(registry.requiredBond(2_000) == 172_800_000, "daily rate should apply"); + function testRequiredBondIsFlatMinimum() public view { + require(registry.requiredBond(1_000) == 1_000_000, "flat minimum applies"); + require( + registry.requiredBond(type(uint128).max) == 1_000_000, "bond does not scale with rate" + ); } function testEscrowReservesNodeAndStartsOnlyThroughGateway() public { @@ -200,7 +202,7 @@ contract LeaseEscrowV1Test { require(!registered, "registration accepted an invalid device binding"); } - function testNodeRegistrationRejectsBondOutsideStorageRange() public { + function testNodeRegistrationAcceptsExtremeRateUnderFlatBond() public { bytes32 nodeId = keccak256("unbounded-rate-device"); bytes32 metadataHash = keccak256("unbounded-rate-offer"); uint128 rate = type(uint128).max; @@ -232,7 +234,8 @@ contract LeaseEscrowV1Test { ) ) ); - require(!registered, "registration truncated required bond"); + require(registered, "flat bond should accept any rate"); + require(registry.getNode(nodeId).bond == 1_000_000, "bond should equal flat minimum"); } function testRetiredNodeCanWithdrawItsEntireBond() public {