@inco/lightning 0.9.0-devnet-test-10 → 0.10.0-devnet-1

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.
Files changed (89) hide show
  1. package/manifest.yaml +150 -0
  2. package/package.json +8 -8
  3. package/src/CreateXHelper.sol +1 -1
  4. package/src/DeployUtils.sol +22 -28
  5. package/src/IncoLightning.sol +27 -18
  6. package/src/IncoVerifier.sol +1 -1
  7. package/src/Lib.alphanet.sol +294 -13
  8. package/src/Lib.demonet.sol +294 -13
  9. package/src/Lib.devnet.sol +294 -13
  10. package/src/Lib.sol +294 -13
  11. package/src/Lib.template.sol +357 -13
  12. package/src/Lib.testnet.sol +294 -13
  13. package/src/Types.sol +44 -0
  14. package/src/interfaces/IIncoLightning.sol +8 -12
  15. package/src/interfaces/automata-interfaces/BELE.sol +1 -1
  16. package/src/interfaces/automata-interfaces/IPCCSRouter.sol +1 -1
  17. package/src/interfaces/automata-interfaces/IPcsDao.sol +1 -1
  18. package/src/interfaces/automata-interfaces/IQuoteVerifier.sol +1 -1
  19. package/src/interfaces/automata-interfaces/Types.sol +1 -1
  20. package/src/libs/incoLightning_alphanet_v0_297966649.sol +294 -13
  21. package/src/libs/incoLightning_alphanet_v1_725458969.sol +294 -13
  22. package/src/libs/incoLightning_alphanet_v2_976644394.sol +294 -13
  23. package/src/libs/incoLightning_demonet_v0_863421733.sol +294 -13
  24. package/src/libs/incoLightning_demonet_v2_467437523.sol +294 -13
  25. package/src/libs/incoLightning_devnet_v0_340846814.sol +294 -13
  26. package/src/libs/incoLightning_devnet_v10_266391127.sol +1223 -0
  27. package/src/libs/incoLightning_devnet_v1_904635675.sol +294 -13
  28. package/src/libs/incoLightning_devnet_v2_295237520.sol +294 -13
  29. package/src/libs/incoLightning_devnet_v3_976859633.sol +294 -13
  30. package/src/libs/incoLightning_devnet_v4_409204766.sol +294 -13
  31. package/src/libs/incoLightning_devnet_v5_203964628.sol +1223 -0
  32. package/src/libs/incoLightning_devnet_v6_281949651.sol +1223 -0
  33. package/src/libs/incoLightning_devnet_v7_24560427.sol +1223 -0
  34. package/src/libs/incoLightning_devnet_v8_985328058.sol +1223 -0
  35. package/src/libs/incoLightning_devnet_v9_269218568.sol +1223 -0
  36. package/src/libs/incoLightning_testnet_v0_183408998.sol +294 -13
  37. package/src/libs/incoLightning_testnet_v2_889158349.sol +294 -13
  38. package/src/lightning-parts/AccessControl/AdvancedAccessControl.sol +8 -3
  39. package/src/lightning-parts/AccessControl/BaseAccessControlList.sol +0 -16
  40. package/src/lightning-parts/AccessControl/interfaces/IAdvancedAccessControl.sol +1 -1
  41. package/src/lightning-parts/AccessControl/interfaces/IBaseAccessControlList.sol +3 -2
  42. package/src/lightning-parts/AccessControl/test/TestAdvancedAccessControl.t.sol +18 -1
  43. package/src/lightning-parts/AccessControl/test/TestBaseAccessControl.t.sol +0 -43
  44. package/src/lightning-parts/DecryptionAttester.sol +124 -2
  45. package/src/lightning-parts/DecryptionAttester.types.sol +20 -0
  46. package/src/lightning-parts/EList.sol +397 -0
  47. package/src/lightning-parts/EncryptedInput.sol +78 -8
  48. package/src/lightning-parts/EncryptedOperations.sol +40 -34
  49. package/src/lightning-parts/Fee.sol +29 -0
  50. package/src/lightning-parts/TEELifecycle.sol +38 -30
  51. package/src/lightning-parts/TEELifecycle.types.sol +1 -1
  52. package/src/lightning-parts/TrivialEncryption.sol +1 -2
  53. package/src/lightning-parts/interfaces/IDecryptionAttester.sol +16 -1
  54. package/src/lightning-parts/interfaces/IEList.sol +38 -0
  55. package/src/lightning-parts/interfaces/IEncryptedInput.sol +9 -1
  56. package/src/lightning-parts/interfaces/IEncryptedOperations.sol +3 -2
  57. package/src/lightning-parts/interfaces/ITEELifecycle.sol +1 -1
  58. package/src/lightning-parts/interfaces/ITrivialEncryption.sol +3 -1
  59. package/src/lightning-parts/primitives/EListHandleGeneration.sol +66 -0
  60. package/src/lightning-parts/primitives/EListHandleMetadata.sol +67 -0
  61. package/src/lightning-parts/primitives/HandleGeneration.sol +31 -8
  62. package/src/lightning-parts/primitives/HandleMetadata.sol +10 -3
  63. package/src/lightning-parts/primitives/interfaces/IEListHandleMetadata.sol +8 -0
  64. package/src/lightning-parts/primitives/test/SignatureVerifier.t.sol +1 -1
  65. package/src/lightning-parts/test/Elist.t.sol +218 -0
  66. package/src/lightning-parts/test/HandleMetadata.t.sol +66 -23
  67. package/src/lightning-parts/test/TestDecryptionAttestationInSynchronousFlow.t.sol +41 -13
  68. package/src/misc/ABIHelper.sol +15 -0
  69. package/src/pasted-dependencies/ICreateX.sol +1 -1
  70. package/src/periphery/IncoUtils.sol +1 -1
  71. package/src/periphery/SessionVerifier.sol +4 -4
  72. package/src/shared/IOwnable.sol +1 -1
  73. package/src/shared/IUUPSUpgradable.sol +1 -1
  74. package/src/shared/TestUtils.sol +8 -1
  75. package/src/test/EListTester.sol +171 -0
  76. package/src/test/FakeIncoInfra/FakeComputeServer.sol +2 -2
  77. package/src/test/FakeIncoInfra/FakeIncoInfraBase.sol +3 -3
  78. package/src/test/FakeIncoInfra/MockOpHandler.sol +7 -9
  79. package/src/test/FakeIncoInfra/MockRemoteAttestation.sol +2 -1
  80. package/src/test/FakeIncoInfra/getOpForSelector.sol +0 -2
  81. package/src/test/IncoTest.sol +17 -5
  82. package/src/test/OpsTest.sol +3 -2
  83. package/src/test/TEELifecycle/TEELifecycleMockTest.t.sol +85 -57
  84. package/src/test/TestDeploy.t.sol +73 -1
  85. package/src/test/TestFakeInfra.t.sol +32 -6
  86. package/src/test/TestLib.t.sol +986 -19
  87. package/src/test/TestReceive.t.sol +42 -0
  88. package/src/test/TestUpgrade.t.sol +34 -63
  89. package/src/version/IncoLightningConfig.sol +1 -1
@@ -2,21 +2,44 @@
2
2
  pragma solidity ^0.8;
3
3
 
4
4
  import {IncoTest} from "../../test/IncoTest.sol";
5
- import {DemoToken} from "@inco/confidential-token-demo/src/DemoToken.sol";
5
+ import {ERC7984DemoToken} from "@inco/incoERC7984/src/ERC7984DemoToken.sol";
6
6
  import {DecryptionAttestation} from "../DecryptionAttester.types.sol";
7
7
  import {GWEI} from "../../shared/TypeUtils.sol";
8
- import {euint256} from "@inco/lightning/src/Lib.sol"; // import via remapping or compiler fails
8
+ import {inco, e, euint256} from "@inco/lightning/src/Lib.sol"; // import via remapping or compiler fails
9
9
  import {AllowanceProof} from "../AccessControl/AdvancedAccessControl.sol";
10
- import {inco} from "../../Lib.sol";
11
10
  import {euint256 as remappedEuint256} from "@inco/lightning/src/Lib.sol";
11
+ import {
12
+ DecryptionAttestation as remappedDecryptionAttestation
13
+ } from "@inco/lightning/src/lightning-parts/DecryptionAttester.types.sol";
12
14
 
13
- contract TokenBurnCurrentBalance is DemoToken {
15
+ /// @notice This test demonstrates how a decryption attestation can be used in a synchronous flow, where the result of the operation is known at the time of requesting the attestation.
16
+ /// In this example, we simulate a token burn operation where the user proves that they have enough balance to burn before actually performing the burn.
17
+ contract TokenBurnCurrentBalance is ERC7984DemoToken {
14
18
 
15
- function burnFullCurrentBalance(DecryptionAttestation memory decryption, bytes[] memory signatures) public {
19
+ using e for uint256;
20
+ using e for euint256;
21
+
22
+ /// @notice Deploys the token with specified name, symbol, and initial supply
23
+ /// @param name_ The token name
24
+ /// @param symbol_ The token symbol
25
+ /// @param initialSupply The initial supply to mint to the deployer (in base units)
26
+ constructor(string memory name_, string memory symbol_, uint256 initialSupply)
27
+ ERC7984DemoToken(name_, symbol_, initialSupply)
28
+ {
29
+ if (initialSupply > 0) {
30
+ _mint(msg.sender, initialSupply.asEuint256());
31
+ }
32
+ }
33
+
34
+ /// @dev In this burn function, the user provides a decryption attestation that proves they have enough balance to burn the specified amount.
35
+ /// The burn operation is performed synchronously, and the success of the burn is verified using the attestation.
36
+ function burnFullCurrentBalance(remappedDecryptionAttestation memory attestation, bytes[] memory signatures)
37
+ public
38
+ {
16
39
  euint256 currentBalance = confidentialBalanceOf(msg.sender);
17
- require(inco.incoVerifier().isValidDecryptionAttestation(decryption, signatures), "Invalid Signature");
18
- require(euint256.unwrap(currentBalance) == decryption.handle, "Handle mismatch");
19
- publicBurn(msg.sender, uint256(decryption.value));
40
+ require(inco.incoVerifier().isValidDecryptionAttestation(attestation, signatures), "Invalid Signature");
41
+ require(euint256.unwrap(currentBalance) == attestation.handle, "Handle mismatch");
42
+ publicBurn(msg.sender, uint256(attestation.value));
20
43
  }
21
44
 
22
45
  }
@@ -26,19 +49,24 @@ contract TestDecryptionAttestationInSynchronousFlow is IncoTest {
26
49
  AllowanceProof emptyProof; // no proof needed when requester has the handle in persisted allowed pairs
27
50
 
28
51
  function testSynchronousBurning() public {
29
- TokenBurnCurrentBalance token = new TokenBurnCurrentBalance();
52
+ TokenBurnCurrentBalance token = new TokenBurnCurrentBalance("DemoToken", "DMT", 100 ether);
30
53
  vm.deal(address(token), 100 ether);
31
- token.confidentialTransfer(alice, fakePrepareEuint256Ciphertext(10 * GWEI, address(this), address(token)), "");
54
+ token.confidentialTransfer(alice, fakePrepareEuint256Ciphertext(10 * GWEI, address(this), address(token)));
32
55
  processAllOperations(); // saves Alice's balance
56
+
33
57
  bytes32 aliceCurrentBalanceHandle = euint256.unwrap(token.confidentialBalanceOf(alice));
34
58
  // simulates Alice requesting for a decryption attestation of Ge op on her balance and the amount
35
59
  // she intends to burn, therefore proving to the token contract that the operation will succeed
36
- (DecryptionAttestation memory decryption, bytes[] memory signatures) =
60
+ (DecryptionAttestation memory attestation, bytes[] memory signatures) =
37
61
  getDecryptionAttestation(alice, HandleWithProof({handle: aliceCurrentBalanceHandle, proof: emptyProof}));
38
- vm.prank(alice);
39
62
 
63
+ // Convert attestation to remapped type for cross-project compatibility
64
+ remappedDecryptionAttestation memory remappedAttestation =
65
+ remappedDecryptionAttestation({handle: attestation.handle, value: attestation.value});
66
+
67
+ vm.prank(alice);
40
68
  // the decryption attestation is passed to the token burn method
41
- token.burnFullCurrentBalance(decryption, signatures);
69
+ token.burnFullCurrentBalance(remappedAttestation, signatures);
42
70
 
43
71
  processAllOperations();
44
72
 
@@ -0,0 +1,15 @@
1
+ // SPDX-License-Identifier: No License
2
+ pragma solidity ^0.8;
3
+
4
+ import {Session} from "@inco/lightning/src/periphery/SessionVerifier.sol";
5
+
6
+ // @dev this contract is not used on-chain, it is only used to generate the
7
+ // ABI of some symbols that are not exposed directly by the IncoLightning or
8
+ // periphery contracts, but are needed for the JS SDK.
9
+ contract ABIHelper {
10
+
11
+ function getSession() public pure returns (Session memory) {
12
+ revert("This function exists only to include Session struct in ABI");
13
+ }
14
+
15
+ }
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-only
2
- pragma solidity ^0.8.4;
2
+ pragma solidity ^0.8;
3
3
 
4
4
  /**
5
5
  * @title CreateX Factory Interface Definition
@@ -5,7 +5,7 @@ import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol";
5
5
 
6
6
  // Re-export FEE constant for convenience - consumers can import both IncoUtils and FEE from this file
7
7
  // forge-lint: disable-next-line(unused-import)
8
- import {FEE} from "../lightning-parts/Fee.sol";
8
+ import {FEE, BIT_FEE} from "../lightning-parts/Fee.sol";
9
9
 
10
10
  contract IncoUtils {
11
11
 
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: No License
2
- pragma solidity ^0.8;
2
+ pragma solidity ^0.8.29;
3
3
 
4
4
  import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
5
5
  import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
@@ -38,13 +38,13 @@ struct Session {
38
38
  contract SessionVerifier is UUPSUpgradeable, OwnableUpgradeable, Version {
39
39
 
40
40
  /// @notice Initializes the SessionVerifier with version information
41
- /// @param salt Unique salt used for deterministic deployment via CreateX
42
- constructor(bytes32 salt)
41
+ /// @param _salt Unique salt used for deterministic deployment via CreateX
42
+ constructor(bytes32 _salt)
43
43
  Version(
44
44
  SESSION_VERIFIER_MAJOR_VERSION,
45
45
  SESSION_VERIFIER_MINOR_VERSION,
46
46
  SESSION_VERIFIER_PATCH_VERSION,
47
- salt,
47
+ _salt,
48
48
  SESSION_VERIFIER_NAME
49
49
  )
50
50
  {}
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.0;
2
+ pragma solidity ^0.8;
3
3
 
4
4
  // OpenZeppelin doesn't export any interfaces for ownable so we define our own
5
5
 
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.0;
2
+ pragma solidity ^0.8;
3
3
 
4
4
  // OpenZeppelin doesn't export any interfaces for uupsUpgradeable so we define our own
5
5
 
@@ -3,8 +3,13 @@ pragma solidity ^0.8;
3
3
 
4
4
  import {Test} from "forge-std/Test.sol";
5
5
 
6
+ /// @title TestUtils
7
+ /// @notice WARNING: This contract contains TEST KEYS for LOCAL DEVELOPMENT ONLY.
8
+ /// @dev These keys are publicly known Anvil accounts and have NO security value.
9
+ /// NEVER use these keys on production networks - anyone can derive the private keys.
6
10
  contract TestUtils is Test {
7
11
 
12
+ // WARNING: Well-known Anvil account #0 - publicly known private key, DO NOT use in production
8
13
  address private constant ANVIL_ZEROTH_ADDRESS = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;
9
14
  uint256 private constant ANVIL_ZEROTH_PRIVATE_KEY =
10
15
  0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80;
@@ -20,7 +25,9 @@ contract TestUtils is Test {
20
25
  uint256 internal evePrivKey;
21
26
  address internal immutable eve;
22
27
 
23
- // it is convenient for e2e tests to use these well-known addresses for the TEE
28
+ // WARNING: These are well-known Anvil test keys with publicly known private keys.
29
+ // They are convenient for e2e tests but have NO security value.
30
+ // Deploy.s.sol has safeguards to prevent using these on non-test chains.
24
31
  address internal teeEOA = ANVIL_ZEROTH_ADDRESS;
25
32
  uint256 internal teePrivKey = ANVIL_ZEROTH_PRIVATE_KEY;
26
33
 
@@ -0,0 +1,171 @@
1
+ // SPDX-License-Identifier: No License
2
+ pragma solidity ^0.8;
3
+
4
+ import {IIncoLightning} from "../interfaces/IIncoLightning.sol";
5
+ /// forge-lint: disable-next-line(unused-import)
6
+ import {ETypes, elist, typeBitSize} from "../Types.sol";
7
+ import {euint256} from "../Types.sol";
8
+ import {IncoUtils, FEE, BIT_FEE} from "../periphery/IncoUtils.sol";
9
+
10
+ contract ElistTester is IncoUtils {
11
+
12
+ /// forge-lint: disable-next-line(screaming-snake-case-immutable)
13
+ IIncoLightning immutable inco;
14
+
15
+ constructor(IIncoLightning _inco) {
16
+ inco = _inco;
17
+ }
18
+
19
+ elist public list;
20
+ elist public newRangeList;
21
+
22
+ function newEList(bytes[] memory inputs, ETypes listType, address user)
23
+ public
24
+ payable
25
+ refundUnspent
26
+ returns (elist)
27
+ {
28
+ list = inco.newEList{value: FEE * inputs.length}(inputs, listType, user);
29
+ inco.allow(elist.unwrap(list), address(this));
30
+ inco.allow(elist.unwrap(list), address(msg.sender));
31
+ return list;
32
+ }
33
+
34
+ function listAppend(bytes memory ctValue) public payable refundUnspent returns (elist) {
35
+ euint256 handle = inco.newEuint256{value: FEE}(ctValue, msg.sender);
36
+ inco.allow(euint256.unwrap(handle), address(this));
37
+ inco.allow(euint256.unwrap(handle), address(msg.sender));
38
+ uint256 typeBits = typeBitSize(ETypes(uint8(uint256(elist.unwrap(list)) >> 16)));
39
+ list = inco.listAppend{value: (uint256(inco.lengthOf(elist.unwrap(list))) * typeBits + typeBits) * BIT_FEE}(
40
+ list, euint256.unwrap(handle)
41
+ );
42
+ inco.allow(elist.unwrap(list), address(this));
43
+ inco.allow(elist.unwrap(list), address(msg.sender));
44
+ return list;
45
+ }
46
+
47
+ function listGet(uint16 index) public returns (bytes32) {
48
+ bytes32 res = inco.listGet(list, index);
49
+ inco.allow(res, msg.sender);
50
+ return res;
51
+ }
52
+
53
+ function newEList(bytes32[] memory handles, ETypes listType) public payable refundUnspent returns (elist) {
54
+ list = inco.newEList{value: FEE * handles.length}(handles, listType);
55
+ inco.allow(elist.unwrap(list), address(this));
56
+ inco.allow(elist.unwrap(list), address(msg.sender));
57
+ return list;
58
+ }
59
+
60
+ function listGetOr(bytes memory ctIndex, bytes memory ctDefaultValue)
61
+ public
62
+ payable
63
+ refundUnspent
64
+ returns (bytes32)
65
+ {
66
+ euint256 index = inco.newEuint256{value: FEE}(ctIndex, msg.sender);
67
+ euint256 defaultValue = inco.newEuint256{value: FEE}(ctDefaultValue, msg.sender);
68
+ bytes32 res = inco.listGetOr(list, euint256.unwrap(index), euint256.unwrap(defaultValue));
69
+ inco.allow(res, msg.sender);
70
+ return res;
71
+ }
72
+
73
+ function listSet(bytes memory ctIndex, bytes memory ctValue) public payable refundUnspent returns (elist) {
74
+ euint256 index = inco.newEuint256{value: FEE}(ctIndex, msg.sender);
75
+ euint256 value = inco.newEuint256{value: FEE}(ctValue, msg.sender);
76
+ uint256 typeBits = typeBitSize(ETypes(uint8(uint256(elist.unwrap(list)) >> 16)));
77
+ list = inco.listSet{value: uint256(inco.lengthOf(elist.unwrap(list))) * typeBits * BIT_FEE}(
78
+ list, euint256.unwrap(index), euint256.unwrap(value)
79
+ );
80
+ inco.allow(elist.unwrap(list), address(this));
81
+ inco.allow(elist.unwrap(list), address(msg.sender));
82
+ return list;
83
+ }
84
+
85
+ function listInsert(bytes memory ctIndex, bytes memory ctValue) public payable refundUnspent returns (elist) {
86
+ euint256 index = inco.newEuint256{value: FEE}(ctIndex, msg.sender);
87
+ euint256 value = inco.newEuint256{value: FEE}(ctValue, msg.sender);
88
+ uint256 typeBits = typeBitSize(ETypes(uint8(uint256(elist.unwrap(list)) >> 16)));
89
+ list = inco.listInsert{value: (uint256(inco.lengthOf(elist.unwrap(list))) * typeBits + typeBits) * BIT_FEE}(
90
+ list, euint256.unwrap(index), euint256.unwrap(value)
91
+ );
92
+ inco.allow(elist.unwrap(list), address(this));
93
+ inco.allow(elist.unwrap(list), address(msg.sender));
94
+ return list;
95
+ }
96
+
97
+ function listConcat(bytes[] memory cts, ETypes listType, address user)
98
+ public
99
+ payable
100
+ refundUnspent
101
+ returns (elist)
102
+ {
103
+ elist rhs = inco.newEList{value: FEE * cts.length}(cts, listType, user);
104
+ inco.allow(elist.unwrap(rhs), address(this));
105
+ inco.allow(elist.unwrap(rhs), address(msg.sender));
106
+ uint256 lhsBits =
107
+ uint256(inco.lengthOf(elist.unwrap(list))) * typeBitSize(ETypes(uint8(uint256(elist.unwrap(list)) >> 16)));
108
+ uint256 rhsBits =
109
+ uint256(inco.lengthOf(elist.unwrap(rhs))) * typeBitSize(ETypes(uint8(uint256(elist.unwrap(rhs)) >> 16)));
110
+ list = inco.listConcat{value: (lhsBits + rhsBits) * BIT_FEE}(list, rhs);
111
+ inco.allow(elist.unwrap(list), address(this));
112
+ inco.allow(elist.unwrap(list), address(msg.sender));
113
+ return list;
114
+ }
115
+
116
+ function listSlice(bytes memory ctStart, uint16 len, bytes memory ctDefaultValue)
117
+ public
118
+ payable
119
+ refundUnspent
120
+ returns (elist)
121
+ {
122
+ euint256 start = inco.newEuint256{value: FEE}(ctStart, msg.sender);
123
+ euint256 defaultValue = inco.newEuint256{value: FEE}(ctDefaultValue, msg.sender);
124
+ uint256 typeBits = typeBitSize(ETypes(uint8(uint256(elist.unwrap(list)) >> 16)));
125
+ list = inco.listSlice{value: uint256(len) * typeBits * BIT_FEE}(
126
+ list, euint256.unwrap(start), len, euint256.unwrap(defaultValue)
127
+ );
128
+ inco.allow(elist.unwrap(list), address(this));
129
+ inco.allow(elist.unwrap(list), address(msg.sender));
130
+ return list;
131
+ }
132
+
133
+ function listRange(uint16 start, uint16 end, ETypes listType) public payable returns (elist) {
134
+ newRangeList =
135
+ inco.listRange{value: uint256(end - start) * typeBitSize(listType) * BIT_FEE}(start, end, listType);
136
+ inco.allow(elist.unwrap(newRangeList), address(this));
137
+ inco.allow(elist.unwrap(newRangeList), address(msg.sender));
138
+ return newRangeList;
139
+ }
140
+
141
+ function listGetRange(uint16 index) public returns (bytes32) {
142
+ bytes32 res = inco.listGet(newRangeList, index);
143
+ inco.allow(res, msg.sender);
144
+ return res;
145
+ }
146
+
147
+ function listShuffle() public payable refundUnspent returns (elist) {
148
+ uint256 typeBits = typeBitSize(ETypes(uint8(uint256(elist.unwrap(list)) >> 16)));
149
+ list = inco.listShuffle{value: uint256(inco.lengthOf(elist.unwrap(list))) * typeBits * BIT_FEE}(list);
150
+ inco.allow(elist.unwrap(list), address(this));
151
+ inco.allow(elist.unwrap(list), address(msg.sender));
152
+ return list;
153
+ }
154
+
155
+ function listReveal() public {
156
+ inco.reveal(elist.unwrap(list));
157
+ }
158
+
159
+ function listReverse() public payable returns (elist) {
160
+ uint256 typeBits = typeBitSize(ETypes(uint8(uint256(elist.unwrap(list)) >> 16)));
161
+ list = inco.listReverse{value: uint256(inco.lengthOf(elist.unwrap(list))) * typeBits * BIT_FEE}(list);
162
+ inco.allow(elist.unwrap(list), address(this));
163
+ inco.allow(elist.unwrap(list), address(msg.sender));
164
+ return list;
165
+ }
166
+
167
+ receive() external payable {
168
+ // Allow contract to receive ETH
169
+ }
170
+
171
+ }
@@ -14,9 +14,9 @@ contract FakeComputeServer {
14
14
  } else if (op == EOps.Mul) {
15
15
  return lhs * rhs;
16
16
  } else if (op == EOps.Div) {
17
- return lhs / rhs;
17
+ return rhs == 0 ? type(uint256).max : lhs / rhs;
18
18
  } else if (op == EOps.Rem) {
19
- return lhs % rhs;
19
+ return rhs == 0 ? lhs : lhs % rhs;
20
20
  } else if (op == EOps.Min) {
21
21
  return lhs < rhs ? lhs : rhs;
22
22
  } else if (op == EOps.Max) {
@@ -19,16 +19,16 @@ contract FakeIncoInfraBase is TestUtils, KVStore, HandleGeneration {
19
19
  {
20
20
  // We need a single word here to get correct encoding
21
21
  bytes memory ciphertext = abi.encode(word);
22
+ uint16 version = 2; // version - X-Wing
22
23
  bytes32 handle = getInputHandle(
23
24
  ciphertext,
24
25
  address(inco),
25
26
  user,
26
27
  contractAddress,
27
- 0,
28
- /* unspecified */
28
+ version, // version - X-Wing
29
29
  inputType
30
30
  );
31
- input = abi.encodePacked(int32(0), abi.encode(handle, ciphertext));
31
+ input = abi.encodePacked(uint32(version), abi.encode(handle, ciphertext));
32
32
  }
33
33
 
34
34
  function fakePrepareEuint256Ciphertext(uint256 value, address userAddress, address contractAddress)
@@ -46,10 +46,6 @@ contract MockOpHandler is FakeIncoInfraBase, FakeComputeServer {
46
46
  ebool value = ebool.wrap(log.topics[1]);
47
47
  ebool result = ebool.wrap(log.topics[2]);
48
48
  handleENot(value, result);
49
- } else if (op == EOps.Rand) {
50
- uint256 counter = uint256(log.topics[1]);
51
- euint256 result = euint256.wrap(log.topics[2]);
52
- handleERand(counter, result);
53
49
  } else if (op == EOps.RandBounded) {
54
50
  uint256 counter = uint256(log.topics[1]);
55
51
  euint256 upperBound = euint256.wrap(log.topics[2]);
@@ -85,12 +81,14 @@ contract MockOpHandler is FakeIncoInfraBase, FakeComputeServer {
85
81
  set(ebool.unwrap(result), asBytes32(!getBoolValue(value)));
86
82
  }
87
83
 
88
- function handleERand(uint256 counter, euint256 result) private {
89
- set(euint256.unwrap(result), bytes32(counter));
90
- }
91
-
92
84
  function handleERandBounded(uint256 counter, euint256 upperBound, euint256 result) private {
93
- set(euint256.unwrap(result), bytes32(counter % getUint256Value(upperBound)));
85
+ uint256 bound = getUint256Value(upperBound);
86
+ if (bound == 0) {
87
+ // upperBound of 0 means unbounded (used by rand())
88
+ set(euint256.unwrap(result), bytes32(counter));
89
+ } else {
90
+ set(euint256.unwrap(result), bytes32(counter % bound));
91
+ }
94
92
  }
95
93
 
96
94
  function handleIfThenElse(ebool control, bytes32 lhs, bytes32 rhs, bytes32 result) private {
@@ -60,7 +60,8 @@ contract MockRemoteAttestation is TestUtils {
60
60
  hex"010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101";
61
61
  // See DEFAULT_MR_AGGREGATED in attestation/src/remote_attestation.rs to
62
62
  // see the calculation of the default value.
63
- mrAggregated = hex"c3a67bac251d4946d7b17481d39631676042fe3afab06e70c22105ad8383c19f";
63
+ // Note: This uses abi.encode (not encodePacked) to avoid hash collision vulnerabilities.
64
+ mrAggregated = hex"3d48a1faa8620d86ae037f4fd6746987733d085314b3cd5d5d074ade8bab6ebd";
64
65
  bootstrapResult = BootstrapResult({networkPubkey: networkPubkey});
65
66
 
66
67
  quote = createQuote(mrtd, signer);
@@ -59,8 +59,6 @@ function getOpForSelector(bytes32 opEventSelector) pure returns (EOps) {
59
59
  return EOps.TrivialEncrypt;
60
60
  } else if (opEventSelector == EncryptedOperations.EIfThenElse.selector) {
61
61
  return EOps.IfThenElse;
62
- } else if (opEventSelector == EncryptedOperations.ERand.selector) {
63
- return EOps.Rand;
64
62
  } else if (opEventSelector == EncryptedOperations.ERandBounded.selector) {
65
63
  return EOps.RandBounded;
66
64
  } else if (opEventSelector == BaseAccessControlList.Allow.selector) {
@@ -12,11 +12,12 @@ import {FakeQuoteVerifier} from "./FakeIncoInfra/FakeQuoteVerifier.sol";
12
12
  import {IOwnable} from "../../src/shared/IOwnable.sol";
13
13
  import {MockRemoteAttestation} from "./FakeIncoInfra/MockRemoteAttestation.sol";
14
14
  import {BootstrapResult} from "../lightning-parts/TEELifecycle.types.sol";
15
+ import {Safe} from "safe-smart-account/Safe.sol";
16
+ import {SafeProxyFactory} from "safe-smart-account/proxies/SafeProxyFactory.sol";
15
17
 
16
18
  contract IncoTest is MockOpHandler, DeployUtils, FakeDecryptionAttester, MockRemoteAttestation {
17
19
 
18
- // forge-lint: disable-next-line(screaming-snake-case-immutable)
19
- address immutable owner;
20
+ address owner;
20
21
  // forge-lint: disable-next-line(screaming-snake-case-immutable)
21
22
  address immutable testDeployer;
22
23
 
@@ -31,7 +32,6 @@ contract IncoTest is MockOpHandler, DeployUtils, FakeDecryptionAttester, MockRem
31
32
  0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80;
32
33
 
33
34
  constructor() {
34
- owner = getLabeledAddress("owner");
35
35
  // extracted from the deploy script running as bare simulation with:
36
36
  // forge script src/script/Deploy.s.sol:Deploy
37
37
  testDeployer = deployedBy;
@@ -42,17 +42,29 @@ contract IncoTest is MockOpHandler, DeployUtils, FakeDecryptionAttester, MockRem
42
42
 
43
43
  function setUp() public virtual {
44
44
  deployCreateX();
45
+
46
+ // Create a Safe multisig (alice, bob, carol) with threshold 2 to act as owner
47
+ Safe master = new Safe();
48
+ SafeProxyFactory factory = new SafeProxyFactory();
49
+ address[] memory safeOwners = new address[](3);
50
+ safeOwners[0] = alice;
51
+ safeOwners[1] = bob;
52
+ safeOwners[2] = carol;
53
+ bytes memory setupData = abi.encodeWithSelector(
54
+ Safe.setup.selector, safeOwners, 2, address(0), bytes(""), address(0), address(0), 0, payable(address(0))
55
+ );
56
+ owner = address(Safe(payable(factory.createProxyWithNonce(address(master), setupData, 0))));
57
+
45
58
  vm.startPrank(testDeployer);
46
59
  vm.setEnv("SHOULD_SETUP_TEE_SIGNER", "true"); // results in a network pubkey and decrypt signer being populated in the TEE Lifecycle
47
60
  (IIncoLightning proxy,) = deployIncoLightningUsingConfig({
48
61
  deployer: testDeployer,
62
+ owner: owner,
49
63
  // The highest precedent deployment
50
64
  // We select the pepper that will be used that will be generated in the lib.sol (usually "testnet"), but currently "alphanet" has higher major version
51
65
  pepper: "devnet",
52
66
  quoteVerifier: new FakeQuoteVerifier()
53
67
  });
54
- IOwnable(address(proxy)).transferOwnership(owner);
55
- IOwnable(address(inco.incoVerifier())).transferOwnership(owner);
56
68
  vm.stopPrank();
57
69
  console.log("Deployed %s (proxy) to: %s", proxy.getName(), address(proxy));
58
70
  console.log("Generated inco address: %s", address(inco));
@@ -380,8 +380,9 @@ contract OpsTest is Fee {
380
380
 
381
381
  // ============ RANDOM NUMBER GENERATION ============
382
382
 
383
- function testRand() external payable returns (euint256) {
384
- euint256 result = euint256.wrap(inco.eRand{value: getFee()}(ETypes.Uint256));
383
+ function testRandUnbounded() external payable returns (euint256) {
384
+ euint256 result =
385
+ euint256.wrap(inco.eRandBounded{value: getFee()}(euint256.unwrap(inco.asEuint256(0)), ETypes.Uint256));
385
386
  inco.allow(euint256.unwrap(result), address(this));
386
387
  inco.allow(euint256.unwrap(result), msg.sender);
387
388
  return result;