「🏗️」 wip(wallet): seemingly working
This commit is contained in:
8
Justfile
8
Justfile
@ -2,10 +2,16 @@
|
|||||||
@default:
|
@default:
|
||||||
just -l
|
just -l
|
||||||
|
|
||||||
|
@build:
|
||||||
|
forge build
|
||||||
|
|
||||||
# To lanch the tests via foundry-rs
|
# To lanch the tests via foundry-rs
|
||||||
@test:
|
@test:
|
||||||
forge test
|
forge test -vv
|
||||||
|
|
||||||
# To generate the ABI in the deployment/ folder
|
# To generate the ABI in the deployment/ folder
|
||||||
@abi-gen:
|
@abi-gen:
|
||||||
solc --abi code/Kanel42_token.sol -o deployment --overwrite
|
solc --abi code/Kanel42_token.sol -o deployment --overwrite
|
||||||
|
|
||||||
|
@fmt:
|
||||||
|
forge fmt
|
||||||
|
@ -42,9 +42,9 @@ contract Kanel42_token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mint(uint256 _value) public {
|
function mint(uint256 _value) public {
|
||||||
if ((totalSupply / 16) <= _value) {
|
if ((totalSupply / 16) <= _value) {
|
||||||
revert("can't mint more than 1/16 of the supply at a time");
|
revert("can't mint more than 1/16 of the supply at a time");
|
||||||
}
|
}
|
||||||
|
|
||||||
balanceOf[msg.sender] += _value;
|
balanceOf[msg.sender] += _value;
|
||||||
totalMinted += _value;
|
totalMinted += _value;
|
||||||
@ -52,7 +52,7 @@ contract Kanel42_token {
|
|||||||
emit Transfer(address(0), msg.sender, _value);
|
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(
|
event Approval(
|
||||||
address indexed _owner, address indexed _spender, uint256 _value
|
address indexed _owner, address indexed _spender, uint256 _value
|
||||||
);
|
);
|
||||||
|
111
code/knlWallet.sol
Normal file
111
code/knlWallet.sol
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
57
code/test/KNL_wallet.t.sol
Normal file
57
code/test/KNL_wallet.t.sol
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ contract Kanel42TokenTest is Test {
|
|||||||
// This function runs before each test
|
// This function runs before each test
|
||||||
function setUp() public {
|
function setUp() public {
|
||||||
token = new Kanel42_token();
|
token = new Kanel42_token();
|
||||||
vm.deal(address(token), 1 ether);
|
vm.deal(address(token), 1 ether);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the initial supply of the token
|
// Test the initial supply of the token
|
||||||
@ -20,40 +20,25 @@ contract Kanel42TokenTest is Test {
|
|||||||
assertEq(token.totalMinted(), 0);
|
assertEq(token.totalMinted(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMint() public {
|
function testMint() public {
|
||||||
// Define the amount of ether to send for minting
|
// Define the amount of ether to send for minting
|
||||||
uint256 mintAmount = 1 * (10 ** token.decimals());
|
uint256 mintAmount = 1 * (10 ** token.decimals());
|
||||||
|
|
||||||
// Get the initial balance of the sender
|
// Get the initial balance of the sender
|
||||||
uint256 initialBalance = token.balanceOf(address(this));
|
uint256 initialBalance = token.balanceOf(address(this));
|
||||||
|
|
||||||
// Mint tokens by sending ether
|
// Mint tokens by sending ether
|
||||||
token.mint(mintAmount);
|
token.mint(mintAmount);
|
||||||
|
|
||||||
// Check if the balance increased as expected
|
// Check if the balance increased as expected
|
||||||
uint256 expectedMintedAmount = mintAmount;
|
uint256 expectedMintedAmount = mintAmount;
|
||||||
uint256 finalBalance = token.balanceOf(address(this));
|
uint256 finalBalance = token.balanceOf(address(this));
|
||||||
assertEq(finalBalance - initialBalance, expectedMintedAmount, "Minted amount is incorrect");
|
assertEq(
|
||||||
}
|
finalBalance - initialBalance,
|
||||||
|
expectedMintedAmount,
|
||||||
function testBurn() public {
|
"Minted amount is incorrect"
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test transferring tokens
|
// Test transferring tokens
|
||||||
function testTransfer() public {
|
function testTransfer() public {
|
||||||
|
Reference in New Issue
Block a user