From 164f8b80c83534bbb20e0b1235d04ad962f8f249 Mon Sep 17 00:00:00 2001 From: adjoly Date: Sun, 10 Aug 2025 20:03:08 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20wip(w?= =?UTF-8?q?allet):=20seemingly=20working?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Justfile | 8 ++- code/KNL_wallet.sol | 0 code/Kanel42_token.sol | 8 +-- code/knlWallet.sol | 111 ++++++++++++++++++++++++++++++++++ code/test/KNL_wallet.t.sol | 57 +++++++++++++++++ code/test/Kanel42_token.t.sol | 49 ++++++--------- 6 files changed, 196 insertions(+), 37 deletions(-) delete mode 100644 code/KNL_wallet.sol create mode 100644 code/knlWallet.sol create mode 100644 code/test/KNL_wallet.t.sol diff --git a/Justfile b/Justfile index 28550d4..1c7e841 100644 --- a/Justfile +++ b/Justfile @@ -2,10 +2,16 @@ @default: just -l +@build: + forge build + # To lanch the tests via foundry-rs @test: - forge test + forge test -vv # To generate the ABI in the deployment/ folder @abi-gen: solc --abi code/Kanel42_token.sol -o deployment --overwrite + +@fmt: + forge fmt diff --git a/code/KNL_wallet.sol b/code/KNL_wallet.sol deleted file mode 100644 index e69de29..0000000 diff --git a/code/Kanel42_token.sol b/code/Kanel42_token.sol index feec27d..c18e4e9 100644 --- a/code/Kanel42_token.sol +++ b/code/Kanel42_token.sol @@ -42,9 +42,9 @@ contract Kanel42_token { } function mint(uint256 _value) public { - if ((totalSupply / 16) <= _value) { - revert("can't mint more than 1/16 of the supply at a time"); - } + if ((totalSupply / 16) <= _value) { + revert("can't mint more than 1/16 of the supply at a time"); + } balanceOf[msg.sender] += _value; totalMinted += _value; @@ -52,7 +52,7 @@ contract Kanel42_token { emit Transfer(address(0), msg.sender, _value); } - event Transfer(address indexed _from, address indexed _to, uint256 _value); + event Transfer(address indexed _from, address indexed _to, uint256 _value); event Approval( address indexed _owner, address indexed _spender, uint256 _value ); diff --git a/code/knlWallet.sol b/code/knlWallet.sol new file mode 100644 index 0000000..9848123 --- /dev/null +++ b/code/knlWallet.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.28; + +import "./lib/forge-std/src/interfaces/IERC20.sol"; + +contract knlWallet { + struct Transaction { + address destination; + uint256 value; + bool executed; + address tokenAddress; + } + + address[] public owners; + uint256 public required; + + uint256 public transactionCount; + mapping(uint256 => Transaction) public transactions; + mapping(uint256 => mapping(address => bool)) public confirmations; + + constructor(address[] memory _owners, uint256 _confirmations) { + require(_owners.length > 0, "need to have owners"); + require(_confirmations > 0, "need to have a number of confirmation"); + require( + _confirmations <= _owners.length, + "need to have more or equals owners than confirmation" + ); + + owners = _owners; + required = _confirmations; + } + + modifier isOwner() { + for (uint256 i = 0; i < owners.length; i++) { + if (owners[i] == msg.sender) { + _; + return; + } + } + revert("need to be owner"); + } + + receive() external payable { } + + function isConfirmed(uint256 transactionId) public view returns (bool) { + return getConfirmationsCount(transactionId) >= required; + } + + function getConfirmationsCount(uint256 transactionId) + public + view + returns (uint256) + { + uint256 count; + for (uint256 i = 0; i < owners.length; i++) { + if (confirmations[transactionId][owners[i]]) { + count++; + } + } + return count; + } + + function addTransaction( + address destination, + uint256 value, + address tokenAddress + ) public isOwner returns (uint256) { + transactions[transactionCount] = + Transaction(destination, value, false, tokenAddress); + + transactionCount += 1; + return transactionCount - 1; + } + + function confirmTransaction(uint256 transactionId) public isOwner { + confirmations[transactionId][msg.sender] = true; + if (isConfirmed(transactionId)) { + executeTransaction(transactionId); + } + } + + function submitTransaction( + address payable dest, + uint256 value, + address tokenAddress + ) external isOwner { + uint256 id = addTransaction(dest, value, tokenAddress); + confirmTransaction(id); + } + + function executeTransaction(uint256 transactionId) public isOwner { + require(isConfirmed(transactionId), "transaction has not been confirmed"); + Transaction storage _tx = transactions[transactionId]; + + if (_tx.tokenAddress == address(0)) { + // Handle Ether transfer + (bool success,) = _tx.destination.call{ value: _tx.value }(""); + require(success); + } else { + // Handle ERC-20 token transfer + IERC20 token = IERC20(_tx.tokenAddress); + require( + token.transfer(_tx.destination, _tx.value), + "Failed to transfer ERC20 tokens" + ); + } + + _tx.executed = true; + } +} diff --git a/code/test/KNL_wallet.t.sol b/code/test/KNL_wallet.t.sol new file mode 100644 index 0000000..528f95f --- /dev/null +++ b/code/test/KNL_wallet.t.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "../lib/forge-std/src/Test.sol"; +import { console } from "../lib/forge-std/src/console.sol"; +import "../knlWallet.sol"; +import "../Kanel42_token.sol"; + +contract KNLwalletTest is Test { + Kanel42_token public token; + knlWallet public wallet; + + address owner1 = address(1); + address owner2 = address(2); + address owner3 = address(3); + address owner4 = address(4); + + address to = address(5); + + function setUp() public { + address[] memory owners = new address[](4); + owners[0] = owner1; + owners[1] = owner2; + owners[2] = owner3; + owners[3] = owner4; + wallet = new knlWallet(owners, 3); + token = new Kanel42_token(); + + console.log(wallet.owners(0)); + + token.mint(10 * (10 ** token.decimals())); + vm.prank(owner3); + token.mint(4 * (10 ** token.decimals())); + token.transfer(address(wallet), 4 * (10 ** token.decimals())); + } + + function testAdd() public { + vm.prank(owner1); + wallet.addTransaction(payable(to), 1, address(token)); + } + + function testConfirm() public { + vm.prank(owner1); + wallet.submitTransaction(payable(to), 1, address(token)); + + uint tr = wallet.transactionCount() - 1; + + vm.prank(owner2); + wallet.confirmTransaction(tr); + + vm.prank(owner3); + wallet.confirmTransaction(tr); + + vm.prank(owner4); + wallet.confirmTransaction(tr); + } +} diff --git a/code/test/Kanel42_token.t.sol b/code/test/Kanel42_token.t.sol index bf837d1..e81f797 100644 --- a/code/test/Kanel42_token.t.sol +++ b/code/test/Kanel42_token.t.sol @@ -11,7 +11,7 @@ contract Kanel42TokenTest is Test { // This function runs before each test function setUp() public { token = new Kanel42_token(); - vm.deal(address(token), 1 ether); + vm.deal(address(token), 1 ether); } // Test the initial supply of the token @@ -20,40 +20,25 @@ contract Kanel42TokenTest is Test { assertEq(token.totalMinted(), 0); } - function testMint() public { - // Define the amount of ether to send for minting - uint256 mintAmount = 1 * (10 ** token.decimals()); + function testMint() public { + // Define the amount of ether to send for minting + uint256 mintAmount = 1 * (10 ** token.decimals()); - // Get the initial balance of the sender - uint256 initialBalance = token.balanceOf(address(this)); + // Get the initial balance of the sender + uint256 initialBalance = token.balanceOf(address(this)); - // Mint tokens by sending ether - token.mint(mintAmount); + // Mint tokens by sending ether + token.mint(mintAmount); - // Check if the balance increased as expected - uint256 expectedMintedAmount = mintAmount; - uint256 finalBalance = token.balanceOf(address(this)); - assertEq(finalBalance - initialBalance, expectedMintedAmount, "Minted amount is incorrect"); - } - - function testBurn() public { - // First, mint some tokens to burn - uint256 mintAmount = 1 * (10 ** token.decimals()); - token.mint(mintAmount); - - // Get the initial balance of the sender - uint256 initialBalance = token.balanceOf(address(this)); - - // Define the amount of tokens to burn - uint256 burnAmount = mintAmount; - - // Burn tokens - token.burn(burnAmount); - - // Check if the balance decreased as expected - uint256 finalBalance = token.balanceOf(address(this)); - assertEq(initialBalance - finalBalance, burnAmount, "Burned amount is incorrect"); - } + // Check if the balance increased as expected + uint256 expectedMintedAmount = mintAmount; + uint256 finalBalance = token.balanceOf(address(this)); + assertEq( + finalBalance - initialBalance, + expectedMintedAmount, + "Minted amount is incorrect" + ); + } // Test transferring tokens function testTransfer() public {