diff --git a/bun.lock b/bun.lock index 7369f4b..bcb0d58 100644 --- a/bun.lock +++ b/bun.lock @@ -27,7 +27,7 @@ "contracts": { "name": "lightning-rod-contracts", "dependencies": { - "@inco/lightning": "0.6.8", + "@inco/lightning": "latest", "@openzeppelin/contracts": "^5.3.0", "ds-test": "https://github.com/dapphub/ds-test", "forge-std": "https://github.com/foundry-rs/forge-std", @@ -459,6 +459,10 @@ "zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="], + "@inco/lightning/ds-test": ["ds-test@github:dapphub/ds-test#e282159", {}, "dapphub-ds-test-e282159"], + + "@inco/lightning/forge-std": ["forge-std@github:foundry-rs/forge-std#799589b", {}, "foundry-rs-forge-std-799589b"], + "@inco/shared/ds-test": ["ds-test@github:dapphub/ds-test#e282159", {}, "dapphub-ds-test-e282159"], "@inco/shared/forge-std": ["forge-std@github:foundry-rs/forge-std#27ab851", {}, "foundry-rs-forge-std-27ab851"], diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 67c248d..1495410 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -1,6 +1,8 @@ [profile.default] src = 'src' -test = 'src' +test = 'src/test' +test_match = '*.t.sol' +no_match_path = 'src/LibTest.sol' allow_paths = ['../'] evm_version = 'cancun' solc = '0.8.28' diff --git a/contracts/package.json b/contracts/package.json index 17fcf3f..365e469 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -2,7 +2,7 @@ "name": "lightning-rod-contracts", "private": true, "dependencies": { - "@inco/lightning": "0.6.8", + "@inco/lightning": "0.7.0", "@openzeppelin/contracts": "^5.3.0", "ds-test": "https://github.com/dapphub/ds-test", "forge-std": "https://github.com/foundry-rs/forge-std" diff --git a/contracts/src/SimpleConfidentialToken.sol b/contracts/src/SimpleConfidentialToken.sol index edbbed5..4d33a9c 100644 --- a/contracts/src/SimpleConfidentialToken.sol +++ b/contracts/src/SimpleConfidentialToken.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8; // This line of import is all you need to get started with Inco -import {euint256, ebool, e} from "@inco/lightning/src/Lib.sol"; +import {euint256, ebool, e, inco} from "@inco/lightning/src/Lib.sol"; /// @notice a fungible token whose balances and transfer values are confidential contract SimpleConfidentialToken { @@ -27,7 +27,8 @@ contract SimpleConfidentialToken { // this function is meant to be called by EOAs or smart wallets as valueInput is an encrypted amount that should // be generated using @inco/js sdk - function transfer(address to, bytes memory valueInput) external returns (ebool) { + function transfer(address to, bytes memory valueInput) external payable returns (ebool) { + require(msg.value == inco.getFee(),"Fee not paid"); // `newInput` returns an euint256 from an encrypted input, if the encrypted input is malformed, it will return // an euint256 with a value of 0. Depending on how malformed the input is, an external observer may know // that the fallback 0 value has been returned. Just use the js sdk to avoid that. diff --git a/contracts/src/test/TestSimpleConfidentialToken.t.sol b/contracts/src/test/TestSimpleConfidentialToken.t.sol index 10a064a..eb96904 100644 --- a/contracts/src/test/TestSimpleConfidentialToken.t.sol +++ b/contracts/src/test/TestSimpleConfidentialToken.t.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8; import {SimpleConfidentialToken} from "../SimpleConfidentialToken.sol"; import {IncoTest} from "@inco/lightning/src/test/IncoTest.sol"; import {GWEI} from "@inco/lightning/src/shared/TypeUtils.sol"; // 1 GWEI = 1e9 +import {console} from "forge-std/console.sol"; +import {inco, euint256, e} from "@inco/lightning/src/Lib.sol"; // IncoTest extends forge-std's Test contract TestSimpleConfidentialToken is IncoTest { @@ -13,18 +15,35 @@ contract TestSimpleConfidentialToken is IncoTest { // always call the parent setUp() function, which deploys the mocked Inco infrastructure super.setUp(); token = new SimpleConfidentialToken(); - // use `fakePrepareEuint256Ciphertext` to simulate producing a ciphertext using the @inco/js sdk - token.transfer(alice, fakePrepareEuint256Ciphertext(10 * GWEI, alice, address(token))); + vm.deal(address(this), inco.getFee()); + + // Transfer 10 GWEI from the test contract (which received the initial mint) to Alice + // The test contract can use the euint256 version of transfer since it's a contract + euint256 transferAmount = e.asEuint256(10 * GWEI); + // Allow the test contract (sender) to use this value for the authorization check + // and allow the token contract to use this value in computations + e.allow(transferAmount, address(this)); + e.allow(transferAmount, address(token)); + token.transfer(alice, transferAmount); + processAllOperations(); + + // Verify Alice's balance + vm.prank(alice); + uint256 decryptedAliceBalance = getUint256Value(token.balanceOf(alice)); + assertEq(decryptedAliceBalance, 10 * GWEI); } function testTransfer() public { - vm.prank(alice); - token.transfer(bob, fakePrepareEuint256Ciphertext(1 * GWEI, bob, address(token))); + vm.deal(address(alice), inco.getFee()); + bytes memory ciphertext = fakePrepareEuint256Ciphertext(1 * GWEI, alice, address(token)); + vm.startPrank(alice); + token.transfer{value: inco.getFee()}(bob, ciphertext); + vm.stopPrank(); + processAllOperations(); // Inco processes the operations over encrypted variables asynchronously offchain. // call processAllOperations() to simulate this offchain processing, which will assign to each e-variable // its encrypted value. if you don't call this function and try to simulate a decrypt on a handle // resulting from an operation, it will revert. - processAllOperations(); // `getUint256Value` is a cheatcode returning the decrypted value of an euint256, without checking // any access rights, it is useful in tests and doesn't exist in prod. uint256 decryptedBobBalance = getUint256Value(token.balanceOf(bob));