@inco/lightning 0.8.0-devnet-1 → 0.8.0-devnet-3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,43 @@
1
+ // SPDX-License-Identifier: No License
2
+ pragma solidity ^0.8;
3
+
4
+ import {IncoTest} from "./IncoTest.sol";
5
+ import {inco} from "../Lib.sol";
6
+ import {EventCounter} from "../lightning-parts/primitives/EventCounter.sol";
7
+
8
+ /// @dev Test harness to expose internal getNewEventId() for coverage
9
+ contract EventCounterHarness is EventCounter {
10
+
11
+ function exposed_getNewEventId() external returns (uint256) {
12
+ return getNewEventId();
13
+ }
14
+
15
+ }
16
+
17
+ contract TestEventCounter is IncoTest {
18
+
19
+ /// @dev Tests the deprecated getEventCounter() function for coverage.
20
+ /// getEventCounter() is deprecated in favor of getNextEventId().
21
+ function testGetEventCounter_Deprecated() public view {
22
+ // Both functions should return the same value
23
+ uint256 counter = inco.getEventCounter();
24
+ uint256 nextId = inco.getNextEventId();
25
+ assertEq(counter, nextId, "getEventCounter should equal getNextEventId");
26
+ }
27
+
28
+ /// @dev Tests getNewEventId() which increments the counter and returns the new ID.
29
+ /// This function is used by lightning-preview's EList operations.
30
+ function testGetNewEventId() public {
31
+ EventCounterHarness harness = new EventCounterHarness();
32
+
33
+ uint256 firstId = harness.exposed_getNewEventId();
34
+ assertEq(firstId, 0, "First event ID should be 0");
35
+
36
+ uint256 secondId = harness.exposed_getNewEventId();
37
+ assertEq(secondId, 1, "Second event ID should be 1");
38
+
39
+ uint256 thirdId = harness.exposed_getNewEventId();
40
+ assertEq(thirdId, 2, "Third event ID should be 2");
41
+ }
42
+
43
+ }
@@ -139,9 +139,10 @@ contract TestFakeInfra is IncoTest {
139
139
  function testEShr() public {
140
140
  euint256 a = e.asEuint256(10);
141
141
  euint256 b = e.asEuint256(4);
142
- euint256 c = a.xor(b);
142
+
143
+ euint256 c = a.shr(b);
143
144
  processAllOperations();
144
- assertEq(getUint256Value(c), 14);
145
+ assertEq(getUint256Value(c), 0);
145
146
  }
146
147
 
147
148
  function testERotl() public {
@@ -546,6 +547,12 @@ contract TestFakeInfra is IncoTest {
546
547
  a.add(euint256.wrap(randomHandle));
547
548
  }
548
549
 
550
+ function testECastAllowed() public {
551
+ bytes32 invalidHandle = keccak256("invalid handle");
552
+ vm.expectRevert(abi.encodeWithSelector(SenderNotAllowedForHandle.selector, invalidHandle, address(this)));
553
+ euint256.wrap(invalidHandle).asEbool();
554
+ }
555
+
549
556
  function testCreateQuote() public view {
550
557
  bytes memory mrtd =
551
558
  hex"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
@@ -57,4 +57,3 @@ contract TestFeeWithdrawal is IncoTest {
57
57
  }
58
58
 
59
59
  }
60
-
@@ -239,4 +239,54 @@ contract TestIncoUtils is Test, IncoUtils {
239
239
  assertEq(address(this).balance, balanceBefore - spendAmount);
240
240
  }
241
241
 
242
+ /// @notice Test reentrancy guard catches direct reentrant call from function body
243
+ function testRefundUnspentReentrancyFromFunctionBody() public {
244
+ vm.expectRevert(IncoUtils.ReentrantCall.selector);
245
+ this.mockFunctionThatReenters{value: 1 ether}();
246
+ }
247
+
248
+ function mockFunctionThatReenters() external payable refundUnspent {
249
+ // Try to call another protected function while inside the first one
250
+ this.mockFunctionNoSpend();
251
+ }
252
+
253
+ /// @notice Test refund=0 when msg.value equals spent exactly
254
+ function testRefundUnspentWhenMsgValueEqualsSpent() public {
255
+ // This explicitly tests the refund=0 branch when msg.value == spent
256
+ uint256 msgValue = 1 ether;
257
+
258
+ vm.deal(address(this), msgValue);
259
+ uint256 balanceBefore = address(this).balance;
260
+
261
+ // Spend exactly msg.value, so refund = msg.value - spent = 0
262
+ this.mockFunctionPartialSpend{value: msgValue}(msgValue);
263
+
264
+ // All ETH was spent, no refund
265
+ assertEq(address(this).balance, balanceBefore - msgValue);
266
+ }
267
+
268
+ /// @notice Test when contract receives more ETH during execution than was sent
269
+ /// This triggers the balanceAfter > balanceBefore branch (spent = 0)
270
+ function testRefundUnspentWhenReceivingMoreThanSent() public {
271
+ uint256 msgValue = 0.5 ether;
272
+ uint256 incomingEth = 1 ether; // More than msg.value
273
+
274
+ vm.deal(address(sender), incomingEth);
275
+ vm.deal(address(this), msgValue);
276
+ uint256 balanceBefore = address(this).balance;
277
+
278
+ // During execution, we receive 1 ETH (more than we sent)
279
+ this.mockFunctionReceivesEthDuringExecution{value: msgValue}(payable(address(sender)), incomingEth);
280
+
281
+ // Execution trace:
282
+ // 1. balanceBefore (modifier) = 0.5 ETH (self-call doesn't change balance)
283
+ // 2. Sender sends 1 ETH during execution
284
+ // 3. balanceAfter (modifier) = 0.5 + 1 = 1.5 ETH
285
+ // 4. spent = balanceBefore > balanceAfter ? ... : 0 = 0 (since 0.5 < 1.5)
286
+ // 5. refund = msg.value - spent = 0.5 - 0 = 0.5 ETH
287
+ // 6. Refund sent to msg.sender (this contract) = self-transfer, no balance change
288
+ // 7. Final balance = 1.5 ETH = balanceBefore (test) + incomingEth
289
+ assertEq(address(this).balance, balanceBefore + incomingEth);
290
+ }
291
+
242
292
  }