From c35a05e774cf33d287de2dbe187dac4b317bb52b Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Wed, 19 Jun 2024 02:37:22 +0300 Subject: [PATCH 01/10] fix build --- lib/forge-std | 2 +- test/BTCDepositAddressDeriver.t.sol | 6 +++++- test/Bech32m.t.sol | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/forge-std b/lib/forge-std index bb4ceea..978ac6f 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit bb4ceea94d6f10eeb5b41dc2391c6c8bf8e734ef +Subproject commit 978ac6fadb62f5f0b723c996f64be52eddba6801 diff --git a/test/BTCDepositAddressDeriver.t.sol b/test/BTCDepositAddressDeriver.t.sol index a4ca5a5..c7bc203 100644 --- a/test/BTCDepositAddressDeriver.t.sol +++ b/test/BTCDepositAddressDeriver.t.sol @@ -6,6 +6,10 @@ import {Test} from "forge-std/Test.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; contract BTCDepositAddressDeriverTest is Test { + // We declare event SeedChanged second time here because Solidity + // does not allow importing events from other contracts. + // https://ethereum.stackexchange.com/questions/52967/can-a-contract-emit-another-contracts-event + event SeedChanged(string btcAddr1, string btcAddr2, string hrp); BTCDepositAddressDeriver deriver; @@ -54,7 +58,7 @@ contract BTCDepositAddressDeriverTest is Test { assertEq(deriver.p2y(), 0); vm.expectEmit(address(deriver)); - emit BTCDepositAddressDeriver.SeedChanged( + emit SeedChanged( "tb1p7g532zgvuzv8fz3hs02wvn2almqh8qyvz4xdr564nannkxh28kdq62ewy3", "tb1psfpmk6v8cvd8kr4rdda0l8gwyn42v5yfjlqkhnureprgs5tuumkqvdkewz", "tb" diff --git a/test/Bech32m.t.sol b/test/Bech32m.t.sol index 3b32b2b..cf58ae8 100644 --- a/test/Bech32m.t.sol +++ b/test/Bech32m.t.sol @@ -1,5 +1,5 @@ // Solidity Version: ^0.8.13 -pragma solidity ^0.8.13; +pragma solidity ^0.8.19; import {Test, console} from "forge-std/Test.sol"; import {Bech32m} from "../src/Bech32m.sol"; From 4032226842d99e31e24de8100492684f9b883a5e Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Wed, 19 Jun 2024 05:50:42 +0300 Subject: [PATCH 02/10] fix --- .gitignore | 5 ++- .gitmodules | 3 ++ foundry.toml | 6 ++- lib/openzeppelin-contracts | 1 + remappings.txt | 5 +++ script/Deploy.s.sol | 5 +++ script/SetSeed.s.sol | 86 +++++++++++++++++++++++++++++++++++--- 7 files changed, 103 insertions(+), 8 deletions(-) create mode 160000 lib/openzeppelin-contracts create mode 100644 remappings.txt diff --git a/.gitignore b/.gitignore index 914b160..6e292f6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,7 @@ docs/ # Dotenv file .env -__pycache__ \ No newline at end of file +__pycache__ + +.vscode +temp/ diff --git a/.gitmodules b/.gitmodules index 59dbe0d..6afefa7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/elliptic-curve-solidity"] path = lib/elliptic-curve-solidity url = https://github.com/witnet/elliptic-curve-solidity +[submodule "lib/openzeppelin-contracts"] + path = lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/foundry.toml b/foundry.toml index 82ecc54..26cd866 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,7 +1,11 @@ [profile.default] +solc = "0.8.25" src = "src" out = "out" libs = ["lib"] -fs_permissions = [{ access = "read", path = "./broadcast" }] +fs_permissions = [ + { access = "read", path = "./broadcast" }, + { access = "read-write", path = "./temp" } +] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts new file mode 160000 index 0000000..dbb6104 --- /dev/null +++ b/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit dbb6104ce834628e473d2173bbc9d47f81a9eec3 diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 0000000..c592c9b --- /dev/null +++ b/remappings.txt @@ -0,0 +1,5 @@ +ds-test/=forge-std/lib/ds-test/src/ +elliptic-curve-solidity/=lib/elliptic-curve-solidity/ +forge-std/=lib/forge-std/src/ +foundry-devops/=lib/foundry-devops/ +@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ \ No newline at end of file diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 766bdf9..f6caef2 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -3,13 +3,18 @@ pragma solidity ^0.8.19; import { Script } from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; contract Deploy is Script { function run() external returns (BTCDepositAddressDeriver) { vm.startBroadcast(); BTCDepositAddressDeriver btcDepositAddressDeriver = new BTCDepositAddressDeriver(); vm.stopBroadcast(); + string memory addressFileName = string.concat("./temp/", "BTCDepositAddressDeriver", ".", Strings.toString(block.chainid), ".address"); + string memory addressStr = Strings.toHexString(address(btcDepositAddressDeriver)); + vm.writeFile(addressFileName, addressStr); return btcDepositAddressDeriver; } } \ No newline at end of file diff --git a/script/SetSeed.s.sol b/script/SetSeed.s.sol index f512bf4..f1f9efe 100644 --- a/script/SetSeed.s.sol +++ b/script/SetSeed.s.sol @@ -6,14 +6,84 @@ import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; contract SetSeed is Script { + // https://www.educative.io/answers/how-to-compare-two-strings-in-solidity + function areStringsEqual( + string memory str1, + string memory str2 + ) public pure returns (bool) { + return + keccak256(abi.encodePacked(str1)) == + keccak256(abi.encodePacked(str2)); + } + + // https://stackoverflow.com/questions/69551020/trying-to-convert-address-string-to-type-address-in-solidity + function fromHexChar(uint8 c) public pure returns (uint8) { + if (bytes1(c) >= bytes1('0') && bytes1(c) <= bytes1('9')) { + return c - uint8(bytes1('0')); + } + if (bytes1(c) >= bytes1('a') && bytes1(c) <= bytes1('f')) { + return 10 + c - uint8(bytes1('a')); + } + if (bytes1(c) >= bytes1('A') && bytes1(c) <= bytes1('F')) { + return 10 + c - uint8(bytes1('A')); + } + return 0; + } + + // https://stackoverflow.com/questions/69551020/trying-to-convert-address-string-to-type-address-in-solidity + function hexStringToAddress(string memory s) public pure returns (bytes memory) { + bytes memory ss = bytes(s); + require(ss.length%2 == 0); // length must be even + bytes memory r = new bytes(ss.length/2); + for (uint i=0; i= 1 + 20, "toAddress_outOfBounds"); + address tempAddress; + + assembly { + tempAddress := div(mload(add(add(_bytes, 0x20), 1)), 0x1000000000000000000000000) + } + + return tempAddress; + } + function run() external { // get contract address - address contractAddress = DevOpsTools.get_most_recent_deployment( - "BTCDepositAddressDeriver", - block.chainid + // if environmental variable is set then use its value + // otherwise try get value from the latest deployment + address contractAddress; + string memory contractAddressStr = vm.envOr( + "CONTRACT_ADDR", + string("") ); + if (!areStringsEqual(contractAddressStr, "")) { + contractAddress = vm.envAddress("CONTRACT_ADDR"); + } else { + string memory addressFileName = string.concat( + "./temp/", + "BTCDepositAddressDeriver", + ".", + Strings.toString(block.chainid), + ".address" + ); + contractAddressStr = vm.readLine(addressFileName); + console.log("contractAddressStr", contractAddressStr); + contractAddress = toAddress(contractAddressStr); + } + console.log("contractAddress", contractAddress); // get first validators' joint pubkey @@ -25,8 +95,8 @@ contract SetSeed is Script { console.log("BTC_ADDR2:", btcAddr2); // get network - uint network = vm.envUint("Network"); - console.log("Network:", network); + uint network = vm.envUint("BTC_NETWORK"); + console.log("BTC_NETWORK:", network); BTCDepositAddressDeriver deriver = BTCDepositAddressDeriver( contractAddress @@ -34,7 +104,11 @@ contract SetSeed is Script { // set validators' pubkeys and network prefix vm.startBroadcast(); - deriver.setSeed(btcAddr1, btcAddr2, BTCDepositAddressDeriver.BitcoinNetwork(network)); + deriver.setSeed( + btcAddr1, + btcAddr2, + BTCDepositAddressDeriver.BitcoinNetwork(network) + ); vm.stopBroadcast(); } } From cc0471711d21fc31a7287527845a016bba7e8caa Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Thu, 20 Jun 2024 03:20:10 +0300 Subject: [PATCH 03/10] fix scripts --- script/Deploy.s.sol | 10 ++-- script/SetSeed.s.sol | 79 ++++++----------------------- src/AddressReaderWriter.sol | 37 ++++++++++++++ src/BTCDepositAddressDeriver.sol | 5 +- src/Tools.sol | 66 ++++++++++++++++++++++++ test/BTCDepositAddressDeriver.t.sol | 22 ++++++++ 6 files changed, 148 insertions(+), 71 deletions(-) create mode 100644 src/AddressReaderWriter.sol create mode 100644 src/Tools.sol diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index f6caef2..7141aa6 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -1,20 +1,20 @@ // SPDX-LICENSE-IDENTIFIER: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; import { Script } from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; +import {Tools} from "../src/Tools.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {AddressReaderWriter} from "../src/AddressReaderWriter.sol"; -contract Deploy is Script { +contract Deploy is Script, AddressReaderWriter { function run() external returns (BTCDepositAddressDeriver) { vm.startBroadcast(); BTCDepositAddressDeriver btcDepositAddressDeriver = new BTCDepositAddressDeriver(); vm.stopBroadcast(); - string memory addressFileName = string.concat("./temp/", "BTCDepositAddressDeriver", ".", Strings.toString(block.chainid), ".address"); - string memory addressStr = Strings.toHexString(address(btcDepositAddressDeriver)); - vm.writeFile(addressFileName, addressStr); + writeContractAddress("BTCDepositAddressDeriver", address(btcDepositAddressDeriver)); return btcDepositAddressDeriver; } } \ No newline at end of file diff --git a/script/SetSeed.s.sol b/script/SetSeed.s.sol index f1f9efe..dc065b8 100644 --- a/script/SetSeed.s.sol +++ b/script/SetSeed.s.sol @@ -1,65 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; +import {Tools} from "../src/Tools.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {AddressReaderWriter} from "../src/AddressReaderWriter.sol"; +import {console} from "forge-std/console.sol"; -contract SetSeed is Script { - // https://www.educative.io/answers/how-to-compare-two-strings-in-solidity - function areStringsEqual( - string memory str1, - string memory str2 - ) public pure returns (bool) { - return - keccak256(abi.encodePacked(str1)) == - keccak256(abi.encodePacked(str2)); - } - - // https://stackoverflow.com/questions/69551020/trying-to-convert-address-string-to-type-address-in-solidity - function fromHexChar(uint8 c) public pure returns (uint8) { - if (bytes1(c) >= bytes1('0') && bytes1(c) <= bytes1('9')) { - return c - uint8(bytes1('0')); - } - if (bytes1(c) >= bytes1('a') && bytes1(c) <= bytes1('f')) { - return 10 + c - uint8(bytes1('a')); - } - if (bytes1(c) >= bytes1('A') && bytes1(c) <= bytes1('F')) { - return 10 + c - uint8(bytes1('A')); - } - return 0; - } - - // https://stackoverflow.com/questions/69551020/trying-to-convert-address-string-to-type-address-in-solidity - function hexStringToAddress(string memory s) public pure returns (bytes memory) { - bytes memory ss = bytes(s); - require(ss.length%2 == 0); // length must be even - bytes memory r = new bytes(ss.length/2); - for (uint i=0; i= 1 + 20, "toAddress_outOfBounds"); - address tempAddress; - - assembly { - tempAddress := div(mload(add(add(_bytes, 0x20), 1)), 0x1000000000000000000000000) - } - - return tempAddress; - } - +contract SetSeed is Script, AddressReaderWriter { function run() external { // get contract address // if environmental variable is set then use its value @@ -69,19 +21,12 @@ contract SetSeed is Script { "CONTRACT_ADDR", string("") ); - if (!areStringsEqual(contractAddressStr, "")) { + if (!Tools.areStringsEqual(contractAddressStr, "")) { contractAddress = vm.envAddress("CONTRACT_ADDR"); } else { - string memory addressFileName = string.concat( - "./temp/", - "BTCDepositAddressDeriver", - ".", - Strings.toString(block.chainid), - ".address" + contractAddress = readContractAddress( + "BTCDepositAddressDeriver" ); - contractAddressStr = vm.readLine(addressFileName); - console.log("contractAddressStr", contractAddressStr); - contractAddress = toAddress(contractAddressStr); } console.log("contractAddress", contractAddress); @@ -101,14 +46,20 @@ contract SetSeed is Script { BTCDepositAddressDeriver deriver = BTCDepositAddressDeriver( contractAddress ); + console.log("deriver", address(deriver)); // set validators' pubkeys and network prefix + console.log("SetSeed step 1"); vm.startBroadcast(); + console.log("SetSeed step 2"); + BTCDepositAddressDeriver.BitcoinNetwork btcNetwork = BTCDepositAddressDeriver.BitcoinNetwork(network); + console.log("SetSeed step 3"); deriver.setSeed( btcAddr1, btcAddr2, - BTCDepositAddressDeriver.BitcoinNetwork(network) + btcNetwork ); + console.log("SetSeed step 4"); vm.stopBroadcast(); } } diff --git a/src/AddressReaderWriter.sol b/src/AddressReaderWriter.sol new file mode 100644 index 0000000..a4a1336 --- /dev/null +++ b/src/AddressReaderWriter.sol @@ -0,0 +1,37 @@ +pragma solidity ^0.8.25; + +import {Script} from "forge-std/Script.sol"; +import {Tools} from "../src/Tools.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +contract AddressReaderWriter is Script { + function writeContractAddress( + string memory contractName, + address contractAddress + ) public { + string memory addressFileName = string.concat( + "./temp/", + contractName, + ".", + Strings.toString(block.chainid), + ".address" + ); + string memory addressStr = Strings.toHexString(contractAddress); + vm.writeFile(addressFileName, addressStr); + } + + function readContractAddress( + string memory contractName + ) public returns (address) { + string memory addressFileName = string.concat( + "./temp/", + contractName, + ".", + Strings.toString(block.chainid), + ".address" + ); + string memory contractAddressStr = vm.readLine(addressFileName); + address contractAddress = Tools.toAddress(contractAddressStr); + return contractAddress; + } +} diff --git a/src/BTCDepositAddressDeriver.sol b/src/BTCDepositAddressDeriver.sol index dcd0e55..a048a4d 100644 --- a/src/BTCDepositAddressDeriver.sol +++ b/src/BTCDepositAddressDeriver.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; +pragma solidity ^0.8.25; import {Deriver} from "./Deriver.sol"; import {Bech32m} from "./Bech32m.sol"; +import {console} from "forge-std/console.sol"; error SeedWasNotSetYet(); error UnsupportedBtcAddress(string btcAddress); @@ -50,7 +51,7 @@ contract BTCDepositAddressDeriver { string calldata _btcAddr2, BitcoinNetwork _network ) public virtual { - + console.log("setSeed step 1"); string memory _hrp = getNetworkPrefix(_network); networkHrp = _hrp; diff --git a/src/Tools.sol b/src/Tools.sol new file mode 100644 index 0000000..51632b3 --- /dev/null +++ b/src/Tools.sol @@ -0,0 +1,66 @@ +pragma solidity ^0.8.25; + +import {Script} from "forge-std/Script.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +library Tools { + // https://www.educative.io/answers/how-to-compare-two-strings-in-solidity + function areStringsEqual( + string memory str1, + string memory str2 + ) public pure returns (bool) { + return + keccak256(abi.encodePacked(str1)) == + keccak256(abi.encodePacked(str2)); + } + + // https://stackoverflow.com/questions/69551020/trying-to-convert-address-string-to-type-address-in-solidity + function fromHexChar(uint8 c) public pure returns (uint8) { + if (bytes1(c) >= bytes1("0") && bytes1(c) <= bytes1("9")) { + return c - uint8(bytes1("0")); + } + if (bytes1(c) >= bytes1("a") && bytes1(c) <= bytes1("f")) { + return 10 + c - uint8(bytes1("a")); + } + if (bytes1(c) >= bytes1("A") && bytes1(c) <= bytes1("F")) { + return 10 + c - uint8(bytes1("A")); + } + return 0; + } + + // https://stackoverflow.com/questions/69551020/trying-to-convert-address-string-to-type-address-in-solidity + function hexStringToAddress( + string memory s + ) public pure returns (bytes memory) { + bytes memory ss = bytes(s); + require(ss.length % 2 == 0); // length must be even + bytes memory r = new bytes(ss.length / 2); + for (uint i = 0; i < ss.length / 2; ++i) { + r[i] = bytes1( + fromHexChar(uint8(ss[2 * i])) * + 16 + + fromHexChar(uint8(ss[2 * i + 1])) + ); + } + + return r; + } + + // https://stackoverflow.com/questions/69551020/trying-to-convert-address-string-to-type-address-in-solidity + function toAddress(string memory s) public pure returns (address) { + bytes memory _bytes = hexStringToAddress(s); + require(_bytes.length >= 1 + 20, "toAddress_outOfBounds"); + address tempAddress; + + assembly { + tempAddress := div( + mload(add(add(_bytes, 0x20), 1)), + 0x1000000000000000000000000 + ) + } + + return tempAddress; + } + + +} diff --git a/test/BTCDepositAddressDeriver.t.sol b/test/BTCDepositAddressDeriver.t.sol index c7bc203..d83dd46 100644 --- a/test/BTCDepositAddressDeriver.t.sol +++ b/test/BTCDepositAddressDeriver.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.19; +import {console} from "forge-std/console.sol"; import {Test} from "forge-std/Test.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; @@ -112,4 +113,25 @@ contract BTCDepositAddressDeriverTest is Test { "tb1pz66m5qeqae7mlqjwwz3hhf8lfz05w53djxxxzzjy47m6hej6cg8s0zs83c" ); } + + function testGetBTCDepositAddress2() public { + deriver.setSeed( + "tb1p5z8wl5tu7m0d79vzqqsl9gu0x4fkjug857fusx4fl4kfgwh5j25spa7245", + "tb1pfusykjdt46ktwq03d20uqqf94uh9487344wr3q5v9szzsxnjdfks9apcjz", + BTCDepositAddressDeriver.BitcoinNetwork(0) + ); + + string memory btcAddress = deriver.getBTCDepositAddress( + 0x1EaCa1277BcDFa83E60658D8938B3D63cD3E63C1 + ); + console.log("btcAddress", btcAddress); + assertEq( + btcAddress, + "tb1phuqvamwdq7ynnydpc93h3sa9qhk9kntadg5vecgph38357jrlq5sqymks5" + ); + // assertEq( + // btcAddress, + // "tb1pz66m5qeqae7mlqjwwz3hhf8lfz05w53djxxxzzjy47m6hej6cg8s0zs83c" + // ); + } } From 06384d6fa0fbf93cb3262577d880eb875e69d31b Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Thu, 20 Jun 2024 03:51:10 +0300 Subject: [PATCH 04/10] fix scripts --- script/GetBtcAddr.s.sol | 48 +++++++++++++++++++++++++++++++++++++++++ script/GetBtcAddr.sol | 27 ----------------------- 2 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 script/GetBtcAddr.s.sol delete mode 100644 script/GetBtcAddr.sol diff --git a/script/GetBtcAddr.s.sol b/script/GetBtcAddr.s.sol new file mode 100644 index 0000000..1f80483 --- /dev/null +++ b/script/GetBtcAddr.s.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.25; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; +import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; +import {Tools} from "../src/Tools.sol"; +import {AddressReaderWriter} from "../src/AddressReaderWriter.sol"; + +contract GetBtcAddr is Script, AddressReaderWriter { + function run() external { + // get contract address + // if environmental variable is set then use its value + // otherwise try get value from the latest deployment + address contractAddress; + string memory contractAddressStr = vm.envOr( + "CONTRACT_ADDR", + string("") + ); + if (!Tools.areStringsEqual(contractAddressStr, "")) { + contractAddress = vm.envAddress("CONTRACT_ADDR"); + } else { + contractAddress = readContractAddress( + "BTCDepositAddressDeriver" + ); + } + console.log("contractAddress", contractAddress); + + address ethAddr = vm.envAddress("ETH_ADDR"); + console.log("ethAddr:", ethAddr); + + BTCDepositAddressDeriver deriver = BTCDepositAddressDeriver( + contractAddress + ); + string memory btcAddr = deriver.getBTCDepositAddress(ethAddr); + console.log("btcAddr:", btcAddr); + + string memory btcAddrFileName = vm.envOr( + "BTC_ADDR_FILE", + string("") + ); + if (!Tools.areStringsEqual(btcAddrFileName, "")) { + vm.writeFile(btcAddrFileName, btcAddr); + } + } +} diff --git a/script/GetBtcAddr.sol b/script/GetBtcAddr.sol deleted file mode 100644 index a046dde..0000000 --- a/script/GetBtcAddr.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.19; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; -import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; - -contract GetBtcAddr is Script { - function run() external { - address contractAddress = DevOpsTools.get_most_recent_deployment( - "BTCDepositAddressDeriver", - block.chainid - ); - console.log("contractAddress", contractAddress); - - address ethAddr = vm.envAddress("ETH_ADDR"); - console.log("ethAddr:", ethAddr); - - BTCDepositAddressDeriver deriver = BTCDepositAddressDeriver( - contractAddress - ); - string memory btcAddr = deriver.getBTCDepositAddress(ethAddr); - console.log("btcAddr:", btcAddr); - } -} From 9d6157f598ee96b59633ac42fd280a8dd64636b0 Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Thu, 20 Jun 2024 03:58:37 +0300 Subject: [PATCH 05/10] remove foundry-devops dependency --- .gitmodules | 3 --- lib/foundry-devops | 1 - script/GetBtcAddr.s.sol | 1 - script/SetSeed.s.sol | 1 - 4 files changed, 6 deletions(-) delete mode 160000 lib/foundry-devops diff --git a/.gitmodules b/.gitmodules index 6afefa7..c9a0fdd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std -[submodule "lib/foundry-devops"] - path = lib/foundry-devops - url = https://github.com/Cyfrin/foundry-devops [submodule "lib/elliptic-curve-solidity"] path = lib/elliptic-curve-solidity url = https://github.com/witnet/elliptic-curve-solidity diff --git a/lib/foundry-devops b/lib/foundry-devops deleted file mode 160000 index 5415faa..0000000 --- a/lib/foundry-devops +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5415faa72d362368cd5a044602c8c6a11bb497be diff --git a/script/GetBtcAddr.s.sol b/script/GetBtcAddr.s.sol index 1f80483..817c29f 100644 --- a/script/GetBtcAddr.s.sol +++ b/script/GetBtcAddr.s.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.25; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; import {Tools} from "../src/Tools.sol"; import {AddressReaderWriter} from "../src/AddressReaderWriter.sol"; diff --git a/script/SetSeed.s.sol b/script/SetSeed.s.sol index dc065b8..4570d70 100644 --- a/script/SetSeed.s.sol +++ b/script/SetSeed.s.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.25; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; import {Tools} from "../src/Tools.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; From 518356051c4108f83e5e42baadb27f0a72b93ba4 Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Thu, 20 Jun 2024 04:55:14 +0300 Subject: [PATCH 06/10] add Makefile --- Makefile | 78 ++++++++++++++++++++++++++++++++ script/SetSeed.s.sol | 4 -- src/BTCDepositAddressDeriver.sol | 1 - 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index e69de29..7bd716e 100644 --- a/Makefile +++ b/Makefile @@ -0,0 +1,78 @@ +# https://stackoverflow.com/questions/5377297/how-to-manually-call-another-target-from-a-make-target +# Determine this makefile's path. +# Be sure to place this BEFORE `include` directives, if any. +THIS_FILE := $(lastword $(MAKEFILE_LIST)) + +# Keys are generated determistically in anvil so they are the same during different runs +# as long the seed is the same. +# Some keys and addresses are copy-pasted in file `env-anvil`. +# https://unix.stackexchange.com/questions/235223/makefile-include-env-file +include env-anvil +export $(shell sed 's/=.*//' env-anvil) + +RED := $(shell tput -Txterm setaf 1) +GREEN := $(shell tput -Txterm setaf 2) +YELLOW := $(shell tput -Txterm setaf 3) +WHITE := $(shell tput -Txterm setaf 7) +CYAN := $(shell tput -Txterm setaf 6) +RESET := $(shell tput -Txterm sgr0) + +.PHONY: build +build: + forge build + +.PHONY: test +test: + forge test + +.PHONY: start-anvil +start-anvil: + anvil + +.PHONY: deploy-anvil +deploy-anvil: + mkdir -p temp + forge script \ + script/Deploy.s.sol:Deploy \ + --fork-url ${ANVIL_RPC_URL} \ + --broadcast \ + --private-key=${ETH_PRIVKEY_0_ANVIL} + +.PHONY: set-sample-seed +set-sample-seed: + BTC_ADDR1=tb1p5z8wl5tu7m0d79vzqqsl9gu0x4fkjug857fusx4fl4kfgwh5j25spa7245 \ + BTC_ADDR2=tb1pfusykjdt46ktwq03d20uqqf94uh9487344wr3q5v9szzsxnjdfks9apcjz \ + BTC_NETWORK=0 \ + forge script \ + -vvv \ + script/SetSeed.s.sol:SetSeed \ + --fork-url ${ANVIL_RPC_URL} \ + --broadcast \ + --private-key=${ETH_PRIVKEY_0_ANVIL} + +.PHONY: get-sample-btc-address +get-sample-btc-address: + ETH_ADDR=${ETH_ADDR_1_ANVIL} \ + BTC_ADDR_FILE=./temp/btc.address \ + forge script -vvv \ + script/GetBtcAddr.s.sol:GetBtcAddr \ + --fork-url ${ANVIL_RPC_URL} + +.PHONY: test-sample-flow +test-sample-flow: + @$(MAKE) -f $(THIS_FILE) deploy-anvil + @$(MAKE) -f $(THIS_FILE) set-sample-seed + @$(MAKE) -f $(THIS_FILE) get-sample-btc-address + if [ `cat ./temp/btc.address` = "1tb1pxt2g6ltjvle3wupwzlg9yuqw5rsswvvjg20eegq46l3yx6ekc2psh78607" ]; \ + then \ + echo "${GREEN}OK${RESET}"; \ + exit 0; \ + else \ + echo "${RED}ERROR${RESET}"; \ + exit 1; \ + fi + +.PHONY: clean +clean: + rm -rf cache + rm -rf out \ No newline at end of file diff --git a/script/SetSeed.s.sol b/script/SetSeed.s.sol index 4570d70..37baf7a 100644 --- a/script/SetSeed.s.sol +++ b/script/SetSeed.s.sol @@ -48,17 +48,13 @@ contract SetSeed is Script, AddressReaderWriter { console.log("deriver", address(deriver)); // set validators' pubkeys and network prefix - console.log("SetSeed step 1"); vm.startBroadcast(); - console.log("SetSeed step 2"); BTCDepositAddressDeriver.BitcoinNetwork btcNetwork = BTCDepositAddressDeriver.BitcoinNetwork(network); - console.log("SetSeed step 3"); deriver.setSeed( btcAddr1, btcAddr2, btcNetwork ); - console.log("SetSeed step 4"); vm.stopBroadcast(); } } diff --git a/src/BTCDepositAddressDeriver.sol b/src/BTCDepositAddressDeriver.sol index a048a4d..1f02e4d 100644 --- a/src/BTCDepositAddressDeriver.sol +++ b/src/BTCDepositAddressDeriver.sol @@ -51,7 +51,6 @@ contract BTCDepositAddressDeriver { string calldata _btcAddr2, BitcoinNetwork _network ) public virtual { - console.log("setSeed step 1"); string memory _hrp = getNetworkPrefix(_network); networkHrp = _hrp; From 89d8e37bb7d9aebf611fdec9a4158e8c42a525d0 Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Thu, 20 Jun 2024 05:20:33 +0300 Subject: [PATCH 07/10] add help to Makefile --- Makefile | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 7bd716e..c442bca 100644 --- a/Makefile +++ b/Makefile @@ -17,20 +17,23 @@ WHITE := $(shell tput -Txterm setaf 7) CYAN := $(shell tput -Txterm setaf 6) RESET := $(shell tput -Txterm sgr0) +## Build: .PHONY: build -build: +build: ## Build library. forge build -.PHONY: test -test: - forge test +.PHONY: clean +clean: ## Clean tempory files. Sometimes forge incorrectly updates its cache. So if there are some strange errors run `make clean`. + rm -rf cache + rm -rf out +## Work with local anvil: .PHONY: start-anvil -start-anvil: +start-anvil: ## Starts anvil with default parameters. anvil -.PHONY: deploy-anvil -deploy-anvil: +.PHONY: deploy-on-anvil +deploy-on-anvil: ## Deploy BTCDepositAddressDeriver smart contract on local anvil blockchain. mkdir -p temp forge script \ script/Deploy.s.sol:Deploy \ @@ -39,7 +42,7 @@ deploy-anvil: --private-key=${ETH_PRIVKEY_0_ANVIL} .PHONY: set-sample-seed -set-sample-seed: +set-sample-seed: ## Set sample seed on previously deployed BTCDepositAddressDeriver. BTC_ADDR1=tb1p5z8wl5tu7m0d79vzqqsl9gu0x4fkjug857fusx4fl4kfgwh5j25spa7245 \ BTC_ADDR2=tb1pfusykjdt46ktwq03d20uqqf94uh9487344wr3q5v9szzsxnjdfks9apcjz \ BTC_NETWORK=0 \ @@ -51,19 +54,24 @@ set-sample-seed: --private-key=${ETH_PRIVKEY_0_ANVIL} .PHONY: get-sample-btc-address -get-sample-btc-address: +get-sample-btc-address: ## Calculates bitcoin address from the sample ethereum address using previously deployed BTCDepositAddressDeriver. ETH_ADDR=${ETH_ADDR_1_ANVIL} \ BTC_ADDR_FILE=./temp/btc.address \ forge script -vvv \ script/GetBtcAddr.s.sol:GetBtcAddr \ --fork-url ${ANVIL_RPC_URL} +## Test: +.PHONY: test +test: ## Run unit tests. + forge test + .PHONY: test-sample-flow -test-sample-flow: - @$(MAKE) -f $(THIS_FILE) deploy-anvil +test-sample-flow: ## Run integration test that deploys smart contract, set seed and calculate sample bitcoin address. It requires anvil to be running. + @$(MAKE) -f $(THIS_FILE) deploy-on-anvil @$(MAKE) -f $(THIS_FILE) set-sample-seed @$(MAKE) -f $(THIS_FILE) get-sample-btc-address - if [ `cat ./temp/btc.address` = "1tb1pxt2g6ltjvle3wupwzlg9yuqw5rsswvvjg20eegq46l3yx6ekc2psh78607" ]; \ + if [ `cat ./temp/btc.address` = "tb1pxt2g6ltjvle3wupwzlg9yuqw5rsswvvjg20eegq46l3yx6ekc2psh78607" ]; \ then \ echo "${GREEN}OK${RESET}"; \ exit 0; \ @@ -72,7 +80,18 @@ test-sample-flow: exit 1; \ fi -.PHONY: clean -clean: - rm -rf cache - rm -rf out \ No newline at end of file +.PHONY: test-all +test-all: test test-sample-flow ## Run unit and integrations tests. It requires anvil to be running. + +## Help: +.PHONY: help +help: ## Show this help + @echo '' + @echo 'Usage:' + @echo ' ${YELLOW}make${RESET} ${GREEN}${RESET}' + @echo '' + @echo 'Targets:' + @awk 'BEGIN {FS = ":.*?## "} { \ + if (/^[a-zA-Z0-9_-]+:.*?##.*$$/) {printf " ${YELLOW}%-25s${GREEN}%s${RESET}\n", $$1, $$2} \ + else if (/^## .*$$/) {printf " ${CYAN}%s${RESET}\n", substr($$1,4)} \ + }' $(MAKEFILE_LIST) \ No newline at end of file From 436e2feb714855837c3b7a37084e5e82ce085e6e Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Thu, 20 Jun 2024 05:24:26 +0300 Subject: [PATCH 08/10] make help the default target in Makefile --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index c442bca..e884e3d 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,9 @@ WHITE := $(shell tput -Txterm setaf 7) CYAN := $(shell tput -Txterm setaf 6) RESET := $(shell tput -Txterm sgr0) +.PHONY: default +default: help + ## Build: .PHONY: build build: ## Build library. From 0b68d3807b9214154908e69c648515fd8d189013 Mon Sep 17 00:00:00 2001 From: Mykola Sakhno Date: Thu, 20 Jun 2024 05:28:13 +0300 Subject: [PATCH 09/10] refactor --- .../AddressReaderWriter.s.sol | 0 script/Deploy.s.sol | 2 +- script/GetBtcAddr.s.sol | 2 +- script/SetSeed.s.sol | 3 +-- src/Bech32m.sol | 2 +- src/Deriver.sol | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) rename src/AddressReaderWriter.sol => script/AddressReaderWriter.s.sol (100%) diff --git a/src/AddressReaderWriter.sol b/script/AddressReaderWriter.s.sol similarity index 100% rename from src/AddressReaderWriter.sol rename to script/AddressReaderWriter.s.sol diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 7141aa6..26b8003 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -7,7 +7,7 @@ import {console} from "forge-std/console.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; import {Tools} from "../src/Tools.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {AddressReaderWriter} from "../src/AddressReaderWriter.sol"; +import {AddressReaderWriter} from "./AddressReaderWriter.s.sol"; contract Deploy is Script, AddressReaderWriter { function run() external returns (BTCDepositAddressDeriver) { diff --git a/script/GetBtcAddr.s.sol b/script/GetBtcAddr.s.sol index 817c29f..27043df 100644 --- a/script/GetBtcAddr.s.sol +++ b/script/GetBtcAddr.s.sol @@ -6,7 +6,7 @@ import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; import {Tools} from "../src/Tools.sol"; -import {AddressReaderWriter} from "../src/AddressReaderWriter.sol"; +import {AddressReaderWriter} from "./AddressReaderWriter.s.sol"; contract GetBtcAddr is Script, AddressReaderWriter { function run() external { diff --git a/script/SetSeed.s.sol b/script/SetSeed.s.sol index 37baf7a..2431f11 100644 --- a/script/SetSeed.s.sol +++ b/script/SetSeed.s.sol @@ -7,7 +7,7 @@ import {console} from "forge-std/console.sol"; import {BTCDepositAddressDeriver} from "../src/BTCDepositAddressDeriver.sol"; import {Tools} from "../src/Tools.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {AddressReaderWriter} from "../src/AddressReaderWriter.sol"; +import {AddressReaderWriter} from "./AddressReaderWriter.s.sol"; import {console} from "forge-std/console.sol"; contract SetSeed is Script, AddressReaderWriter { @@ -45,7 +45,6 @@ contract SetSeed is Script, AddressReaderWriter { BTCDepositAddressDeriver deriver = BTCDepositAddressDeriver( contractAddress ); - console.log("deriver", address(deriver)); // set validators' pubkeys and network prefix vm.startBroadcast(); diff --git a/src/Bech32m.sol b/src/Bech32m.sol index dea3695..f046087 100644 --- a/src/Bech32m.sol +++ b/src/Bech32m.sol @@ -2,7 +2,7 @@ // https://github.com/gregdhill/bech32-sol/blob/master/src/Bech32.sol // based on https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki // https://github.com/sipa/bech32/blob/master/ref/python/segwit_addr.py -pragma solidity ^0.8.18; +pragma solidity ^0.8.25; error EncodingIsUnknown(); diff --git a/src/Deriver.sol b/src/Deriver.sol index 2c6500d..f819110 100644 --- a/src/Deriver.sol +++ b/src/Deriver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; +pragma solidity ^0.8.25; import {EllipticCurve} from "../lib/elliptic-curve-solidity/contracts/EllipticCurve.sol"; From 7166a8d54c7b27a7ee9e2d1738cbd9ca13438b73 Mon Sep 17 00:00:00 2001 From: Viacheslav Zhygulin Date: Thu, 20 Jun 2024 11:30:55 +0300 Subject: [PATCH 10/10] make tests pass --- test/BTCDepositAddressDeriver.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/BTCDepositAddressDeriver.t.sol b/test/BTCDepositAddressDeriver.t.sol index 1ceb139..462e593 100644 --- a/test/BTCDepositAddressDeriver.t.sol +++ b/test/BTCDepositAddressDeriver.t.sol @@ -118,7 +118,7 @@ contract BTCDepositAddressDeriverTest is Test { deriver.setSeed( "tb1p5z8wl5tu7m0d79vzqqsl9gu0x4fkjug857fusx4fl4kfgwh5j25spa7245", "tb1pfusykjdt46ktwq03d20uqqf94uh9487344wr3q5v9szzsxnjdfks9apcjz", - BTCDepositAddressDeriver.BitcoinNetwork(0) + 0 ); string memory btcAddress = deriver.getBTCDepositAddress(